Mercurial > hg > nginx
comparison src/http/modules/ngx_http_map_module.c @ 6535:db699978a33f
Map: support of complex values in resulting strings.
author | Dmitry Volyntsev <xeioex@nginx.com> |
---|---|
date | Thu, 12 May 2016 16:43:19 +0300 |
parents | f01ab2dbcfdc |
children | 014905eb7b3d |
comparison
equal
deleted
inserted
replaced
6534:19a54ba76c04 | 6535:db699978a33f |
---|---|
18 | 18 |
19 typedef struct { | 19 typedef struct { |
20 ngx_hash_keys_arrays_t keys; | 20 ngx_hash_keys_arrays_t keys; |
21 | 21 |
22 ngx_array_t *values_hash; | 22 ngx_array_t *values_hash; |
23 ngx_array_t var_values; | |
24 #if (NGX_PCRE) | 23 #if (NGX_PCRE) |
25 ngx_array_t regexes; | 24 ngx_array_t regexes; |
26 #endif | 25 #endif |
27 | 26 |
28 ngx_http_variable_value_t *default_value; | 27 ngx_http_variable_value_t *default_value; |
108 ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, | 107 ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, |
109 uintptr_t data) | 108 uintptr_t data) |
110 { | 109 { |
111 ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data; | 110 ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data; |
112 | 111 |
113 ngx_str_t val; | 112 ngx_str_t val, str; |
113 ngx_http_complex_value_t *cv; | |
114 ngx_http_variable_value_t *value; | 114 ngx_http_variable_value_t *value; |
115 | 115 |
116 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 116 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
117 "http map started"); | 117 "http map started"); |
118 | 118 |
129 if (value == NULL) { | 129 if (value == NULL) { |
130 value = map->default_value; | 130 value = map->default_value; |
131 } | 131 } |
132 | 132 |
133 if (!value->valid) { | 133 if (!value->valid) { |
134 value = ngx_http_get_flushed_variable(r, (uintptr_t) value->data); | 134 cv = (ngx_http_complex_value_t *) value->data; |
135 | 135 |
136 if (value == NULL || value->not_found) { | 136 if (ngx_http_complex_value(r, cv, &str) != NGX_OK) { |
137 value = &ngx_http_variable_null_value; | 137 return NGX_ERROR; |
138 } | 138 } |
139 } | 139 |
140 | 140 v->valid = 1; |
141 *v = *value; | 141 v->no_cacheable = 0; |
142 v->not_found = 0; | |
143 v->len = str.len; | |
144 v->data = str.data; | |
145 | |
146 } else { | |
147 *v = *value; | |
148 } | |
142 | 149 |
143 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 150 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
144 "http map: \"%V\" \"%v\"", &val, v); | 151 "http map: \"%V\" \"%v\"", &val, v); |
145 | 152 |
146 return NGX_OK; | 153 return NGX_OK; |
244 if (ctx.values_hash == NULL) { | 251 if (ctx.values_hash == NULL) { |
245 ngx_destroy_pool(pool); | 252 ngx_destroy_pool(pool); |
246 return NGX_CONF_ERROR; | 253 return NGX_CONF_ERROR; |
247 } | 254 } |
248 | 255 |
249 if (ngx_array_init(&ctx.var_values, cf->pool, 2, | |
250 sizeof(ngx_http_variable_value_t)) | |
251 != NGX_OK) | |
252 { | |
253 ngx_destroy_pool(pool); | |
254 return NGX_CONF_ERROR; | |
255 } | |
256 | |
257 #if (NGX_PCRE) | 256 #if (NGX_PCRE) |
258 if (ngx_array_init(&ctx.regexes, cf->pool, 2, sizeof(ngx_http_map_regex_t)) | 257 if (ngx_array_init(&ctx.regexes, cf->pool, 2, sizeof(ngx_http_map_regex_t)) |
259 != NGX_OK) | 258 != NGX_OK) |
260 { | 259 { |
261 ngx_destroy_pool(pool); | 260 ngx_destroy_pool(pool); |
373 | 372 |
374 | 373 |
375 static char * | 374 static char * |
376 ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) | 375 ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) |
377 { | 376 { |
378 ngx_int_t rv, index; | 377 u_char *data; |
379 ngx_str_t *value, name; | 378 size_t len; |
380 ngx_uint_t i, key; | 379 ngx_int_t rv; |
381 ngx_http_map_conf_ctx_t *ctx; | 380 ngx_str_t *value, v; |
382 ngx_http_variable_value_t *var, **vp; | 381 ngx_uint_t i, key; |
382 ngx_http_map_conf_ctx_t *ctx; | |
383 ngx_http_complex_value_t cv, *cvp; | |
384 ngx_http_variable_value_t *var, **vp; | |
385 ngx_http_compile_complex_value_t ccv; | |
383 | 386 |
384 ctx = cf->ctx; | 387 ctx = cf->ctx; |
385 | 388 |
386 value = cf->args->elts; | 389 value = cf->args->elts; |
387 | 390 |
399 | 402 |
400 if (ngx_strcmp(value[0].data, "include") == 0) { | 403 if (ngx_strcmp(value[0].data, "include") == 0) { |
401 return ngx_conf_include(cf, dummy, conf); | 404 return ngx_conf_include(cf, dummy, conf); |
402 } | 405 } |
403 | 406 |
404 if (value[1].data[0] == '$') { | |
405 name = value[1]; | |
406 name.len--; | |
407 name.data++; | |
408 | |
409 index = ngx_http_get_variable_index(ctx->cf, &name); | |
410 if (index == NGX_ERROR) { | |
411 return NGX_CONF_ERROR; | |
412 } | |
413 | |
414 var = ctx->var_values.elts; | |
415 | |
416 for (i = 0; i < ctx->var_values.nelts; i++) { | |
417 if (index == (intptr_t) var[i].data) { | |
418 var = &var[i]; | |
419 goto found; | |
420 } | |
421 } | |
422 | |
423 var = ngx_array_push(&ctx->var_values); | |
424 if (var == NULL) { | |
425 return NGX_CONF_ERROR; | |
426 } | |
427 | |
428 var->valid = 0; | |
429 var->no_cacheable = 0; | |
430 var->not_found = 0; | |
431 var->len = 0; | |
432 var->data = (u_char *) (intptr_t) index; | |
433 | |
434 goto found; | |
435 } | |
436 | |
437 key = 0; | 407 key = 0; |
438 | 408 |
439 for (i = 0; i < value[1].len; i++) { | 409 for (i = 0; i < value[1].len; i++) { |
440 key = ngx_hash(key, value[1].data[i]); | 410 key = ngx_hash(key, value[1].data[i]); |
441 } | 411 } |
444 | 414 |
445 vp = ctx->values_hash[key].elts; | 415 vp = ctx->values_hash[key].elts; |
446 | 416 |
447 if (vp) { | 417 if (vp) { |
448 for (i = 0; i < ctx->values_hash[key].nelts; i++) { | 418 for (i = 0; i < ctx->values_hash[key].nelts; i++) { |
449 if (value[1].len != (size_t) vp[i]->len) { | 419 |
420 if (vp[i]->valid) { | |
421 data = vp[i]->data; | |
422 len = vp[i]->len; | |
423 | |
424 } else { | |
425 cvp = (ngx_http_complex_value_t *) vp[i]->data; | |
426 data = cvp->value.data; | |
427 len = cvp->value.len; | |
428 } | |
429 | |
430 if (value[1].len != len) { | |
450 continue; | 431 continue; |
451 } | 432 } |
452 | 433 |
453 if (ngx_strncmp(value[1].data, vp[i]->data, value[1].len) == 0) { | 434 if (ngx_strncmp(value[1].data, data, len) == 0) { |
454 var = vp[i]; | 435 var = vp[i]; |
455 goto found; | 436 goto found; |
456 } | 437 } |
457 } | 438 } |
458 | 439 |
468 var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t)); | 449 var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t)); |
469 if (var == NULL) { | 450 if (var == NULL) { |
470 return NGX_CONF_ERROR; | 451 return NGX_CONF_ERROR; |
471 } | 452 } |
472 | 453 |
473 var->len = value[1].len; | 454 v.len = value[1].len; |
474 var->data = ngx_pstrdup(ctx->keys.pool, &value[1]); | 455 v.data = ngx_pstrdup(ctx->keys.pool, &value[1]); |
475 if (var->data == NULL) { | 456 if (v.data == NULL) { |
476 return NGX_CONF_ERROR; | 457 return NGX_CONF_ERROR; |
477 } | 458 } |
478 | 459 |
479 var->valid = 1; | 460 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
461 | |
462 ccv.cf = ctx->cf; | |
463 ccv.value = &v; | |
464 ccv.complex_value = &cv; | |
465 | |
466 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
467 return NGX_CONF_ERROR; | |
468 } | |
469 | |
470 if (cv.lengths != NULL) { | |
471 cvp = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_complex_value_t)); | |
472 if (cvp == NULL) { | |
473 return NGX_CONF_ERROR; | |
474 } | |
475 | |
476 *cvp = cv; | |
477 | |
478 var->len = 0; | |
479 var->data = (u_char *) cvp; | |
480 var->valid = 0; | |
481 | |
482 } else { | |
483 var->len = v.len; | |
484 var->data = v.data; | |
485 var->valid = 1; | |
486 } | |
487 | |
480 var->no_cacheable = 0; | 488 var->no_cacheable = 0; |
481 var->not_found = 0; | 489 var->not_found = 0; |
482 | 490 |
483 vp = ngx_array_push(&ctx->values_hash[key]); | 491 vp = ngx_array_push(&ctx->values_hash[key]); |
484 if (vp == NULL) { | 492 if (vp == NULL) { |