From 2402502c2f35b831ee89369a532b1ff4e4e19947 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Fri, 16 Dec 2005 15:07:08 +0000 Subject: nginx-0.3.16-RELEASE import *) Feature: the ngx_http_map_module. *) Feature: the "types_hash_max_size" and "types_hash_bucket_size" directives. *) Feature: the "ssi_value_length" directive. *) Feature: the "worker_rlimit_core" directive. *) Workaround: the connection number in logs was always 1 if nginx was built by the icc 8.1 or 9.0 compilers with optimization for Pentium 4. *) Bugfix: the "config timefmt" SSI command set incorrect time format. *) Bugfix: nginx did not close connection to IMAP/POP3 backend for the SSL connections; the bug had appeared in 0.3.13. Thanks to Rob Mueller. *) Bugfix: segmentation fault may occurred in at SSL shutdown; the bug had appeared in 0.3.13. --- src/http/modules/ngx_http_geo_module.c | 47 +- src/http/modules/ngx_http_gzip_filter_module.c | 4 +- src/http/modules/ngx_http_map_module.c | 637 +++++++++++++++++++++++++ src/http/modules/ngx_http_proxy_module.c | 9 +- src/http/modules/ngx_http_ssi_filter_module.c | 15 +- 5 files changed, 681 insertions(+), 31 deletions(-) create mode 100644 src/http/modules/ngx_http_map_module.c (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c index bf7b9251b..a6e8db301 100644 --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -13,7 +13,7 @@ typedef struct { ngx_radix_tree_t *tree; ngx_pool_t *pool; ngx_array_t values; -} ngx_http_geo_conf_t; +} ngx_http_geo_conf_ctx_t; static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -95,12 +95,12 @@ ngx_http_geo_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, static char * ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - char *rv; - ngx_str_t *value, name; - ngx_conf_t save; - ngx_pool_t *pool; - ngx_radix_tree_t *tree; - ngx_http_geo_conf_t geo; + char *rv; + ngx_str_t *value, name; + ngx_conf_t save; + ngx_pool_t *pool; + ngx_radix_tree_t *tree; + ngx_http_geo_conf_ctx_t ctx; ngx_http_variable_t *var; value = cf->args->elts; @@ -135,20 +135,20 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - if (ngx_array_init(&geo.values, pool, 512, + if (ngx_array_init(&ctx.values, pool, 512, sizeof(ngx_http_variable_value_t *)) - == NGX_ERROR) + != NGX_OK) { ngx_destroy_pool(pool); return NGX_CONF_ERROR; } - geo.tree = tree; - geo.pool = cf->pool; + ctx.tree = tree; + ctx.pool = cf->pool; save = *cf; cf->pool = pool; - cf->ctx = &geo; + cf->ctx = &ctx; cf->handler = ngx_http_geo; cf->handler_conf = conf; @@ -182,10 +182,10 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) ngx_str_t *value, file; ngx_uint_t i; ngx_inet_cidr_t cidrin; - ngx_http_geo_conf_t *geo; + ngx_http_geo_conf_ctx_t *ctx; ngx_http_variable_value_t *var, *old, **v; - geo = cf->ctx; + ctx = cf->ctx; if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -223,28 +223,27 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) } var = NULL; - v = geo->values.elts; + v = ctx->values.elts; - for (i = 0; i < geo->values.nelts; i++) { + for (i = 0; i < ctx->values.nelts; i++) { if ((size_t) v[i]->len != value[1].len) { continue; } - if (ngx_strncmp(value[1].data, v[i]->data, value[1].len) == 0) - { + if (ngx_strncmp(value[1].data, v[i]->data, value[1].len) == 0) { var = v[i]; break; } } if (var == NULL) { - var = ngx_palloc(geo->pool, sizeof(ngx_http_variable_value_t)); + var = ngx_palloc(ctx->pool, sizeof(ngx_http_variable_value_t)); if (var == NULL) { return NGX_CONF_ERROR; } var->len = value[1].len; - var->data = ngx_pstrdup(geo->pool, &value[1]); + var->data = ngx_pstrdup(ctx->pool, &value[1]); if (var->data == NULL) { return NGX_CONF_ERROR; } @@ -253,7 +252,7 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) var->no_cachable = 0; var->not_found = 0; - v = ngx_array_push(&geo->values); + v = ngx_array_push(&ctx->values); if (v == NULL) { return NGX_CONF_ERROR; } @@ -262,7 +261,7 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) } for (i = 2; i; i--) { - rc = ngx_radix32tree_insert(geo->tree, cidrin.addr, cidrin.mask, + rc = ngx_radix32tree_insert(ctx->tree, cidrin.addr, cidrin.mask, (uintptr_t) var); if (rc == NGX_OK) { return NGX_CONF_OK; @@ -275,14 +274,14 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) /* rc == NGX_BUSY */ old = (ngx_http_variable_value_t *) - ngx_radix32tree_find(geo->tree, cidrin.addr & cidrin.mask); + ngx_radix32tree_find(ctx->tree, cidrin.addr & cidrin.mask); ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate parameter \"%V\", value: \"%V\", " "old value: \"%V\"", &value[0], var, old); - rc = ngx_radix32tree_delete(geo->tree, cidrin.addr, cidrin.mask); + rc = ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask); if (rc == NGX_ERROR) { return NGX_CONF_ERROR; diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c index e8197598f..940e082a5 100644 --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -22,7 +22,7 @@ typedef struct { ngx_uint_t http_version; ngx_uint_t proxied; - int level; + ngx_int_t level; size_t wbits; size_t memlevel; ssize_t min_length; @@ -509,7 +509,7 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in) ctx->zstream.zfree = ngx_http_gzip_filter_free; ctx->zstream.opaque = ctx; - rc = deflateInit2(&ctx->zstream, conf->level, Z_DEFLATED, + rc = deflateInit2(&ctx->zstream, (int) conf->level, Z_DEFLATED, -wbits, memlevel, Z_DEFAULT_STRATEGY); if (rc != Z_OK) { diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c new file mode 100644 index 000000000..2769028d6 --- /dev/null +++ b/src/http/modules/ngx_http_map_module.c @@ -0,0 +1,637 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include +#include +#include + + +#define NGX_HTTP_MAP_HASH 10007 + +typedef struct { + ngx_uint_t hash_max_size; + ngx_uint_t hash_bucket_size; +} ngx_http_map_conf_t; + + +typedef struct { + ngx_pool_t *pool; + + ngx_array_t keys; + ngx_array_t *keys_hash; + + ngx_array_t dns_wildcards; + ngx_array_t *dns_hash; + + ngx_array_t *values_hash; + + ngx_http_variable_value_t *default_value; + ngx_uint_t hostnames; /* unsigned hostnames:1 */ +} ngx_http_map_conf_ctx_t; + + +typedef struct { + ngx_hash_t hash; + ngx_hash_wildcard_t *dns_wildcards; + ngx_int_t index; + ngx_http_variable_value_t *default_value; + ngx_uint_t hostnames; /* unsigned hostnames:1 */ +} ngx_http_map_ctx_t; + + +static int ngx_libc_cdecl ngx_http_map_cmp_dns_wildcards(const void *one, + const void *two); +static void *ngx_http_map_create_conf(ngx_conf_t *cf); +static char *ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); + + +static ngx_command_t ngx_http_map_commands[] = { + + { ngx_string("map"), + NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2, + ngx_http_map_block, + NGX_HTTP_MAIN_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("map_hash_max_size"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_map_conf_t, hash_max_size), + NULL }, + + { ngx_string("map_hash_bucket_size"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_map_conf_t, hash_bucket_size), + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_map_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + ngx_http_map_create_conf, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_map_module = { + NGX_MODULE_V1, + &ngx_http_map_module_ctx, /* module context */ + ngx_http_map_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data; + + size_t len; + u_char *name; + ngx_uint_t key, i; + ngx_http_variable_value_t *vv, *value; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http map started"); + + vv = ngx_http_get_flushed_variable(r, map->index); + + len = vv->len; + + if (len && map->hostnames && vv->data[len - 1] == '.') { + len--; + } + + if (len == 0) { + *v = *map->default_value; + return NGX_OK; + } + + name = ngx_palloc(r->pool, len); + if (name == NULL) { + return NGX_ERROR; + } + + key = 0; + for (i = 0; i < len; i++) { + name[i] = ngx_tolower(vv->data[i]); + key = ngx_hash(key, name[i]); + } + + value = NULL; + + if (map->hash.buckets) { + value = ngx_hash_find(&map->hash, key, name, len); + } + + if (value) { + *v = *value; + + } else { + if (map->dns_wildcards && map->dns_wildcards->hash.buckets) { + value = ngx_hash_find_wildcard(map->dns_wildcards, name, len); + if (value) { + *v = *value; + + } else { + *v = *map->default_value; + } + + } else { + *v = *map->default_value; + } + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http map: \"%V\" \"%V\"", vv, v); + + return NGX_OK; +} + + +static void * +ngx_http_map_create_conf(ngx_conf_t *cf) +{ + ngx_http_map_conf_t *mcf; + + mcf = ngx_palloc(cf->pool, sizeof(ngx_http_map_conf_t)); + if (mcf == NULL) { + return NGX_CONF_ERROR; + } + + mcf->hash_max_size = NGX_CONF_UNSET_UINT; + mcf->hash_bucket_size = NGX_CONF_UNSET_UINT; + + return mcf; +} + + +static char * +ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + 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; + + if (mcf->hash_max_size == NGX_CONF_UNSET_UINT) { + mcf->hash_max_size = 2048; + } + + if (mcf->hash_bucket_size == NGX_CONF_UNSET_UINT) { + mcf->hash_bucket_size = ngx_cacheline_size; + + } else { + mcf->hash_bucket_size = ngx_align(mcf->hash_bucket_size, + ngx_cacheline_size); + } + + map = ngx_pcalloc(cf->pool, sizeof(ngx_http_map_ctx_t)); + if (map == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + name = value[1]; + name.len--; + name.data++; + + map->index = ngx_http_get_variable_index(cf, &name); + + if (map->index == NGX_ERROR) { + return NGX_CONF_ERROR; + } + + name = value[2]; + name.len--; + name.data++; + + var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGABLE); + if (var == NULL) { + return NGX_CONF_ERROR; + } + + var->handler = ngx_http_map_variable; + var->data = (uintptr_t) map; + + pool = ngx_create_pool(16384, cf->log); + if (pool == NULL) { + return NGX_CONF_ERROR; + } + + if (ngx_array_init(&ctx.keys, pool, 16384, sizeof(ngx_hash_key_t)) + != NGX_OK) + { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + + if (ngx_array_init(&ctx.dns_wildcards, pool, 16384, sizeof(ngx_hash_key_t)) + != NGX_OK) + { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + + ctx.keys_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH); + if (ctx.keys_hash == NULL) { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + + ctx.dns_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH); + if (ctx.dns_hash == NULL) { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + + ctx.values_hash = ngx_pcalloc(pool, + sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH); + if (ctx.values_hash == NULL) { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + + ctx.pool = cf->pool; + ctx.default_value = NULL; + ctx.hostnames = 0; + + save = *cf; + cf->pool = pool; + cf->ctx = &ctx; + cf->handler = ngx_http_map; + cf->handler_conf = conf; + + rv = ngx_conf_parse(cf, NULL); + + *cf = save; + + if (rv != NGX_CONF_OK) { + ngx_destroy_pool(pool); + + return rv; + } + + hash.key = ngx_hash_key_lc; + hash.max_size = mcf->hash_max_size; + hash.bucket_size = mcf->hash_bucket_size; + hash.name = "map_hash"; + hash.pool = cf->pool; + + if (ctx.keys.nelts) { + hash.hash = &map->hash; + hash.temp_pool = NULL; + + if (ngx_hash_init(&hash, ctx.keys.elts, ctx.keys.nelts) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + + map->default_value = ctx.default_value ? ctx.default_value: + &ngx_http_variable_null_value; + + if (ctx.dns_wildcards.nelts) { + + ngx_qsort(ctx.dns_wildcards.elts, (size_t) ctx.dns_wildcards.nelts, + sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards); + + hash.hash = NULL; + hash.temp_pool = pool; + + if (ngx_hash_wildcard_init(&hash, ctx.dns_wildcards.elts, + ctx.dns_wildcards.nelts) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + map->dns_wildcards = (ngx_hash_wildcard_t *) hash.hash; + } + + ngx_destroy_pool(pool); + + return rv; +} + + +static int ngx_libc_cdecl +ngx_http_map_cmp_dns_wildcards(const void *one, const void *two) +{ + ngx_hash_key_t *first, *second; + + first = (ngx_hash_key_t *) one; + second = (ngx_hash_key_t *) two; + + return ngx_strcmp(first->key.data, second->key.data); +} + + +static char * +ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) +{ + size_t len; + ngx_str_t *value, file, *name; + ngx_uint_t i, n, key; + ngx_hash_key_t *m; + ngx_http_map_conf_ctx_t *ctx; + ngx_http_variable_value_t *var, *old, **vp; + u_char buf[2048]; + + ctx = cf->ctx; + + value = cf->args->elts; + + if (cf->args->nelts == 1 + && ngx_strcmp(value[0].data, "hostnames") == 0) + { + ctx->hostnames = 1; + return NGX_CONF_OK; + + } else if (cf->args->nelts != 2) { + 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) == NGX_ERROR){ + return NGX_CONF_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); + + return ngx_conf_parse(cf, &file); + } + + key = 0; + + for (i = 0; i < value[1].len; i++) { + key = ngx_hash(key, value[1].data[i]); + } + + key %= NGX_HTTP_MAP_HASH; + + vp = ctx->values_hash[key].elts; + + if (vp) { + for (i = 0; i < ctx->values_hash[key].nelts; i++) { + if (value[1].len != (size_t) vp[i]->len) { + continue; + } + + if (ngx_strncmp(value[1].data, vp[i]->data, value[1].len) == 0) { + var = vp[i]; + goto found; + } + } + + } else { + if (ngx_array_init(&ctx->values_hash[key], cf->pool, 4, + sizeof(ngx_http_variable_value_t *)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + + var = ngx_palloc(ctx->pool, sizeof(ngx_http_variable_value_t)); + if (var == NULL) { + return NGX_CONF_ERROR; + } + + var->len = value[1].len; + var->data = ngx_pstrdup(ctx->pool, &value[1]); + if (var->data == NULL) { + return NGX_CONF_ERROR; + } + + var->valid = 1; + var->no_cachable = 0; + var->not_found = 0; + + vp = ngx_array_push(&ctx->values_hash[key]); + if (vp == NULL) { + return NGX_CONF_ERROR; + } + + *vp = var; + +found: + + if (value[0].data[0] != '*' || ctx->hostnames == 0) { + + if (ngx_strcmp(value[0].data, "default") != 0) { + + if (value[0].len && value[0].data[0] == '!') { + value[0].len--; + value[0].data++; + } + + key = 0; + + for (i = 0; i < value[0].len; i++) { + value[0].data[i] = ngx_tolower(value[0].data[i]); + key = ngx_hash(key, value[0].data[i]); + } + + key %= NGX_HTTP_MAP_HASH; + + name = ctx->keys_hash[key].elts; + + if (name) { + for (i = 0; i < ctx->keys_hash[key].nelts; i++) { + if (value[0].len != name[i].len) { + continue; + } + + if (ngx_strncmp(value[0].data, name[i].data, value[0].len) + == 0) + { + m = ctx->keys.elts; + for (i = 0; i < ctx->keys.nelts; i++) { + if (ngx_strcmp(value[0].data, m[i].key.data) == 0) { + old = m[i].value; + m[i].value = var; + + goto duplicate; + } + } + } + } + + } else { + if (ngx_array_init(&ctx->keys_hash[key], cf->pool, 4, + sizeof(ngx_str_t)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + + name = ngx_array_push(&ctx->keys_hash[key]); + if (name == NULL) { + return NGX_CONF_ERROR; + } + + *name = value[0]; + + m = ngx_array_push(&ctx->keys); + if (m == NULL) { + return NGX_CONF_ERROR; + } + + m->key = value[0]; + m->key_hash = ngx_hash_key(value[0].data, value[0].len); + m->value = var; + + } else { + if (ctx->default_value) { + old = ctx->default_value; + ctx->default_value = var; + + goto duplicate; + } + + ctx->default_value = var; + } + + } else { + + if (value[0].len < 3 || value[0].data[1] != '.') { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid DNS wildcard \"%V\"", &value[0]); + return NGX_CONF_ERROR; + } + + key = 0; + + for (i = 2; i < value[0].len; i++) { + value[0].data[i] = ngx_tolower(value[0].data[i]); + key = ngx_hash(key, value[0].data[i]); + } + + key %= NGX_HTTP_MAP_HASH; + + /* convert "*.example.com" into "com.example.\0" */ + + len = 0; + n = 0; + + for (i = value[0].len - 1; i; i--) { + if (value[0].data[i] == '.') { + ngx_memcpy(&buf[n], &value[0].data[i + 1], len); + n += len; + buf[n++] = '.'; + len = 0; + continue; + } + + len++; + } + + buf[n] = '\0'; + + name = ctx->dns_hash[key].elts; + + if (name) { + for (i = 0; i < ctx->dns_hash[key].nelts; i++) { + if (value[0].len != name[i].len) { + continue; + } + + if (ngx_strncmp(value[0].data, name[i].data, value[0].len) + == 0) + { + m = ctx->dns_wildcards.elts; + for (i = 0; i < ctx->dns_wildcards.nelts; i++) { + if (ngx_strcmp(buf, m[i].key.data) == 0) { + old = m[i].value; + m[i].value = var; + + goto duplicate; + } + } + } + } + + } else { + if (ngx_array_init(&ctx->dns_hash[key], cf->pool, 4, + sizeof(ngx_str_t)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + + name = ngx_array_push(&ctx->dns_hash[key]); + if (name == NULL) { + return NGX_CONF_ERROR; + } + + *name = value[0]; + + ngx_memcpy(value[0].data, buf, value[0].len); + value[0].len--; + + m = ngx_array_push(&ctx->dns_wildcards); + if (m == NULL) { + return NGX_CONF_ERROR; + } + + m->key = value[0]; + m->key_hash = 0; + m->value = var; + } + + return NGX_CONF_OK; + +duplicate: + + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "duplicate parameter \"%V\", value: \"%V\", " + "old value: \"%V\"", + &value[0], var, old); + + return NGX_CONF_OK; +} diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index afadc18ce..c39f32065 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -42,7 +42,7 @@ typedef struct { ngx_array_t *body_set; ngx_array_t *headers_set_len; ngx_array_t *headers_set; - ngx_hash_t *headers_set_hash; + ngx_hash0_t *headers_set_hash; ngx_array_t *headers_source; ngx_array_t *headers_names; @@ -1892,7 +1892,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) *code = (uintptr_t) NULL; - conf->headers_set_hash = ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); + conf->headers_set_hash = ngx_pcalloc(cf->pool, sizeof(ngx_hash0_t)); if (conf->headers_set_hash == NULL) { return NGX_CONF_ERROR; } @@ -1902,8 +1902,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) conf->headers_set_hash->bucket_size = sizeof(ngx_str_t); conf->headers_set_hash->name = "proxy_headers"; - if (ngx_hash_init(conf->headers_set_hash, cf->pool, - conf->headers_names->elts, conf->headers_names->nelts) != NGX_OK) + if (ngx_hash0_init(conf->headers_set_hash, cf->pool, + conf->headers_names->elts, conf->headers_names->nelts) + != NGX_OK) { return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index dd0e92fcd..c984f7e9e 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -186,6 +186,13 @@ static ngx_command_t ngx_http_ssi_filter_commands[] = { offsetof(ngx_http_ssi_conf_t, min_file_chunk), NULL }, + { ngx_string("ssi_value_length"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_ssi_conf_t, value_len), + NULL }, + { ngx_string("ssi_types"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_http_ssi_types, @@ -1728,7 +1735,13 @@ ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, value = params[NGX_HTTP_SSI_CONFIG_TIMEFMT]; if (value) { - ctx->timefmt = *value; + ctx->timefmt.len = value->len; + ctx->timefmt.data = ngx_palloc(r->pool, value->len + 1); + if (ctx->timefmt.data == NULL) { + return NGX_HTTP_SSI_ERROR; + } + + ngx_cpystrn(ctx->timefmt.data, value->data, value->len + 1); } value = params[NGX_HTTP_SSI_CONFIG_ERRMSG]; -- cgit v1.2.3