You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-12-25 00:40:59 +03:00
fix: createClient url+tls invariant violation check (#2835)
This commit is contained in:
@@ -64,7 +64,8 @@ describe('Client', () => {
|
||||
const expected: RedisClientOptions = {
|
||||
socket: {
|
||||
host: 'localhost',
|
||||
port: 6379
|
||||
port: 6379,
|
||||
tls: false
|
||||
},
|
||||
username: 'user',
|
||||
password: 'secret',
|
||||
@@ -161,12 +162,58 @@ describe('Client', () => {
|
||||
{
|
||||
socket: {
|
||||
host: 'localhost',
|
||||
tls: false
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseOptions', () => {
|
||||
it('should throw error if tls socket option is set to true and the url protocol is "redis:"', () => {
|
||||
assert.throws(
|
||||
() => RedisClient.parseOptions({
|
||||
url: 'redis://localhost',
|
||||
socket: {
|
||||
tls: true
|
||||
}
|
||||
}),
|
||||
TypeError
|
||||
);
|
||||
});
|
||||
it('should throw error if tls socket option is set to false and the url protocol is "rediss:"', () => {
|
||||
assert.throws(
|
||||
() => RedisClient.parseOptions({
|
||||
url: 'rediss://localhost',
|
||||
socket: {
|
||||
tls: false
|
||||
}
|
||||
}),
|
||||
TypeError
|
||||
);
|
||||
});
|
||||
it('should not throw when tls socket option and url protocol matches"', () => {
|
||||
assert.equal(
|
||||
RedisClient.parseOptions({
|
||||
url: 'rediss://localhost',
|
||||
socket: {
|
||||
tls: true
|
||||
}
|
||||
}).socket.tls,
|
||||
true
|
||||
);
|
||||
assert.equal(
|
||||
RedisClient.parseOptions({
|
||||
url: 'redis://localhost',
|
||||
socket: {
|
||||
tls: false
|
||||
}
|
||||
}).socket.tls,
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('authentication', () => {
|
||||
testUtils.testWithClient('Client should be authenticated', async client => {
|
||||
assert.equal(
|
||||
|
||||
@@ -315,21 +315,45 @@ export default class RedisClient<
|
||||
return RedisClient.factory(options)(options);
|
||||
}
|
||||
|
||||
static parseURL(url: string): RedisClientOptions {
|
||||
static parseOptions<O extends RedisClientOptions>(options: O): O {
|
||||
if (options?.url) {
|
||||
const parsed = RedisClient.parseURL(options.url);
|
||||
if (options.socket) {
|
||||
if (options.socket.tls !== undefined && options.socket.tls !== parsed.socket.tls) {
|
||||
throw new TypeError(`tls socket option is set to ${options.socket.tls} which is mismatch with protocol or the URL ${options.url} passed`)
|
||||
}
|
||||
parsed.socket = Object.assign(options.socket, parsed.socket);
|
||||
}
|
||||
|
||||
Object.assign(options, parsed);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
static parseURL(url: string): RedisClientOptions & {
|
||||
socket: Exclude<RedisClientOptions['socket'], undefined> & {
|
||||
tls: boolean
|
||||
}
|
||||
} {
|
||||
// https://www.iana.org/assignments/uri-schemes/prov/redis
|
||||
const { hostname, port, protocol, username, password, pathname } = new URL(url),
|
||||
parsed: RedisClientOptions = {
|
||||
parsed: RedisClientOptions & {
|
||||
socket: Exclude<RedisClientOptions['socket'], undefined> & {
|
||||
tls: boolean
|
||||
}
|
||||
} = {
|
||||
socket: {
|
||||
host: hostname
|
||||
host: hostname,
|
||||
tls: false
|
||||
}
|
||||
};
|
||||
|
||||
if (protocol === 'rediss:') {
|
||||
parsed!.socket!.tls = true;
|
||||
} else if (protocol !== 'redis:') {
|
||||
if (protocol !== 'redis:' && protocol !== 'rediss:') {
|
||||
throw new TypeError('Invalid protocol');
|
||||
}
|
||||
|
||||
parsed.socket.tls = protocol === 'rediss:';
|
||||
|
||||
if (port) {
|
||||
(parsed.socket as TcpSocketConnectOpts).port = Number(port);
|
||||
}
|
||||
@@ -464,15 +488,6 @@ export default class RedisClient<
|
||||
};
|
||||
}
|
||||
|
||||
if (options?.url) {
|
||||
const parsed = RedisClient.parseURL(options.url);
|
||||
if (options.socket) {
|
||||
parsed.socket = Object.assign(options.socket, parsed.socket);
|
||||
}
|
||||
|
||||
Object.assign(options, parsed);
|
||||
}
|
||||
|
||||
if (options?.database) {
|
||||
this._self.#selectedDB = options.database;
|
||||
}
|
||||
@@ -481,6 +496,10 @@ export default class RedisClient<
|
||||
this._commandOptions = options.commandOptions;
|
||||
}
|
||||
|
||||
if (options) {
|
||||
return RedisClient.parseOptions(options);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user