diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6584615..221d04f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,7 +22,7 @@ jobs: strategy: matrix: - node-version: [20.x, 22.x] + node-version: [20.x, 22.x, 24.x] steps: - uses: actions/checkout@v3 diff --git a/lib/nano.js b/lib/nano.js index f21389a..ad5dfda 100644 --- a/lib/nano.js +++ b/lib/nano.js @@ -56,7 +56,7 @@ module.exports = exports = function dbScope (cfg) { cfg.plainURL = `${cfg.parsedURL.origin}${cfg.parsedURL.pathname}` cfg.headers = cfg.headers || {} if (cfg.parsedURL.username && cfg.parsedURL.password) { - cfg.headers.Authorization = 'Basic ' + Buffer.from(`${cfg.parsedURL.username}:${cfg.parsedURL.password}`).toString('base64') + cfg.headers.Authorization = 'Basic ' + Buffer.from(`${decodeURIComponent(cfg.parsedURL.username)}:${decodeURIComponent(cfg.parsedURL.password)}`).toString('base64') } // look for agentOptions diff --git a/package-lock.json b/package-lock.json index 7987105..d5fbaac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,36 +1,36 @@ { "name": "nano", - "version": "11.0.3", + "version": "11.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nano", - "version": "11.0.3", + "version": "11.0.4", "license": "Apache-2.0", "devDependencies": { - "@types/node": "^24.4.0", - "typescript": "^5.9.2", - "undici": "^7.16.0" + "@types/node": "^25.2.1", + "typescript": "^5.9.3", + "undici": "^7.20.0" }, "engines": { "node": ">=20.0" } }, "node_modules/@types/node": { - "version": "24.4.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.4.0.tgz", - "integrity": "sha512-gUuVEAK4/u6F9wRLznPUU4WGUacSEBDPoC2TrBkw3GAnOLHBL45QdfHOXp1kJ4ypBGLxTOB+t7NJLpKoC3gznQ==", + "version": "25.2.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.1.tgz", + "integrity": "sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.11.0" + "undici-types": "~7.16.0" } }, "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -42,9 +42,9 @@ } }, "node_modules/undici": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", - "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.20.0.tgz", + "integrity": "sha512-MJZrkjyd7DeC+uPZh+5/YaMDxFiiEEaDgbUSVMXayofAkDWF1088CDo+2RPg7B1BuS1qf1vgNE7xqwPxE0DuSQ==", "dev": true, "license": "MIT", "engines": { @@ -52,9 +52,9 @@ } }, "node_modules/undici-types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.11.0.tgz", - "integrity": "sha512-kt1ZriHTi7MU+Z/r9DOdAI3ONdaR3M3csEaRc6ewa4f4dTvX4cQCbJ4NkEn0ohE4hHtq85+PhPSTY+pO/1PwgA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, "license": "MIT" } diff --git a/package.json b/package.json index 483d1f8..6048c3e 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "license": "Apache-2.0", "homepage": "http://github.com/apache/couchdb-nano", "repository": "http://github.com/apache/couchdb-nano", - "version": "11.0.3", + "version": "11.0.4", "author": "Apache CouchDB (http://couchdb.apache.org)", "keywords": [ "couchdb", @@ -19,9 +19,9 @@ "dependencies": { }, "devDependencies": { - "undici": "^7.16.0", - "@types/node": "^24.4.0", - "typescript": "^5.9.2" + "undici": "^7.20.0", + "@types/node": "^25.2.1", + "typescript": "^5.9.3" }, "scripts": { "test": "tsc lib/nano.d.ts && node --test ./test/*.test.js" diff --git a/test/nano.basicauth.test.js b/test/nano.basicauth.test.js new file mode 100644 index 0000000..1031f35 --- /dev/null +++ b/test/nano.basicauth.test.js @@ -0,0 +1,38 @@ +// Licensed under the Apache License, Version 2.0 (the 'License'); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +const test = require('node:test') +const assert = require('node:assert/strict') +const COUCH_URL="http://admin[:admin]@127.0.0.1:5984" +const { mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') +const Nano = require('..') +const nano = Nano({ url: COUCH_URL }) +const pkg = require('../package.json') + +test('should handle special characters in username & password', async () => { + // mocks + const auth = 'Basic ' + Buffer.from('admin[:admin]').toString('base64') + mockPool + .intercept({ + path: '/_all_dbs', + headers: { + 'authorization': auth, + 'content-type': 'application/json' + } + }) + .reply(200, ['a'], JSON_HEADERS) + + // test POST /_session + const q = await nano.db.list() + assert.deepEqual(q, ['a']) + mockAgent.assertNoPendingInterceptors() +})