You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-06 02:15:48 +03:00
Send client user-agent during connection, via CLIENT SETINFO (#2645)
* Add SETINFO support to client connection, with the ability to disable sending the user agent if the end user desires. * Also enables modifying the user-agent with a tag to enable distinguishing different usages.
This commit is contained in:
@@ -10,6 +10,8 @@ import { once } from 'events';
|
||||
import { ClientKillFilters } from '../commands/CLIENT_KILL';
|
||||
import { promisify } from 'util';
|
||||
|
||||
import {version} from '../../package.json';
|
||||
|
||||
export const SQUARE_SCRIPT = defineScript({
|
||||
SCRIPT: 'return ARGV[1] * ARGV[1];',
|
||||
NUMBER_OF_KEYS: 0,
|
||||
@@ -118,6 +120,44 @@ describe('Client', () => {
|
||||
...GLOBAL.SERVERS.PASSWORD,
|
||||
disableClientSetup: true
|
||||
});
|
||||
|
||||
testUtils.testWithClient('should set default lib name and version', async client => {
|
||||
const clientInfo = await client.clientInfo();
|
||||
|
||||
assert.equal(clientInfo.libName, 'node-redis');
|
||||
assert.equal(clientInfo.libVer, version);
|
||||
}, {
|
||||
...GLOBAL.SERVERS.PASSWORD,
|
||||
minimumDockerVersion: [7, 2]
|
||||
});
|
||||
|
||||
testUtils.testWithClient('disable sending lib name and version', async client => {
|
||||
const clientInfo = await client.clientInfo();
|
||||
|
||||
assert.equal(clientInfo.libName, '');
|
||||
assert.equal(clientInfo.libVer, '');
|
||||
}, {
|
||||
...GLOBAL.SERVERS.PASSWORD,
|
||||
clientOptions: {
|
||||
...GLOBAL.SERVERS.PASSWORD.clientOptions,
|
||||
disableClientInfo: true
|
||||
},
|
||||
minimumDockerVersion: [7, 2]
|
||||
});
|
||||
|
||||
testUtils.testWithClient('send client name tag', async client => {
|
||||
const clientInfo = await client.clientInfo();
|
||||
|
||||
assert.equal(clientInfo.libName, 'node-redis(test)');
|
||||
assert.equal(clientInfo.libVer, version);
|
||||
}, {
|
||||
...GLOBAL.SERVERS.PASSWORD,
|
||||
clientOptions: {
|
||||
...GLOBAL.SERVERS.PASSWORD.clientOptions,
|
||||
clientInfoTag: "test"
|
||||
},
|
||||
minimumDockerVersion: [7, 2]
|
||||
});
|
||||
});
|
||||
|
||||
describe('authentication', () => {
|
||||
|
@@ -11,11 +11,13 @@ import { ScanCommandOptions } from '../commands/SCAN';
|
||||
import { HScanTuple } from '../commands/HSCAN';
|
||||
import { attachCommands, attachExtensions, fCallArguments, transformCommandArguments, transformCommandReply, transformLegacyCommandArguments } from '../commander';
|
||||
import { Pool, Options as PoolOptions, createPool } from 'generic-pool';
|
||||
import { ClientClosedError, ClientOfflineError, DisconnectsClientError } from '../errors';
|
||||
import { ClientClosedError, ClientOfflineError, DisconnectsClientError, ErrorReply } from '../errors';
|
||||
import { URL } from 'url';
|
||||
import { TcpSocketConnectOpts } from 'net';
|
||||
import { PubSubType, PubSubListener, PubSubTypeListeners, ChannelListeners } from './pub-sub';
|
||||
|
||||
import {version} from '../../package.json';
|
||||
|
||||
export interface RedisClientOptions<
|
||||
M extends RedisModules = RedisModules,
|
||||
F extends RedisFunctions = RedisFunctions,
|
||||
@@ -66,6 +68,14 @@ export interface RedisClientOptions<
|
||||
* Useful with Redis deployments that do not use TCP Keep-Alive.
|
||||
*/
|
||||
pingInterval?: number;
|
||||
/**
|
||||
* If set to true, disables sending client identifier (user-agent like message) to the redis server
|
||||
*/
|
||||
disableClientInfo?: boolean;
|
||||
/**
|
||||
* Tag to append to library name that is sent to the Redis server
|
||||
*/
|
||||
clientInfoTag?: string;
|
||||
}
|
||||
|
||||
type WithCommands = {
|
||||
@@ -274,6 +284,33 @@ export default class RedisClient<
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.#options?.disableClientInfo) {
|
||||
promises.push(
|
||||
this.#queue.addCommand(
|
||||
[ 'CLIENT', 'SETINFO', 'LIB-VER', version],
|
||||
{ asap: true }
|
||||
).catch(err => {
|
||||
if (!(err instanceof ErrorReply)) {
|
||||
throw err;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
promises.push(
|
||||
this.#queue.addCommand(
|
||||
[
|
||||
'CLIENT', 'SETINFO', 'LIB-NAME',
|
||||
this.#options?.clientInfoTag ? `node-redis(${this.#options.clientInfoTag})` : 'node-redis'
|
||||
],
|
||||
{ asap: true }
|
||||
).catch(err => {
|
||||
if (!(err instanceof ErrorReply)) {
|
||||
throw err;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (this.#options?.name) {
|
||||
promises.push(
|
||||
this.#queue.addCommand(
|
||||
|
@@ -31,6 +31,9 @@ export interface ClientInfoReply {
|
||||
user?: string; // 6.0
|
||||
redir?: number; // 6.2
|
||||
resp?: number; // 7.0
|
||||
// 7.2
|
||||
libName?: string;
|
||||
libVer?: string;
|
||||
}
|
||||
|
||||
const CLIENT_INFO_REGEX = /([^\s=]+)=([^\s]*)/g;
|
||||
@@ -62,7 +65,9 @@ export function transformReply(rawReply: string): ClientInfoReply {
|
||||
totMem: Number(map['tot-mem']),
|
||||
events: map.events,
|
||||
cmd: map.cmd,
|
||||
user: map.user
|
||||
user: map.user,
|
||||
libName: map['lib-name'],
|
||||
libVer: map['lib-ver'],
|
||||
};
|
||||
|
||||
if (map.laddr !== undefined) {
|
||||
|
@@ -4,7 +4,8 @@ import { promiseTimeout } from './utils';
|
||||
|
||||
const utils = new TestUtils({
|
||||
dockerImageName: 'redis',
|
||||
dockerImageVersionArgument: 'redis-version'
|
||||
dockerImageVersionArgument: 'redis-version',
|
||||
defaultDockerVersion: '7.2'
|
||||
});
|
||||
|
||||
export default utils;
|
||||
|
Reference in New Issue
Block a user