Skip to content

Commit

Permalink
feat: support username in URI (#1284)
Browse files Browse the repository at this point in the history
  • Loading branch information
luin authored Feb 5, 2021
1 parent 0b001e0 commit cbc5421
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 6 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ You can also specify connection options as a [`redis://` URL](http://www.iana.or
```javascript
// Connect to 127.0.0.1:6380, db 4, using password "authpassword":
new Redis("redis://:[email protected]:6380/4");

// Username can also be passed via URI.
// It's worth to noticing that for compatibility reasons `allowUsernameInURI`
// need to be provided, otherwise the username part will be ignored.
new Redis(
"redis://username:[email protected]:6380/4?allowUsernameInURI=true"
);
```

See [API Documentation](API.md#new_Redis) for all available options.
Expand Down
15 changes: 12 additions & 3 deletions lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,19 @@ export function parseURL(url) {
parsed = urllibParse(url, true, true);
}

const options = parsed.query || {};
const allowUsernameInURI =
options.allowUsernameInURI && options.allowUsernameInURI !== "false";
delete options.allowUsernameInURI;

const result: any = {};
if (parsed.auth) {
const index = parsed.auth.indexOf(":")
result.password = index === -1 ? '' : parsed.auth.slice(index + 1)
const index = parsed.auth.indexOf(":");
if (allowUsernameInURI) {
result.username =
index === -1 ? parsed.auth : parsed.auth.slice(0, index);
}
result.password = index === -1 ? "" : parsed.auth.slice(index + 1);
}
if (parsed.pathname) {
if (parsed.protocol === "redis:" || parsed.protocol === "rediss:") {
Expand All @@ -275,7 +284,7 @@ export function parseURL(url) {
if (parsed.port) {
result.port = parsed.port;
}
defaults(result, parsed.query);
defaults(result, options);

return result;
}
Expand Down
19 changes: 19 additions & 0 deletions test/functional/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,25 @@ describe("auth", function () {
redis = new Redis({ port: 17379, username, password });
});

it("should handle auth with Redis URL string with username and password (Redis >=6) (redis://foo:[email protected]/) correctly", function (done) {
let username = "user";
let password = "pass";
let redis;
new MockServer(17379, function (argv) {
if (
argv[0] === "auth" &&
argv[1] === username &&
argv[2] === password
) {
redis.disconnect();
done();
}
});
redis = new Redis(
`redis://user:pass@localhost:17379/?allowUsernameInURI=true`
);
});

it('should not emit "error" when the Redis >=6 server doesn\'t need auth', function (done) {
new MockServer(17379, function (argv) {
if (argv[0] === "auth" && argv[1] === "pass") {
Expand Down
57 changes: 54 additions & 3 deletions test/unit/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,7 @@ describe("utils", function () {
password: "pass:word",
key: "value",
});
expect(
utils.parseURL("redis://[email protected]:6380/4?key=value")
).to.eql({
expect(utils.parseURL("redis://[email protected]:6380/4?key=value")).to.eql({
host: "127.0.0.1",
port: "6380",
db: "4",
Expand All @@ -226,6 +224,59 @@ describe("utils", function () {
key: "value",
});
});

it("supports allowUsernameInURI", function () {
expect(
utils.parseURL(
"redis://user:[email protected]:6380/4?allowUsernameInURI=true"
)
).to.eql({
host: "127.0.0.1",
port: "6380",
db: "4",
username: "user",
password: "pass",
});
expect(
utils.parseURL(
"redis://user:[email protected]:6380/4?allowUsernameInURI=false"
)
).to.eql({
host: "127.0.0.1",
port: "6380",
db: "4",
password: "pass",
});
expect(
utils.parseURL(
"redis://user:pass:[email protected]:6380/4?key=value&allowUsernameInURI=true"
)
).to.eql({
host: "127.0.0.1",
port: "6380",
db: "4",
username: "user",
password: "pass:word",
key: "value",
});
expect(
utils.parseURL(
"redis://[email protected]:6380/4?key=value&allowUsernameInURI=true"
)
).to.eql({
host: "127.0.0.1",
port: "6380",
db: "4",
username: "user",
password: "",
key: "value",
});
expect(
utils.parseURL("redis://127.0.0.1/?allowUsernameInURI=true")
).to.eql({
host: "127.0.0.1",
});
});
});

describe(".sample", function () {
Expand Down

0 comments on commit cbc5421

Please sign in to comment.