Skip to content

Commit

Permalink
Merge branch 'thiagoc01-keyval-multi-var'
Browse files Browse the repository at this point in the history
  • Loading branch information
kjdev committed Mar 31, 2024
2 parents 0adec5c + 8883219 commit 707ad77
Show file tree
Hide file tree
Showing 6 changed files with 404 additions and 56 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ in the key-value database.
The database is stored in shared memory or Redis as specified
by the zone parameter.

In `key`, you can use a mix of variables and text or just variables.

> For example:
> - `$remote_addr:$http_user_agent`
> - `'$remote_addr $http_user_agent $host "a random text"'`
```
Syntax: keyval_zone zone=name:size [timeout=time] [ttl=time];
Default: -
Expand Down
30 changes: 6 additions & 24 deletions src/ngx_http_keyval_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,30 +121,10 @@ ngx_http_keyval_conf_set_variable(ngx_conf_t *cf,
return NGX_CONF_OK;
}

static ngx_int_t
ngx_http_keyval_variable_get_key(ngx_http_request_t *r,
ngx_keyval_variable_t *var, ngx_str_t *key)
static ngx_variable_value_t *
ngx_http_keyval_get_indexed_variable(void *data, ngx_uint_t index)
{
if (!key || !var) {
return NGX_ERROR;
}

if (var->key_index != NGX_CONF_UNSET) {
ngx_http_variable_value_t *v;
v = ngx_http_get_indexed_variable(r, var->key_index);
if (v == NULL || v->not_found) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"keyval: variable specified was not provided");
return NGX_ERROR;
} else {
key->data = v->data;
key->len = v->len;
}
} else {
*key = var->key_string;
}

return NGX_OK;
return ngx_http_get_indexed_variable((ngx_http_request_t *) data, index);
}

static ngx_int_t
Expand All @@ -169,7 +149,9 @@ ngx_http_keyval_variable_init(ngx_http_request_t *r, uintptr_t data,

var = (ngx_keyval_variable_t *) data;

if (ngx_http_keyval_variable_get_key(r, var, key) != NGX_OK) {
if (ngx_keyval_variable_get_key(r->connection, var, key,
ngx_http_keyval_get_indexed_variable,
(void *) r) != NGX_OK) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"keyval: rejected due to not found variable key");
return NGX_ERROR;
Expand Down
163 changes: 156 additions & 7 deletions src/ngx_keyval.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,13 +450,21 @@ ngx_keyval_conf_set_variable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf,
ngx_keyval_get_variable_index get_variable_index)
{
ngx_str_t *value;
int final_pos = 0;
int num_vars = 0;
size_t size_buffer_variable_name = 0, size_buffer_intermediate_string = 0;
u_char *string = NULL, *variable_name = NULL;
ngx_array_t *indexes = NULL;

if (!config || !tag) {
return "missing required parameter";
}

value = cf->args->elts;

size_buffer_variable_name = value[1].len;
size_buffer_intermediate_string = value[1].len;

if (value[1].len == 0) {
return "is empty";
}
Expand Down Expand Up @@ -486,14 +494,78 @@ ngx_keyval_conf_set_variable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf,
return "failed to allocate iteam";
}

if (value[1].data[0] == '$') {
value[1].data++;
value[1].len--;
(*var)->key_index = get_variable_index(cf, &value[1]);
ngx_str_null(&((*var)->key_string));
} else {
(*var)->key_index = NGX_CONF_UNSET;
if (config->indexes == NULL) {
config->indexes = ngx_array_create(cf->pool, 4, sizeof(ngx_array_t));
if (config->indexes == NULL) {
return "failed to allocate";
}
}
indexes = ngx_array_push(config->indexes);
if (indexes == NULL) {
return "failed to allocate item";
}
(*var)->indexes = ngx_array_create(cf->pool, 4, sizeof(ngx_int_t));
if ((*var)->indexes == NULL) {
return "failed to allocate";
}

string = value[1].data;

(*var)->key_string.len = 0;
(*var)->key_string.data = ngx_pnalloc(cf->pool,
size_buffer_intermediate_string);
if ((*var)->key_string.data == NULL) {
return "failed to allocate memory for intermediate string";
}

variable_name = ngx_pnalloc(cf->pool, size_buffer_variable_name);
if (variable_name == NULL) {
return "failed to allocate memory for variable name buffer";
}

while (*string != '\0') {
if (*string == '$') {
int variable_name_str_index = 0;
ngx_int_t *index;
ngx_str_t str;

(*var)->key_string.data[final_pos++] = '$';
(*var)->key_string.len++;
string++;

while (*string != '\0'
&& ((*string >= 'A' && *string <= 'Z')
|| (*string >= 'a' && *string <= 'z')
|| (*string >= '0' && *string <= '9')
|| *string == '_')) {
variable_name[variable_name_str_index] = *string;
variable_name_str_index++;
string++;
}

variable_name[variable_name_str_index] = '\0';

str.data = variable_name;
str.len = ngx_strlen(variable_name);

index = ngx_array_push((*var)->indexes);
if (index == NULL) {
return "failed to allocate item";
}
*index = get_variable_index(cf, &str);

num_vars++;
} else {
(*var)->key_string.len++;
(*var)->key_string.data[final_pos++] = *string;
string++;
}
}

if (num_vars == 0) {
(*var)->key_string = value[1];
} else {
(*var)->key_string.data[final_pos] = '\0';
}

(*var)->variable = value[2];
Expand All @@ -515,6 +587,83 @@ ngx_keyval_conf_set_variable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf,
return NGX_CONF_OK;
}

ngx_int_t
ngx_keyval_variable_get_key(ngx_connection_t *connection,
ngx_keyval_variable_t *var, ngx_str_t *key,
ngx_keyval_get_index_variable get_index_variable,
void *data)
{
if (!key || !var || !connection || !data) {
return NGX_ERROR;
}

if (var->indexes->nelts != 0) {
ngx_variable_value_t **v;
ngx_int_t current_index = 0;
ngx_str_t string_var = var->key_string;
ngx_uint_t size_string = 0;
u_char *last_space_available;

v = ngx_palloc(connection->pool,
sizeof(ngx_variable_value_t *) * var->indexes->nelts);

if (v == NULL) {
ngx_log_error(NGX_LOG_ERR, connection->log, 0,
"keyval: failed to allocate memory "
"for variable values array");
return NGX_ERROR;
}

ngx_int_t *indexes = var->indexes->elts;

for (ngx_uint_t i = 0 ; i < var->indexes->nelts ; i++) {
v[i] = get_index_variable(data, indexes[i]);

if (v[i] == NULL || v[i]-> not_found) {
ngx_log_error(NGX_LOG_INFO, connection->log, 0,
"keyval: variable specified was not provided");
return NGX_ERROR;
}

size_string += v[i]->len;
}

key->data = (u_char *) ngx_pnalloc(connection->pool,
size_string
+ (string_var.len - var->indexes->nelts)
+ 1);

if (key->data == NULL) {
ngx_log_error(NGX_LOG_ERR, connection->log, 0,
"keyval: error allocating memory for key string");
return NGX_ERROR;
}

key->len = 0;

last_space_available = key->data;

for ( ; *(string_var.data) != '\0' ; string_var.data++) {
if (*(string_var.data) == '$') {
last_space_available = ngx_cpystrn(last_space_available,
v[current_index]->data,
v[current_index]->len + 1);
key->len += v[current_index++]->len;
} else {
*last_space_available = *(string_var.data);
last_space_available += sizeof(u_char);
key->len++;
}
}

*last_space_available = '\0';
} else {
*key = var->key_string;
}

return NGX_OK;
}

void *
ngx_keyval_create_main_conf(ngx_conf_t *cf)
{
Expand Down
5 changes: 4 additions & 1 deletion src/ngx_keyval.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef enum {
} ngx_keyval_zone_type_t;

typedef struct {
ngx_array_t *indexes;
ngx_array_t *variables;
ngx_array_t *zones;
} ngx_keyval_conf_t;
Expand Down Expand Up @@ -56,7 +57,7 @@ typedef struct {
} ngx_keyval_zone_t;

typedef struct {
ngx_int_t key_index;
ngx_array_t *indexes;
ngx_str_t key_string;
ngx_str_t variable;
ngx_keyval_zone_t *zone;
Expand All @@ -69,12 +70,14 @@ typedef struct {
#endif

typedef ngx_int_t (*ngx_keyval_get_variable_index)(ngx_conf_t *cf, ngx_str_t *name);
typedef ngx_variable_value_t *(*ngx_keyval_get_index_variable)(void *data, ngx_uint_t index);

char *ngx_keyval_conf_set_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, ngx_keyval_conf_t *config, void *tag);
#if (NGX_HAVE_KEYVAL_ZONE_REDIS)
char *ngx_keyval_conf_set_zone_redis(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, ngx_keyval_conf_t *config, void *tag);
#endif
char *ngx_keyval_conf_set_variable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, ngx_keyval_conf_t *config, void *tag, ngx_keyval_variable_t **var, ngx_keyval_get_variable_index get_variable_index);
ngx_int_t ngx_keyval_variable_get_key(ngx_connection_t *connection, ngx_keyval_variable_t *var, ngx_str_t *key, ngx_keyval_get_index_variable get_index_variable, void *data);

void *ngx_keyval_create_main_conf(ngx_conf_t *cf);

Expand Down
30 changes: 6 additions & 24 deletions src/ngx_stream_keyval_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,30 +119,10 @@ ngx_stream_keyval_conf_set_variable(ngx_conf_t *cf,
return NGX_CONF_OK;
}

static ngx_int_t
ngx_stream_keyval_variable_get_key(ngx_stream_session_t *s,
ngx_keyval_variable_t *var, ngx_str_t *key)
static ngx_variable_value_t *
ngx_stream_keyval_get_indexed_variable(void *data, ngx_uint_t index)
{
if (!key || !var) {
return NGX_ERROR;
}

if (var->key_index != NGX_CONF_UNSET) {
ngx_stream_variable_value_t *v;
v = ngx_stream_get_indexed_variable(s, var->key_index);
if (v == NULL || v->not_found) {
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"keyval: variable specified was not provided");
return NGX_ERROR;
} else {
key->data = v->data;
key->len = v->len;
}
} else {
*key = var->key_string;
}

return NGX_OK;
return ngx_stream_get_indexed_variable((ngx_stream_session_t *) data, index);
}

static ngx_int_t
Expand All @@ -167,7 +147,9 @@ ngx_stream_keyval_variable_init(ngx_stream_session_t *s, uintptr_t data,

var = (ngx_keyval_variable_t *) data;

if (ngx_stream_keyval_variable_get_key(s, var, key) != NGX_OK) {
if (ngx_keyval_variable_get_key(s->connection, var, key,
ngx_stream_keyval_get_indexed_variable,
(void *) s) != NGX_OK) {
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"keyval: rejected due to not found variable key");
return NGX_ERROR;
Expand Down
Loading

0 comments on commit 707ad77

Please sign in to comment.