aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2011-03-16 15:32:31 +0000
committerIgor Sysoev <igor@sysoev.ru>2011-03-16 15:32:31 +0000
commit0519b43a772476a7537e02a34acb9b265e814815 (patch)
tree291b9eaa9e0a27313d60439b893c8d820f6aedeb
parent32c73df97a205e59d3df9b6def7ca2beb36a4012 (diff)
downloadnginx-0519b43a772476a7537e02a34acb9b265e814815.tar.gz
nginx-0519b43a772476a7537e02a34acb9b265e814815.zip
allow regex as "map" parameter
-rw-r--r--src/http/modules/ngx_http_map_module.c70
-rw-r--r--src/http/ngx_http_variables.c44
-rw-r--r--src/http/ngx_http_variables.h19
3 files changed, 128 insertions, 5 deletions
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c
index 5f263a55d..9dc0ef6fc 100644
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -20,6 +20,9 @@ typedef struct {
ngx_array_t *values_hash;
ngx_array_t var_values;
+#if (NGX_PCRE)
+ ngx_array_t regexes;
+#endif
ngx_http_variable_value_t *default_value;
ngx_conf_t *cf;
@@ -28,7 +31,7 @@ typedef struct {
typedef struct {
- ngx_hash_combined_t hash;
+ ngx_http_map_t map;
ngx_http_complex_value_t value;
ngx_http_variable_value_t *default_value;
ngx_uint_t hostnames; /* unsigned hostnames:1 */
@@ -126,7 +129,7 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
key = ngx_hash_strlow(val.data, val.data, len);
- value = ngx_hash_find_combined(&map->hash, key, val.data, len);
+ value = ngx_http_map_find(r, &map->map, key, val.data, len, &val);
if (value == NULL) {
value = map->default_value;
@@ -249,6 +252,15 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
+#if (NGX_PCRE)
+ if (ngx_array_init(&ctx.regexes, cf->pool, 2, sizeof(ngx_http_map_regex_t))
+ != NGX_OK)
+ {
+ ngx_destroy_pool(pool);
+ return NGX_CONF_ERROR;
+ }
+#endif
+
ctx.default_value = NULL;
ctx.cf = &save;
ctx.hostnames = 0;
@@ -278,7 +290,7 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
hash.pool = cf->pool;
if (ctx.keys.keys.nelts) {
- hash.hash = &map->hash.hash;
+ hash.hash = &map->map.hash.hash;
hash.temp_pool = NULL;
if (ngx_hash_init(&hash, ctx.keys.keys.elts, ctx.keys.keys.nelts)
@@ -306,7 +318,7 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- map->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
+ map->map.hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
}
if (ctx.keys.dns_wc_tail.nelts) {
@@ -326,9 +338,18 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- map->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
+ map->map.hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
}
+#if (NGX_PCRE)
+
+ if (ctx.regexes.nelts) {
+ map->map.regex = ctx.regexes.elts;
+ map->map.nregex = ctx.regexes.nelts;
+ }
+
+#endif
+
ngx_destroy_pool(pool);
return rv;
@@ -491,6 +512,45 @@ found:
return NGX_CONF_OK;
}
+#if (NGX_PCRE)
+
+ if (value[0].len && value[0].data[0] == '~') {
+ ngx_regex_compile_t rc;
+ ngx_http_map_regex_t *regex;
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
+
+ regex = ngx_array_push(&ctx->regexes);
+ if (regex == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ value[0].len--;
+ value[0].data++;
+
+ ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+ if (value[0].data[0] == '*') {
+ value[0].len--;
+ value[0].data++;
+ rc.options = NGX_REGEX_CASELESS;
+ }
+
+ rc.pattern = value[0];
+ rc.err.len = NGX_MAX_CONF_ERRSTR;
+ rc.err.data = errstr;
+
+ regex->regex = ngx_http_regex_compile(ctx->cf, &rc);
+ if (regex->regex == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ regex->value = var;
+
+ return NGX_CONF_OK;
+ }
+
+#endif
+
if (value[0].len && value[0].data[0] == '\\') {
value[0].len--;
value[0].data++;
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 00d9d5eb4..3946e3867 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -1660,6 +1660,50 @@ ngx_http_variable_pid(ngx_http_request_t *r,
}
+void *
+ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map, ngx_uint_t key,
+ u_char *text, size_t len, ngx_str_t *match)
+{
+ void *p;
+
+ p = ngx_hash_find_combined(&map->hash, key, text, len);
+ if (p) {
+ return p;
+ }
+
+#if (NGX_PCRE)
+
+ if (len && map->nregex) {
+ ngx_int_t n;
+ ngx_uint_t i;
+ ngx_http_map_regex_t *reg;
+
+ reg = map->regex;
+
+ for (i = 0; i < map->nregex; i++) {
+
+ n = ngx_http_regex_exec(r, reg[i].regex, match);
+
+ if (n == NGX_OK) {
+ return reg[i].value;
+ }
+
+ if (n == NGX_DECLINED) {
+ continue;
+ }
+
+ /* NGX_ERROR */
+
+ return NULL;
+ }
+ }
+
+#endif
+
+ return NULL;
+}
+
+
#if (NGX_PCRE)
static ngx_int_t
diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h
index 588f5caf5..8e7263646 100644
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -76,6 +76,12 @@ typedef struct {
} ngx_http_regex_t;
+typedef struct {
+ ngx_http_regex_t *regex;
+ void *value;
+} ngx_http_map_regex_t;
+
+
ngx_http_regex_t *ngx_http_regex_compile(ngx_conf_t *cf,
ngx_regex_compile_t *rc);
ngx_int_t ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re,
@@ -84,6 +90,19 @@ ngx_int_t ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re,
#endif
+typedef struct {
+ ngx_hash_combined_t hash;
+#if (NGX_PCRE)
+ ngx_http_map_regex_t *regex;
+ ngx_uint_t nregex;
+#endif
+} ngx_http_map_t;
+
+
+void *ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map,
+ ngx_uint_t key, u_char *text, size_t len, ngx_str_t *match);
+
+
ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf);
ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf);