Mercurial > hg > nginx-mail
diff src/http/modules/ngx_http_map_module.c @ 665:0b460e61bdcd default tip
Merge with nginx 1.0.0.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Apr 2011 04:22:17 +0400 |
parents | 8214eaef3530 |
children |
line wrap: on
line diff
--- a/src/http/modules/ngx_http_map_module.c +++ b/src/http/modules/ngx_http_map_module.c @@ -19,15 +19,20 @@ typedef struct { ngx_hash_keys_arrays_t keys; 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; ngx_uint_t hostnames; /* unsigned hostnames:1 */ } ngx_http_map_conf_ctx_t; typedef struct { - ngx_hash_combined_t hash; - ngx_int_t index; + 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 */ } ngx_http_map_ctx_t; @@ -105,49 +110,43 @@ ngx_http_map_variable(ngx_http_request_t ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data; size_t len; - u_char *name; + ngx_str_t val; ngx_uint_t key; - ngx_http_variable_value_t *vv, *value; + ngx_http_variable_value_t *value; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http map started"); - vv = ngx_http_get_flushed_variable(r, map->index); - - if (vv == NULL || vv->not_found) { - *v = *map->default_value; - return NGX_OK; + if (ngx_http_complex_value(r, &map->value, &val) != NGX_OK) { + return NGX_ERROR; } - len = vv->len; + len = val.len; - if (len && map->hostnames && vv->data[len - 1] == '.') { + if (len && map->hostnames && val.data[len - 1] == '.') { len--; } - if (len == 0) { - *v = *map->default_value; - return NGX_OK; - } + key = ngx_hash_strlow(val.data, val.data, len); - name = ngx_pnalloc(r->pool, len); - if (name == NULL) { - return NGX_ERROR; + value = ngx_http_map_find(r, &map->map, key, val.data, len, &val); + + if (value == NULL) { + value = map->default_value; } - key = ngx_hash_strlow(name, vv->data, len); - - value = ngx_hash_find_combined(&map->hash, key, name, len); + if (!value->valid) { + value = ngx_http_get_flushed_variable(r, (ngx_uint_t) value->data); - if (value) { - *v = *value; - - } else { - *v = *map->default_value; + if (value == NULL || value->not_found) { + value = &ngx_http_variable_null_value; + } } + *v = *value; + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http map: \"%v\" \"%v\"", vv, v); + "http map: \"%v\" \"%v\"", &val, v); return NGX_OK; } @@ -175,14 +174,15 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_c { ngx_http_map_conf_t *mcf = conf; - char *rv; - ngx_str_t *value, name; - ngx_conf_t save; - ngx_pool_t *pool; - ngx_hash_init_t hash; - ngx_http_map_ctx_t *map; - ngx_http_variable_t *var; - ngx_http_map_conf_ctx_t ctx; + char *rv; + ngx_str_t *value, name; + ngx_conf_t save; + ngx_pool_t *pool; + ngx_hash_init_t hash; + ngx_http_map_ctx_t *map; + ngx_http_variable_t *var; + ngx_http_map_conf_ctx_t ctx; + ngx_http_compile_complex_value_t ccv; if (mcf->hash_max_size == NGX_CONF_UNSET_UINT) { mcf->hash_max_size = 2048; @@ -203,13 +203,13 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_c value = cf->args->elts; - name = value[1]; - name.len--; - name.data++; + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); - map->index = ngx_http_get_variable_index(cf, &name); + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &map->value; - if (map->index == NGX_ERROR) { + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; } @@ -244,7 +244,25 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_c return NGX_CONF_ERROR; } + if (ngx_array_init(&ctx.var_values, cf->pool, 2, + sizeof(ngx_http_variable_value_t)) + != NGX_OK) + { + ngx_destroy_pool(pool); + 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; save = *cf; @@ -272,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) @@ -300,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) { @@ -320,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; @@ -344,8 +371,8 @@ ngx_http_map_cmp_dns_wildcards(const voi static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { - ngx_int_t rc; - ngx_str_t *value, file; + ngx_int_t rc, index; + ngx_str_t *value, file, name; ngx_uint_t i, key; ngx_http_map_conf_ctx_t *ctx; ngx_http_variable_value_t *var, **vp; @@ -364,17 +391,12 @@ ngx_http_map(ngx_conf_t *cf, ngx_command ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR; - - } else if (value[0].len == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid first parameter"); - return NGX_CONF_ERROR; } if (ngx_strcmp(value[0].data, "include") == 0) { file = value[1]; - if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK){ + if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { return NGX_CONF_ERROR; } @@ -383,6 +405,45 @@ ngx_http_map(ngx_conf_t *cf, ngx_command return ngx_conf_parse(cf, &file); } + if (value[1].data[0] == '$') { + name = value[1]; + name.len--; + name.data++; + + index = ngx_http_get_variable_index(ctx->cf, &name); + if (index == NGX_ERROR) { + return NGX_CONF_ERROR; + } + + var = ctx->var_values.elts; + + for (i = 0; i < ctx->var_values.nelts; i++) { + if (index == (ngx_int_t) var[i].data) { + goto found; + } + } + + var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t)); + if (var == NULL) { + return NGX_CONF_ERROR; + } + + var->valid = 0; + var->no_cacheable = 0; + var->not_found = 0; + var->len = 0; + var->data = (u_char *) index; + + vp = ngx_array_push(&ctx->var_values); + if (vp == NULL) { + return NGX_CONF_ERROR; + } + + *vp = var; + + goto found; + } + key = 0; for (i = 0; i < value[1].len; i++) { @@ -451,7 +512,40 @@ found: return NGX_CONF_OK; } - if (value[0].len && value[0].data[0] == '!') { +#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)); + + 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++; }