Mercurial > hg > nginx-vendor-current
comparison src/http/modules/ngx_http_map_module.c @ 604:428c6e58046a NGINX_0_9_0
nginx 0.9.0
*) Feature: the "keepalive_disable" directive.
*) Feature: the "map" directive supports variables as value of a
defined variable.
*) Feature: the "map" directive supports empty strings as value of the
first parameter.
*) Feature: the "map" directive supports expressions as the first
parameter.
*) Feature: nginx(8) manual page.
Thanks to Sergey Osokin.
*) Feature: Linux accept4() support.
Thanks to Simon Liu.
*) Workaround: elimination of Linux linker warning about "sys_errlist"
and "sys_nerr"; the warning had appeared in 0.8.35.
*) Bugfix: a segmentation fault might occur in a worker process, if the
"auth_basic" directive was used.
Thanks to Michail Laletin.
*) Bugfix: compatibility with ngx_http_eval_module; the bug had
appeared in 0.8.42.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 29 Nov 2010 00:00:00 +0300 |
parents | c456a023113c |
children | 8214eaef3530 |
comparison
equal
deleted
inserted
replaced
603:94ea26a3b3aa | 604:428c6e58046a |
---|---|
17 | 17 |
18 typedef struct { | 18 typedef struct { |
19 ngx_hash_keys_arrays_t keys; | 19 ngx_hash_keys_arrays_t keys; |
20 | 20 |
21 ngx_array_t *values_hash; | 21 ngx_array_t *values_hash; |
22 ngx_array_t var_values; | |
22 | 23 |
23 ngx_http_variable_value_t *default_value; | 24 ngx_http_variable_value_t *default_value; |
25 ngx_conf_t *cf; | |
24 ngx_uint_t hostnames; /* unsigned hostnames:1 */ | 26 ngx_uint_t hostnames; /* unsigned hostnames:1 */ |
25 } ngx_http_map_conf_ctx_t; | 27 } ngx_http_map_conf_ctx_t; |
26 | 28 |
27 | 29 |
28 typedef struct { | 30 typedef struct { |
29 ngx_hash_combined_t hash; | 31 ngx_hash_combined_t hash; |
30 ngx_int_t index; | 32 ngx_http_complex_value_t value; |
31 ngx_http_variable_value_t *default_value; | 33 ngx_http_variable_value_t *default_value; |
32 ngx_uint_t hostnames; /* unsigned hostnames:1 */ | 34 ngx_uint_t hostnames; /* unsigned hostnames:1 */ |
33 } ngx_http_map_ctx_t; | 35 } ngx_http_map_ctx_t; |
34 | 36 |
35 | 37 |
103 uintptr_t data) | 105 uintptr_t data) |
104 { | 106 { |
105 ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data; | 107 ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data; |
106 | 108 |
107 size_t len; | 109 size_t len; |
108 u_char *name; | 110 ngx_str_t val; |
109 ngx_uint_t key; | 111 ngx_uint_t key; |
110 ngx_http_variable_value_t *vv, *value; | 112 ngx_http_variable_value_t *value; |
111 | 113 |
112 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 114 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
113 "http map started"); | 115 "http map started"); |
114 | 116 |
115 vv = ngx_http_get_flushed_variable(r, map->index); | 117 if (ngx_http_complex_value(r, &map->value, &val) != NGX_OK) { |
116 | 118 return NGX_ERROR; |
117 if (vv == NULL || vv->not_found) { | 119 } |
118 *v = *map->default_value; | 120 |
119 return NGX_OK; | 121 len = val.len; |
120 } | 122 |
121 | 123 if (len && map->hostnames && val.data[len - 1] == '.') { |
122 len = vv->len; | |
123 | |
124 if (len && map->hostnames && vv->data[len - 1] == '.') { | |
125 len--; | 124 len--; |
126 } | 125 } |
127 | 126 |
128 if (len == 0) { | 127 key = ngx_hash_strlow(val.data, val.data, len); |
129 *v = *map->default_value; | 128 |
130 return NGX_OK; | 129 value = ngx_hash_find_combined(&map->hash, key, val.data, len); |
131 } | 130 |
132 | 131 if (value == NULL) { |
133 name = ngx_pnalloc(r->pool, len); | 132 value = map->default_value; |
134 if (name == NULL) { | 133 } |
135 return NGX_ERROR; | 134 |
136 } | 135 if (!value->valid) { |
137 | 136 value = ngx_http_get_flushed_variable(r, (ngx_uint_t) value->data); |
138 key = ngx_hash_strlow(name, vv->data, len); | 137 |
139 | 138 if (value == NULL || value->not_found) { |
140 value = ngx_hash_find_combined(&map->hash, key, name, len); | 139 value = &ngx_http_variable_null_value; |
141 | 140 } |
142 if (value) { | 141 } |
143 *v = *value; | 142 |
144 | 143 *v = *value; |
145 } else { | |
146 *v = *map->default_value; | |
147 } | |
148 | 144 |
149 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 145 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
150 "http map: \"%v\" \"%v\"", vv, v); | 146 "http map: \"%v\" \"%v\"", &val, v); |
151 | 147 |
152 return NGX_OK; | 148 return NGX_OK; |
153 } | 149 } |
154 | 150 |
155 | 151 |
173 static char * | 169 static char * |
174 ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 170 ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
175 { | 171 { |
176 ngx_http_map_conf_t *mcf = conf; | 172 ngx_http_map_conf_t *mcf = conf; |
177 | 173 |
178 char *rv; | 174 char *rv; |
179 ngx_str_t *value, name; | 175 ngx_str_t *value, name; |
180 ngx_conf_t save; | 176 ngx_conf_t save; |
181 ngx_pool_t *pool; | 177 ngx_pool_t *pool; |
182 ngx_hash_init_t hash; | 178 ngx_hash_init_t hash; |
183 ngx_http_map_ctx_t *map; | 179 ngx_http_map_ctx_t *map; |
184 ngx_http_variable_t *var; | 180 ngx_http_variable_t *var; |
185 ngx_http_map_conf_ctx_t ctx; | 181 ngx_http_map_conf_ctx_t ctx; |
182 ngx_http_compile_complex_value_t ccv; | |
186 | 183 |
187 if (mcf->hash_max_size == NGX_CONF_UNSET_UINT) { | 184 if (mcf->hash_max_size == NGX_CONF_UNSET_UINT) { |
188 mcf->hash_max_size = 2048; | 185 mcf->hash_max_size = 2048; |
189 } | 186 } |
190 | 187 |
201 return NGX_CONF_ERROR; | 198 return NGX_CONF_ERROR; |
202 } | 199 } |
203 | 200 |
204 value = cf->args->elts; | 201 value = cf->args->elts; |
205 | 202 |
206 name = value[1]; | 203 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
207 name.len--; | 204 |
208 name.data++; | 205 ccv.cf = cf; |
209 | 206 ccv.value = &value[1]; |
210 map->index = ngx_http_get_variable_index(cf, &name); | 207 ccv.complex_value = &map->value; |
211 | 208 |
212 if (map->index == NGX_ERROR) { | 209 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { |
213 return NGX_CONF_ERROR; | 210 return NGX_CONF_ERROR; |
214 } | 211 } |
215 | 212 |
216 name = value[2]; | 213 name = value[2]; |
217 name.len--; | 214 name.len--; |
242 if (ctx.values_hash == NULL) { | 239 if (ctx.values_hash == NULL) { |
243 ngx_destroy_pool(pool); | 240 ngx_destroy_pool(pool); |
244 return NGX_CONF_ERROR; | 241 return NGX_CONF_ERROR; |
245 } | 242 } |
246 | 243 |
244 if (ngx_array_init(&ctx.var_values, cf->pool, 2, | |
245 sizeof(ngx_http_variable_value_t)) | |
246 != NGX_OK) | |
247 { | |
248 ngx_destroy_pool(pool); | |
249 return NGX_CONF_ERROR; | |
250 } | |
251 | |
247 ctx.default_value = NULL; | 252 ctx.default_value = NULL; |
253 ctx.cf = &save; | |
248 ctx.hostnames = 0; | 254 ctx.hostnames = 0; |
249 | 255 |
250 save = *cf; | 256 save = *cf; |
251 cf->pool = pool; | 257 cf->pool = pool; |
252 cf->ctx = &ctx; | 258 cf->ctx = &ctx; |
342 | 348 |
343 | 349 |
344 static char * | 350 static char * |
345 ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) | 351 ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) |
346 { | 352 { |
347 ngx_int_t rc; | 353 ngx_int_t rc, index; |
348 ngx_str_t *value, file; | 354 ngx_str_t *value, file, name; |
349 ngx_uint_t i, key; | 355 ngx_uint_t i, key; |
350 ngx_http_map_conf_ctx_t *ctx; | 356 ngx_http_map_conf_ctx_t *ctx; |
351 ngx_http_variable_value_t *var, **vp; | 357 ngx_http_variable_value_t *var, **vp; |
352 | 358 |
353 ctx = cf->ctx; | 359 ctx = cf->ctx; |
362 | 368 |
363 } else if (cf->args->nelts != 2) { | 369 } else if (cf->args->nelts != 2) { |
364 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 370 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
365 "invalid number of the map parameters"); | 371 "invalid number of the map parameters"); |
366 return NGX_CONF_ERROR; | 372 return NGX_CONF_ERROR; |
367 | |
368 } else if (value[0].len == 0) { | |
369 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
370 "invalid first parameter"); | |
371 return NGX_CONF_ERROR; | |
372 } | 373 } |
373 | 374 |
374 if (ngx_strcmp(value[0].data, "include") == 0) { | 375 if (ngx_strcmp(value[0].data, "include") == 0) { |
375 file = value[1]; | 376 file = value[1]; |
376 | 377 |
379 } | 380 } |
380 | 381 |
381 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); | 382 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); |
382 | 383 |
383 return ngx_conf_parse(cf, &file); | 384 return ngx_conf_parse(cf, &file); |
385 } | |
386 | |
387 if (value[1].data[0] == '$') { | |
388 name = value[1]; | |
389 name.len--; | |
390 name.data++; | |
391 | |
392 index = ngx_http_get_variable_index(ctx->cf, &name); | |
393 if (index == NGX_ERROR) { | |
394 return NGX_CONF_ERROR; | |
395 } | |
396 | |
397 var = ctx->var_values.elts; | |
398 | |
399 for (i = 0; i < ctx->var_values.nelts; i++) { | |
400 if (index == (ngx_int_t) var[i].data) { | |
401 goto found; | |
402 } | |
403 } | |
404 | |
405 var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t)); | |
406 if (var == NULL) { | |
407 return NGX_CONF_ERROR; | |
408 } | |
409 | |
410 var->valid = 0; | |
411 var->no_cacheable = 0; | |
412 var->not_found = 0; | |
413 var->len = 0; | |
414 var->data = (u_char *) index; | |
415 | |
416 vp = ngx_array_push(&ctx->var_values); | |
417 if (vp == NULL) { | |
418 return NGX_CONF_ERROR; | |
419 } | |
420 | |
421 *vp = var; | |
422 | |
423 goto found; | |
384 } | 424 } |
385 | 425 |
386 key = 0; | 426 key = 0; |
387 | 427 |
388 for (i = 0; i < value[1].len; i++) { | 428 for (i = 0; i < value[1].len; i++) { |
449 ctx->default_value = var; | 489 ctx->default_value = var; |
450 | 490 |
451 return NGX_CONF_OK; | 491 return NGX_CONF_OK; |
452 } | 492 } |
453 | 493 |
454 if (value[0].len && value[0].data[0] == '!') { | 494 if (value[0].len && value[0].data[0] == '\\') { |
455 value[0].len--; | 495 value[0].len--; |
456 value[0].data++; | 496 value[0].data++; |
457 } | 497 } |
458 | 498 |
459 rc = ngx_hash_add_key(&ctx->keys, &value[0], var, | 499 rc = ngx_hash_add_key(&ctx->keys, &value[0], var, |