This is an automated email from the ASF dual-hosted git repository.
glynnbird pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb-nano.git
The following commit(s) were added to refs/heads/main by this push:
new c757679 Fix basicauth for credentials requiring percent encoding
(#364)
c757679 is described below
commit c757679a1627b224f2bb338ba1ad1ea0efd616a3
Author: Glynn Bird <[email protected]>
AuthorDate: Fri Feb 6 12:47:54 2026 +0000
Fix basicauth for credentials requiring percent encoding (#364)
* ensure that username and password returned from new URL are decoded
before use
* tests working
* added node 24 to the testing matrix
* 11.0.4 + dependency bump
---------
Co-authored-by: Glynn Bird <[email protected]>
---
.github/workflows/ci.yaml | 2 +-
lib/nano.js | 2 +-
package-lock.json | 36 ++++++++++++++++++------------------
package.json | 8 ++++----
test/nano.basicauth.test.js | 38 ++++++++++++++++++++++++++++++++++++++
5 files changed, 62 insertions(+), 24 deletions(-)
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 <[email protected]>
(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()
+})