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,