# HG changeset patch # User Igor Sysoev # Date 1300289551 0 # Node ID 83cd1910329c22db02335cb5c59a12a8df6179f2 # Parent 8ccd6ed1d4bb71730615e11dff95646cf3d5e513 allow regex as "map" parameter diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c --- 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 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_c 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_c 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_c 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_c 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 --- 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 } +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 --- 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_r #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);