Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
dc5edc7b
Commit
dc5edc7b
authored
Mar 18, 2019
by
Yossi Gottlieb
Committed by
antirez
May 13, 2019
Browse files
Add command filtering argument handling API.
parent
5f29e2e2
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/module.c
View file @
dc5edc7b
...
...
@@ -291,6 +291,10 @@ typedef struct RedisModuleCommandFilter {
/* Registered filters */
static list *moduleCommandFilters;
typedef struct RedisModuleCommandFilterCtx {
RedisModuleString **argv;
int argc;
} RedisModuleCommandFilterCtx;
/* --------------------------------------------------------------------------
* Prototypes
...
...
@@ -4844,6 +4848,78 @@ void moduleCallCommandFilters(client *c) {
c->argc = cmd.argc;
}
/* Return the number of arguments a filtered command has. The number of
* arguments include the command itself.
*/
int RM_CommandFilterArgsCount(RedisModuleCommandFilterCtx *filter)
{
return filter->argc;
}
/* Return the specified command argument. The first argument (position 0) is
* the command itself, and the rest are user-provided args.
*/
const RedisModuleString *RM_CommandFilterArgGet(RedisModuleCommandFilterCtx *filter, int pos)
{
if (pos < 0 || pos >= filter->argc) return NULL;
return filter->argv[pos];
}
/* Modify the filtered command by inserting a new argument at the specified
* position. The specified RedisModuleString argument may be used by Redis
* after the filter context is destroyed, so it must not be auto-memory
* allocated, freed or used elsewhere.
*/
int RM_CommandFilterArgInsert(RedisModuleCommandFilterCtx *filter, int pos, RedisModuleString *arg)
{
int i;
if (pos < 0 || pos > filter->argc) return REDISMODULE_ERR;
filter->argv = zrealloc(filter->argv, (filter->argc+1)*sizeof(RedisModuleString *));
for (i = filter->argc; i > pos; i--) {
filter->argv[i] = filter->argv[i-1];
}
filter->argv[pos] = arg;
filter->argc++;
return REDISMODULE_OK;
}
/* Modify the filtered command by replacing an existing argument with a new one.
* The specified RedisModuleString argument may be used by Redis after the
* filter context is destroyed, so it must not be auto-memory allocated, freed
* or used elsewhere.
*/
int RM_CommandFilterArgReplace(RedisModuleCommandFilterCtx *filter, int pos, RedisModuleString *arg)
{
if (pos < 0 || pos >= filter->argc) return REDISMODULE_ERR;
decrRefCount(filter->argv[pos]);
filter->argv[pos] = arg;
return REDISMODULE_OK;
}
/* Modify the filtered command by deleting an argument at the specified
* position.
*/
int RM_CommandFilterArgDelete(RedisModuleCommandFilterCtx *filter, int pos)
{
int i;
if (pos < 0 || pos >= filter->argc) return REDISMODULE_ERR;
decrRefCount(filter->argv[pos]);
for (i = pos; i < filter->argc-1; i++) {
filter->argv[i] = filter->argv[i+1];
}
filter->argc--;
return REDISMODULE_OK;
}
/* --------------------------------------------------------------------------
* Modules API internals
* -------------------------------------------------------------------------- */
...
...
@@ -5291,4 +5367,9 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API(ExportSharedAPI);
REGISTER_API(GetSharedAPI);
REGISTER_API(RegisterCommandFilter);
REGISTER_API(CommandFilterArgsCount);
REGISTER_API(CommandFilterArgGet);
REGISTER_API(CommandFilterArgInsert);
REGISTER_API(CommandFilterArgReplace);
REGISTER_API(CommandFilterArgDelete);
}
src/modules/hellofilter.c
View file @
dc5edc7b
#define REDISMODULE_EXPERIMENTAL_API
#include "../redismodule.h"
#include <string.h>
static
RedisModuleString
*
log_key_name
;
static
const
char
log_command_name
[]
=
"hellofilter.log"
;
...
...
@@ -35,16 +37,46 @@ int HelloFilter_LogCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int ar
return
REDISMODULE_OK
;
}
void
HelloFilter_CommandFilter
(
RedisModuleCtx
*
ctx
,
RedisModule
FilteredCommand
*
cmd
)
void
HelloFilter_CommandFilter
(
RedisModuleCtx
*
ctx
,
RedisModule
CommandFilterCtx
*
filter
)
{
cmd
->
argv
=
RedisModule_Realloc
(
cmd
->
argv
,
(
cmd
->
argc
+
1
)
*
sizeof
(
RedisModuleString
*
));
int
i
;
(
void
)
ctx
;
for
(
i
=
cmd
->
argc
;
i
>
0
;
i
--
)
{
cmd
->
argv
[
i
]
=
cmd
->
argv
[
i
-
1
];
/* Fun manipulations:
* - Remove @delme
* - Replace @replaceme
* - Append @insertbefore or @insertafter
* - Prefix with Log command if @log encounterd
*/
int
log
=
0
;
int
pos
=
0
;
while
(
pos
<
RedisModule_CommandFilterArgsCount
(
filter
))
{
const
RedisModuleString
*
arg
=
RedisModule_CommandFilterArgGet
(
filter
,
pos
);
size_t
arg_len
;
const
char
*
arg_str
=
RedisModule_StringPtrLen
(
arg
,
&
arg_len
);
if
(
arg_len
==
6
&&
!
memcmp
(
arg_str
,
"@delme"
,
6
))
{
RedisModule_CommandFilterArgDelete
(
filter
,
pos
);
continue
;
}
if
(
arg_len
==
10
&&
!
memcmp
(
arg_str
,
"@replaceme"
,
10
))
{
RedisModule_CommandFilterArgReplace
(
filter
,
pos
,
RedisModule_CreateString
(
NULL
,
"--replaced--"
,
12
));
}
else
if
(
arg_len
==
13
&&
!
memcmp
(
arg_str
,
"@insertbefore"
,
13
))
{
RedisModule_CommandFilterArgInsert
(
filter
,
pos
,
RedisModule_CreateString
(
NULL
,
"--inserted-before--"
,
19
));
pos
++
;
}
else
if
(
arg_len
==
12
&&
!
memcmp
(
arg_str
,
"@insertafter"
,
12
))
{
RedisModule_CommandFilterArgInsert
(
filter
,
pos
+
1
,
RedisModule_CreateString
(
NULL
,
"--inserted-after--"
,
18
));
pos
++
;
}
else
if
(
arg_len
==
4
&&
!
memcmp
(
arg_str
,
"@log"
,
4
))
{
log
=
1
;
}
pos
++
;
}
cmd
->
argv
[
0
]
=
RedisModule_CreateString
(
ctx
,
log_command_name
,
sizeof
(
log_command_name
)
-
1
);
cmd
->
argc
++
;
if
(
log
)
RedisModule_CommandFilterArgInsert
(
filter
,
0
,
RedisModule_CreateString
(
NULL
,
log_command_name
,
sizeof
(
log_command_name
)
-
1
));
}
int
RedisModule_OnLoad
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
...
...
src/redismodule.h
View file @
dc5edc7b
...
...
@@ -150,6 +150,7 @@ typedef struct RedisModuleBlockedClient RedisModuleBlockedClient;
typedef
struct
RedisModuleClusterInfo
RedisModuleClusterInfo
;
typedef
struct
RedisModuleDict
RedisModuleDict
;
typedef
struct
RedisModuleDictIter
RedisModuleDictIter
;
typedef
struct
RedisModuleCommandFilterCtx
RedisModuleCommandFilterCtx
;
typedef
int
(
*
RedisModuleCmdFunc
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
);
typedef
void
(
*
RedisModuleDisconnectFunc
)(
RedisModuleCtx
*
ctx
,
RedisModuleBlockedClient
*
bc
);
...
...
@@ -162,12 +163,7 @@ typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value
typedef
void
(
*
RedisModuleTypeFreeFunc
)(
void
*
value
);
typedef
void
(
*
RedisModuleClusterMessageReceiver
)(
RedisModuleCtx
*
ctx
,
const
char
*
sender_id
,
uint8_t
type
,
const
unsigned
char
*
payload
,
uint32_t
len
);
typedef
void
(
*
RedisModuleTimerProc
)(
RedisModuleCtx
*
ctx
,
void
*
data
);
typedef
struct
RedisModuleFilteredCommand
{
RedisModuleString
**
argv
;
int
argc
;
}
RedisModuleFilteredCommand
;
typedef
void
(
*
RedisModuleCommandFilterFunc
)
(
RedisModuleCtx
*
ctx
,
RedisModuleFilteredCommand
*
cmd
);
typedef
void
(
*
RedisModuleCommandFilterFunc
)
(
RedisModuleCtx
*
ctx
,
RedisModuleCommandFilterCtx
*
filter
);
#define REDISMODULE_TYPE_METHOD_VERSION 1
typedef
struct
RedisModuleTypeMethods
{
...
...
@@ -345,6 +341,11 @@ void REDISMODULE_API_FUNC(RedisModule_SetClusterFlags)(RedisModuleCtx *ctx, uint
int
REDISMODULE_API_FUNC
(
RedisModule_ExportSharedAPI
)(
RedisModuleCtx
*
ctx
,
const
char
*
apiname
,
void
*
func
);
void
*
REDISMODULE_API_FUNC
(
RedisModule_GetSharedAPI
)(
RedisModuleCtx
*
ctx
,
const
char
*
apiname
);
int
REDISMODULE_API_FUNC
(
RedisModule_RegisterCommandFilter
)(
RedisModuleCtx
*
ctx
,
RedisModuleCommandFilterFunc
cb
);
int
REDISMODULE_API_FUNC
(
RedisModule_CommandFilterArgsCount
)(
RedisModuleCommandFilterCtx
*
filter
);
const
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CommandFilterArgGet
)(
RedisModuleCommandFilterCtx
*
filter
,
int
pos
);
int
REDISMODULE_API_FUNC
(
RedisModule_CommandFilterArgInsert
)(
RedisModuleCommandFilterCtx
*
filter
,
int
pos
,
RedisModuleString
*
arg
);
int
REDISMODULE_API_FUNC
(
RedisModule_CommandFilterArgReplace
)(
RedisModuleCommandFilterCtx
*
filter
,
int
pos
,
RedisModuleString
*
arg
);
int
REDISMODULE_API_FUNC
(
RedisModule_CommandFilterArgDelete
)(
RedisModuleCommandFilterCtx
*
filter
,
int
pos
);
#endif
/* This is included inline inside each Redis module. */
...
...
@@ -509,6 +510,11 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
ExportSharedAPI
);
REDISMODULE_GET_API
(
GetSharedAPI
);
REDISMODULE_GET_API
(
RegisterCommandFilter
);
REDISMODULE_GET_API
(
CommandFilterArgsCount
);
REDISMODULE_GET_API
(
CommandFilterArgGet
);
REDISMODULE_GET_API
(
CommandFilterArgInsert
);
REDISMODULE_GET_API
(
CommandFilterArgReplace
);
REDISMODULE_GET_API
(
CommandFilterArgDelete
);
#endif
if
(
RedisModule_IsModuleNameBusy
&&
RedisModule_IsModuleNameBusy
(
name
))
return
REDISMODULE_ERR
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment