You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-10 11:43:01 +03:00
Auth before select database (#1679)
* Auth before select database * fix #1681 Co-authored-by: leibale <leibale1998@gmail.com>
This commit is contained in:
@@ -119,6 +119,18 @@ describe('Client', () => {
|
|||||||
|
|
||||||
assert.equal(client.isOpen, false);
|
assert.equal(client.isOpen, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itWithClient(TestRedisServers.PASSWORD, 'should execute AUTH before SELECT', async client => {
|
||||||
|
assert.equal(
|
||||||
|
(await client.clientInfo()).db,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}, {
|
||||||
|
minimumRedisVersion: [6, 2],
|
||||||
|
clientOptions: {
|
||||||
|
database: 2
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('legacyMode', () => {
|
describe('legacyMode', () => {
|
||||||
|
@@ -177,24 +177,44 @@ export default class RedisClient<M extends RedisModules, S extends RedisScripts>
|
|||||||
|
|
||||||
#initiateSocket(): RedisSocket {
|
#initiateSocket(): RedisSocket {
|
||||||
const socketInitiator = async (): Promise<void> => {
|
const socketInitiator = async (): Promise<void> => {
|
||||||
const v4Commands = this.#options?.legacyMode ? this.#v4 : this,
|
const promises = [];
|
||||||
promises = [];
|
|
||||||
|
|
||||||
if (this.#selectedDB !== 0) {
|
if (this.#selectedDB !== 0) {
|
||||||
promises.push(v4Commands.select(RedisClient.commandOptions({ asap: true }), this.#selectedDB));
|
promises.push(
|
||||||
|
this.#queue.addCommand(
|
||||||
|
['SELECT', this.#selectedDB.toString()],
|
||||||
|
{ asap: true }
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.#options?.readonly) {
|
if (this.#options?.readonly) {
|
||||||
promises.push(v4Commands.readonly(RedisClient.commandOptions({ asap: true })));
|
promises.push(
|
||||||
|
this.#queue.addCommand(
|
||||||
|
COMMANDS.READONLY.transformArguments(),
|
||||||
|
{ asap: true }
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.#options?.username || this.#options?.password) {
|
if (this.#options?.username || this.#options?.password) {
|
||||||
promises.push(v4Commands.auth(RedisClient.commandOptions({ asap: true }), this.#options));
|
promises.push(
|
||||||
|
this.#queue.addCommand(
|
||||||
|
COMMANDS.AUTH.transformArguments({
|
||||||
|
username: this.#options.username,
|
||||||
|
password: this.#options.password ?? ''
|
||||||
|
}),
|
||||||
|
{ asap: true }
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resubscribePromise = this.#queue.resubscribe();
|
const resubscribePromise = this.#queue.resubscribe();
|
||||||
if (resubscribePromise) {
|
if (resubscribePromise) {
|
||||||
promises.push(resubscribePromise);
|
promises.push(resubscribePromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (promises.length) {
|
||||||
this.#tick();
|
this.#tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,7 +430,7 @@ export default class RedisClient<M extends RedisModules, S extends RedisScripts>
|
|||||||
quit = this.QUIT;
|
quit = this.QUIT;
|
||||||
|
|
||||||
#tick(): void {
|
#tick(): void {
|
||||||
if (!this.#socket.isSocketExists) {
|
if (!this.#socket.isSocketExists || this.#socket.writableNeedDrain) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,6 +76,14 @@ export default class RedisSocket extends EventEmitter {
|
|||||||
return !!this.#socket;
|
return !!this.#socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `writable.writableNeedDrain` was added in v15.2.0 and therefore can't be used
|
||||||
|
// https://nodejs.org/api/stream.html#stream_writable_writableneeddrain
|
||||||
|
#writableNeedDrain = false;
|
||||||
|
|
||||||
|
get writableNeedDrain(): boolean {
|
||||||
|
return this.#writableNeedDrain;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(initiator?: RedisSocketInitiator, options?: RedisSocketOptions) {
|
constructor(initiator?: RedisSocketInitiator, options?: RedisSocketOptions) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -163,7 +171,10 @@ export default class RedisSocket extends EventEmitter {
|
|||||||
this.#onSocketError(new Error('Socket closed unexpectedly'));
|
this.#onSocketError(new Error('Socket closed unexpectedly'));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on('drain', () => this.emit('drain'))
|
.on('drain', () => {
|
||||||
|
this.#writableNeedDrain = false;
|
||||||
|
this.emit('drain');
|
||||||
|
})
|
||||||
.on('data', (data: Buffer) => this.emit('data', data));
|
.on('data', (data: Buffer) => this.emit('data', data));
|
||||||
|
|
||||||
resolve(socket);
|
resolve(socket);
|
||||||
@@ -198,7 +209,9 @@ export default class RedisSocket extends EventEmitter {
|
|||||||
throw new ClientClosedError();
|
throw new ClientClosedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.#socket.write(toWrite);
|
const wasFullyWritten = this.#socket.write(toWrite);
|
||||||
|
this.#writableNeedDrain = !wasFullyWritten;
|
||||||
|
return wasFullyWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
async disconnect(ignoreIsOpen = false): Promise<void> {
|
async disconnect(ignoreIsOpen = false): Promise<void> {
|
||||||
|
@@ -284,16 +284,23 @@ export function describeHandleMinimumRedisVersion(minimumVersion: PartialRedisVe
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RedisClientTestOptions extends RedisTestOptions {
|
||||||
|
clientOptions?: RedisClientOptions<{}, {}>;
|
||||||
|
}
|
||||||
|
|
||||||
export function itWithClient(
|
export function itWithClient(
|
||||||
type: TestRedisServers,
|
type: TestRedisServers,
|
||||||
title: string,
|
title: string,
|
||||||
fn: (client: RedisClientType) => Promise<void>,
|
fn: (client: RedisClientType) => Promise<void>,
|
||||||
options?: RedisTestOptions
|
options?: RedisClientTestOptions
|
||||||
): void {
|
): void {
|
||||||
it(title, async function () {
|
it(title, async function () {
|
||||||
if (handleMinimumRedisVersion(this, options?.minimumRedisVersion)) return;
|
if (handleMinimumRedisVersion(this, options?.minimumRedisVersion)) return;
|
||||||
|
|
||||||
const client = RedisClient.create(TEST_REDIS_SERVERS[type]);
|
const client = RedisClient.create({
|
||||||
|
...TEST_REDIS_SERVERS[type],
|
||||||
|
...options?.clientOptions
|
||||||
|
});
|
||||||
|
|
||||||
await client.connect();
|
await client.connect();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user