Skip to content

Commit 01e0fba

Browse files
committed
createClient url+tls invariant violation check
1 parent 28d719d commit 01e0fba

File tree

2 files changed

+82
-16
lines changed

2 files changed

+82
-16
lines changed

packages/client/lib/client/index.spec.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ describe('Client', () => {
6464
const expected: RedisClientOptions = {
6565
socket: {
6666
host: 'localhost',
67-
port: 6379
67+
port: 6379,
68+
tls: false
6869
},
6970
username: 'user',
7071
password: 'secret',
@@ -161,12 +162,58 @@ describe('Client', () => {
161162
{
162163
socket: {
163164
host: 'localhost',
165+
tls: false
164166
}
165167
}
166168
);
167169
});
168170
});
169171

172+
describe('parseOptions', () => {
173+
it('should throw error if tls socket option is set to true and the url protocol is "redis:"', () => {
174+
assert.throws(
175+
() => RedisClient.parseOptions({
176+
url: 'redis://localhost',
177+
socket: {
178+
tls: true
179+
}
180+
}),
181+
TypeError
182+
);
183+
});
184+
it('should throw error if tls socket option is set to false and the url protocol is "rediss:"', () => {
185+
assert.throws(
186+
() => RedisClient.parseOptions({
187+
url: 'rediss://localhost',
188+
socket: {
189+
tls: false
190+
}
191+
}),
192+
TypeError
193+
);
194+
});
195+
it('should not throw when tls socket option and url protocol matches"', () => {
196+
assert.equal(
197+
RedisClient.parseOptions({
198+
url: 'rediss://localhost',
199+
socket: {
200+
tls: true
201+
}
202+
}).socket.tls,
203+
true
204+
);
205+
assert.equal(
206+
RedisClient.parseOptions({
207+
url: 'redis://localhost',
208+
socket: {
209+
tls: false
210+
}
211+
}).socket.tls,
212+
false
213+
);
214+
});
215+
});
216+
170217
describe('authentication', () => {
171218
testUtils.testWithClient('Client should be authenticated', async client => {
172219
assert.equal(

packages/client/lib/client/index.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -315,21 +315,45 @@ export default class RedisClient<
315315
return RedisClient.factory(options)(options);
316316
}
317317

318-
static parseURL(url: string): RedisClientOptions {
318+
static parseOptions<O extends RedisClientOptions>(options: O): O {
319+
if (options?.url) {
320+
const parsed = RedisClient.parseURL(options.url);
321+
if (options.socket) {
322+
if (options.socket.tls !== undefined && options.socket.tls !== parsed.socket.tls) {
323+
throw new TypeError(`tls socket option is set to ${options.socket.tls} which is mismatch with protocol or the URL ${options.url} passed`)
324+
}
325+
parsed.socket = Object.assign(options.socket, parsed.socket);
326+
}
327+
328+
Object.assign(options, parsed);
329+
}
330+
return options;
331+
}
332+
333+
static parseURL(url: string): RedisClientOptions & {
334+
socket: Exclude<RedisClientOptions['socket'], undefined> & {
335+
tls: boolean
336+
}
337+
} {
319338
// https://www.iana.org/assignments/uri-schemes/prov/redis
320339
const { hostname, port, protocol, username, password, pathname } = new URL(url),
321-
parsed: RedisClientOptions = {
340+
parsed: RedisClientOptions & {
341+
socket: Exclude<RedisClientOptions['socket'], undefined> & {
342+
tls: boolean
343+
}
344+
} = {
322345
socket: {
323-
host: hostname
346+
host: hostname,
347+
tls: false
324348
}
325349
};
326350

327-
if (protocol === 'rediss:') {
328-
parsed!.socket!.tls = true;
329-
} else if (protocol !== 'redis:') {
351+
if (protocol !== 'redis:' && protocol !== 'rediss:') {
330352
throw new TypeError('Invalid protocol');
331353
}
332354

355+
parsed.socket.tls = protocol === 'rediss:';
356+
333357
if (port) {
334358
(parsed.socket as TcpSocketConnectOpts).port = Number(port);
335359
}
@@ -464,15 +488,6 @@ export default class RedisClient<
464488
};
465489
}
466490

467-
if (options?.url) {
468-
const parsed = RedisClient.parseURL(options.url);
469-
if (options.socket) {
470-
parsed.socket = Object.assign(options.socket, parsed.socket);
471-
}
472-
473-
Object.assign(options, parsed);
474-
}
475-
476491
if (options?.database) {
477492
this._self.#selectedDB = options.database;
478493
}
@@ -481,6 +496,10 @@ export default class RedisClient<
481496
this._commandOptions = options.commandOptions;
482497
}
483498

499+
if (options) {
500+
return RedisClient.parseOptions(options);
501+
}
502+
484503
return options;
485504
}
486505

0 commit comments

Comments
 (0)