Mercurial > hg > nginx-vendor-0-7
comparison src/http/modules/ngx_http_map_module.c @ 140:55a211e5eeb7 NGINX_0_3_17
nginx 0.3.17
*) Change: now on Linux configure checks the presence of epoll and
sendfile64() in kernel.
*) Feature: the "map" directive supports domain names in the
".domain.tld" form.
*) Bugfix: the timeouts were not used in SSL handshake; bug appeared in
0.2.4.
*) Bugfix: in the HTTPS protocol in the "proxy_pass" directive.
*) Bugfix: when the HTTPS protocol was used in the "proxy_pass"
directive the port 80 was used by default.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Sun, 18 Dec 2005 00:00:00 +0300 |
parents | 8e6d4d96ec4c |
children | 84910468f6de |
comparison
equal
deleted
inserted
replaced
139:9cee8bc94578 | 140:55a211e5eeb7 |
---|---|
6 | 6 |
7 #include <ngx_config.h> | 7 #include <ngx_config.h> |
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 | 10 |
11 | |
12 #define NGX_HTTP_MAP_HASH 10007 | |
13 | 11 |
14 typedef struct { | 12 typedef struct { |
15 ngx_uint_t hash_max_size; | 13 ngx_uint_t hash_max_size; |
16 ngx_uint_t hash_bucket_size; | 14 ngx_uint_t hash_bucket_size; |
17 } ngx_http_map_conf_t; | 15 } ngx_http_map_conf_t; |
18 | 16 |
19 | 17 |
20 typedef struct { | 18 typedef struct { |
21 ngx_pool_t *pool; | 19 ngx_http_hash_conf_t hash; |
22 | |
23 ngx_array_t keys; | |
24 ngx_array_t *keys_hash; | |
25 | |
26 ngx_array_t dns_wildcards; | |
27 ngx_array_t *dns_hash; | |
28 | 20 |
29 ngx_array_t *values_hash; | 21 ngx_array_t *values_hash; |
30 | 22 |
31 ngx_http_variable_value_t *default_value; | 23 ngx_http_variable_value_t *default_value; |
32 ngx_uint_t hostnames; /* unsigned hostnames:1 */ | 24 ngx_uint_t hostnames; /* unsigned hostnames:1 */ |
251 pool = ngx_create_pool(16384, cf->log); | 243 pool = ngx_create_pool(16384, cf->log); |
252 if (pool == NULL) { | 244 if (pool == NULL) { |
253 return NGX_CONF_ERROR; | 245 return NGX_CONF_ERROR; |
254 } | 246 } |
255 | 247 |
256 if (ngx_array_init(&ctx.keys, pool, 16384, sizeof(ngx_hash_key_t)) | 248 if (ngx_array_init(&ctx.hash.keys, pool, 16384, sizeof(ngx_hash_key_t)) |
257 != NGX_OK) | 249 != NGX_OK) |
258 { | 250 { |
259 ngx_destroy_pool(pool); | 251 ngx_destroy_pool(pool); |
260 return NGX_CONF_ERROR; | 252 return NGX_CONF_ERROR; |
261 } | 253 } |
262 | 254 |
263 if (ngx_array_init(&ctx.dns_wildcards, pool, 16384, sizeof(ngx_hash_key_t)) | 255 if (ngx_array_init(&ctx.hash.dns_wildcards, pool, 16384, |
256 sizeof(ngx_hash_key_t)) | |
264 != NGX_OK) | 257 != NGX_OK) |
265 { | 258 { |
266 ngx_destroy_pool(pool); | 259 ngx_destroy_pool(pool); |
267 return NGX_CONF_ERROR; | 260 return NGX_CONF_ERROR; |
268 } | 261 } |
269 | 262 |
270 ctx.keys_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH); | 263 ctx.hash.keys_hash = ngx_pcalloc(pool, |
271 if (ctx.keys_hash == NULL) { | 264 sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH); |
265 if (ctx.hash.keys_hash == NULL) { | |
272 ngx_destroy_pool(pool); | 266 ngx_destroy_pool(pool); |
273 return NGX_CONF_ERROR; | 267 return NGX_CONF_ERROR; |
274 } | 268 } |
275 | 269 |
276 ctx.dns_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH); | 270 ctx.hash.dns_hash = ngx_pcalloc(pool, |
277 if (ctx.dns_hash == NULL) { | 271 sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH); |
272 if (ctx.hash.dns_hash == NULL) { | |
278 ngx_destroy_pool(pool); | 273 ngx_destroy_pool(pool); |
279 return NGX_CONF_ERROR; | 274 return NGX_CONF_ERROR; |
280 } | 275 } |
281 | 276 |
282 ctx.values_hash = ngx_pcalloc(pool, | 277 ctx.values_hash = ngx_pcalloc(pool, |
283 sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH); | 278 sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH); |
284 if (ctx.values_hash == NULL) { | 279 if (ctx.values_hash == NULL) { |
285 ngx_destroy_pool(pool); | 280 ngx_destroy_pool(pool); |
286 return NGX_CONF_ERROR; | 281 return NGX_CONF_ERROR; |
287 } | 282 } |
288 | 283 |
289 ctx.pool = cf->pool; | 284 ctx.hash.pool = cf->pool; |
285 ctx.hash.temp_pool = pool; | |
290 ctx.default_value = NULL; | 286 ctx.default_value = NULL; |
291 ctx.hostnames = 0; | 287 ctx.hostnames = 0; |
292 | 288 |
293 save = *cf; | 289 save = *cf; |
294 cf->pool = pool; | 290 cf->pool = pool; |
310 hash.max_size = mcf->hash_max_size; | 306 hash.max_size = mcf->hash_max_size; |
311 hash.bucket_size = mcf->hash_bucket_size; | 307 hash.bucket_size = mcf->hash_bucket_size; |
312 hash.name = "map_hash"; | 308 hash.name = "map_hash"; |
313 hash.pool = cf->pool; | 309 hash.pool = cf->pool; |
314 | 310 |
315 if (ctx.keys.nelts) { | 311 if (ctx.hash.keys.nelts) { |
316 hash.hash = &map->hash; | 312 hash.hash = &map->hash; |
317 hash.temp_pool = NULL; | 313 hash.temp_pool = NULL; |
318 | 314 |
319 if (ngx_hash_init(&hash, ctx.keys.elts, ctx.keys.nelts) != NGX_OK) { | 315 if (ngx_hash_init(&hash, ctx.hash.keys.elts, ctx.hash.keys.nelts) |
316 != NGX_OK) | |
317 { | |
320 return NGX_CONF_ERROR; | 318 return NGX_CONF_ERROR; |
321 } | 319 } |
322 } | 320 } |
323 | 321 |
324 map->default_value = ctx.default_value ? ctx.default_value: | 322 map->default_value = ctx.default_value ? ctx.default_value: |
325 &ngx_http_variable_null_value; | 323 &ngx_http_variable_null_value; |
326 | 324 |
327 if (ctx.dns_wildcards.nelts) { | 325 if (ctx.hash.dns_wildcards.nelts) { |
328 | 326 |
329 ngx_qsort(ctx.dns_wildcards.elts, (size_t) ctx.dns_wildcards.nelts, | 327 ngx_qsort(ctx.hash.dns_wildcards.elts, |
328 (size_t) ctx.hash.dns_wildcards.nelts, | |
330 sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards); | 329 sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards); |
331 | 330 |
332 hash.hash = NULL; | 331 hash.hash = NULL; |
333 hash.temp_pool = pool; | 332 hash.temp_pool = pool; |
334 | 333 |
335 if (ngx_hash_wildcard_init(&hash, ctx.dns_wildcards.elts, | 334 if (ngx_hash_wildcard_init(&hash, ctx.hash.dns_wildcards.elts, |
336 ctx.dns_wildcards.nelts) | 335 ctx.hash.dns_wildcards.nelts) |
337 != NGX_OK) | 336 != NGX_OK) |
338 { | 337 { |
339 return NGX_CONF_ERROR; | 338 return NGX_CONF_ERROR; |
340 } | 339 } |
341 | 340 |
361 | 360 |
362 | 361 |
363 static char * | 362 static char * |
364 ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) | 363 ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) |
365 { | 364 { |
366 size_t len; | 365 u_char ch; |
367 ngx_str_t *value, file, *name; | 366 ngx_int_t rc; |
368 ngx_uint_t i, n, key; | 367 ngx_str_t *value, file; |
369 ngx_hash_key_t *m; | 368 ngx_uint_t i, key, flags; |
370 ngx_http_map_conf_ctx_t *ctx; | 369 ngx_http_map_conf_ctx_t *ctx; |
371 ngx_http_variable_value_t *var, *old, **vp; | 370 ngx_http_variable_value_t *var, **vp; |
372 u_char buf[2048]; | |
373 | 371 |
374 ctx = cf->ctx; | 372 ctx = cf->ctx; |
375 | 373 |
376 value = cf->args->elts; | 374 value = cf->args->elts; |
377 | 375 |
408 | 406 |
409 for (i = 0; i < value[1].len; i++) { | 407 for (i = 0; i < value[1].len; i++) { |
410 key = ngx_hash(key, value[1].data[i]); | 408 key = ngx_hash(key, value[1].data[i]); |
411 } | 409 } |
412 | 410 |
413 key %= NGX_HTTP_MAP_HASH; | 411 key %= NGX_HTTP_CONFIG_HASH; |
414 | 412 |
415 vp = ctx->values_hash[key].elts; | 413 vp = ctx->values_hash[key].elts; |
416 | 414 |
417 if (vp) { | 415 if (vp) { |
418 for (i = 0; i < ctx->values_hash[key].nelts; i++) { | 416 for (i = 0; i < ctx->values_hash[key].nelts; i++) { |
433 { | 431 { |
434 return NGX_CONF_ERROR; | 432 return NGX_CONF_ERROR; |
435 } | 433 } |
436 } | 434 } |
437 | 435 |
438 var = ngx_palloc(ctx->pool, sizeof(ngx_http_variable_value_t)); | 436 var = ngx_palloc(ctx->hash.pool, sizeof(ngx_http_variable_value_t)); |
439 if (var == NULL) { | 437 if (var == NULL) { |
440 return NGX_CONF_ERROR; | 438 return NGX_CONF_ERROR; |
441 } | 439 } |
442 | 440 |
443 var->len = value[1].len; | 441 var->len = value[1].len; |
444 var->data = ngx_pstrdup(ctx->pool, &value[1]); | 442 var->data = ngx_pstrdup(ctx->hash.pool, &value[1]); |
445 if (var->data == NULL) { | 443 if (var->data == NULL) { |
446 return NGX_CONF_ERROR; | 444 return NGX_CONF_ERROR; |
447 } | 445 } |
448 | 446 |
449 var->valid = 1; | 447 var->valid = 1; |
457 | 455 |
458 *vp = var; | 456 *vp = var; |
459 | 457 |
460 found: | 458 found: |
461 | 459 |
462 if (value[0].data[0] != '*' || ctx->hostnames == 0) { | 460 ch = value[0].data[0]; |
463 | 461 |
464 if (ngx_strcmp(value[0].data, "default") != 0) { | 462 if ((ch != '*' && ch != '.') || ctx->hostnames == 0) { |
465 | 463 |
466 if (value[0].len && value[0].data[0] == '!') { | 464 if (ngx_strcmp(value[0].data, "default") == 0) { |
467 value[0].len--; | 465 |
468 value[0].data++; | 466 if (ctx->default_value) { |
469 } | 467 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
470 | 468 "duplicate default map parameter"); |
471 key = 0; | |
472 | |
473 for (i = 0; i < value[0].len; i++) { | |
474 value[0].data[i] = ngx_tolower(value[0].data[i]); | |
475 key = ngx_hash(key, value[0].data[i]); | |
476 } | |
477 | |
478 key %= NGX_HTTP_MAP_HASH; | |
479 | |
480 name = ctx->keys_hash[key].elts; | |
481 | |
482 if (name) { | |
483 for (i = 0; i < ctx->keys_hash[key].nelts; i++) { | |
484 if (value[0].len != name[i].len) { | |
485 continue; | |
486 } | |
487 | |
488 if (ngx_strncmp(value[0].data, name[i].data, value[0].len) | |
489 == 0) | |
490 { | |
491 m = ctx->keys.elts; | |
492 for (i = 0; i < ctx->keys.nelts; i++) { | |
493 if (ngx_strcmp(value[0].data, m[i].key.data) == 0) { | |
494 old = m[i].value; | |
495 m[i].value = var; | |
496 | |
497 goto duplicate; | |
498 } | |
499 } | |
500 } | |
501 } | |
502 | |
503 } else { | |
504 if (ngx_array_init(&ctx->keys_hash[key], cf->pool, 4, | |
505 sizeof(ngx_str_t)) | |
506 != NGX_OK) | |
507 { | |
508 return NGX_CONF_ERROR; | |
509 } | |
510 } | |
511 | |
512 name = ngx_array_push(&ctx->keys_hash[key]); | |
513 if (name == NULL) { | |
514 return NGX_CONF_ERROR; | 469 return NGX_CONF_ERROR; |
515 } | 470 } |
516 | 471 |
517 *name = value[0]; | |
518 | |
519 m = ngx_array_push(&ctx->keys); | |
520 if (m == NULL) { | |
521 return NGX_CONF_ERROR; | |
522 } | |
523 | |
524 m->key = value[0]; | |
525 m->key_hash = ngx_hash_key(value[0].data, value[0].len); | |
526 m->value = var; | |
527 | |
528 } else { | |
529 if (ctx->default_value) { | |
530 old = ctx->default_value; | |
531 ctx->default_value = var; | |
532 | |
533 goto duplicate; | |
534 } | |
535 | |
536 ctx->default_value = var; | 472 ctx->default_value = var; |
537 } | 473 |
474 return NGX_CONF_OK; | |
475 } | |
476 | |
477 if (value[0].len && ch == '!') { | |
478 value[0].len--; | |
479 value[0].data++; | |
480 } | |
481 | |
482 flags = 0; | |
538 | 483 |
539 } else { | 484 } else { |
540 | 485 |
541 if (value[0].len < 3 || value[0].data[1] != '.') { | 486 if ((ch == '*' && (value[0].len < 3 || value[0].data[1] != '.')) |
487 || (ch == '.' && value[0].len < 2)) | |
488 { | |
542 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 489 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
543 "invalid DNS wildcard \"%V\"", &value[0]); | 490 "invalid DNS wildcard \"%V\"", &value[0]); |
491 | |
544 return NGX_CONF_ERROR; | 492 return NGX_CONF_ERROR; |
545 } | 493 } |
546 | 494 |
547 key = 0; | 495 flags = NGX_HTTP_WILDCARD_HASH; |
548 | 496 } |
549 for (i = 2; i < value[0].len; i++) { | 497 |
550 value[0].data[i] = ngx_tolower(value[0].data[i]); | 498 rc = ngx_http_config_add_hash(&ctx->hash, &value[0], var, flags); |
551 key = ngx_hash(key, value[0].data[i]); | 499 |
552 } | 500 if (rc == NGX_OK) { |
553 | 501 return NGX_CONF_OK; |
554 key %= NGX_HTTP_MAP_HASH; | 502 } |
555 | 503 |
556 /* convert "*.example.com" into "com.example.\0" */ | 504 if (rc == NGX_BUSY) { |
557 | 505 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
558 len = 0; | 506 "conflicting parameter \"%V\"", &value[0]); |
559 n = 0; | 507 } |
560 | 508 |
561 for (i = value[0].len - 1; i; i--) { | 509 return NGX_CONF_ERROR; |
562 if (value[0].data[i] == '.') { | |
563 ngx_memcpy(&buf[n], &value[0].data[i + 1], len); | |
564 n += len; | |
565 buf[n++] = '.'; | |
566 len = 0; | |
567 continue; | |
568 } | |
569 | |
570 len++; | |
571 } | |
572 | |
573 buf[n] = '\0'; | |
574 | |
575 name = ctx->dns_hash[key].elts; | |
576 | |
577 if (name) { | |
578 for (i = 0; i < ctx->dns_hash[key].nelts; i++) { | |
579 if (value[0].len != name[i].len) { | |
580 continue; | |
581 } | |
582 | |
583 if (ngx_strncmp(value[0].data, name[i].data, value[0].len) | |
584 == 0) | |
585 { | |
586 m = ctx->dns_wildcards.elts; | |
587 for (i = 0; i < ctx->dns_wildcards.nelts; i++) { | |
588 if (ngx_strcmp(buf, m[i].key.data) == 0) { | |
589 old = m[i].value; | |
590 m[i].value = var; | |
591 | |
592 goto duplicate; | |
593 } | |
594 } | |
595 } | |
596 } | |
597 | |
598 } else { | |
599 if (ngx_array_init(&ctx->dns_hash[key], cf->pool, 4, | |
600 sizeof(ngx_str_t)) | |
601 != NGX_OK) | |
602 { | |
603 return NGX_CONF_ERROR; | |
604 } | |
605 } | |
606 | |
607 name = ngx_array_push(&ctx->dns_hash[key]); | |
608 if (name == NULL) { | |
609 return NGX_CONF_ERROR; | |
610 } | |
611 | |
612 *name = value[0]; | |
613 | |
614 ngx_memcpy(value[0].data, buf, value[0].len); | |
615 value[0].len--; | |
616 | |
617 m = ngx_array_push(&ctx->dns_wildcards); | |
618 if (m == NULL) { | |
619 return NGX_CONF_ERROR; | |
620 } | |
621 | |
622 m->key = value[0]; | |
623 m->key_hash = 0; | |
624 m->value = var; | |
625 } | |
626 | |
627 return NGX_CONF_OK; | |
628 | |
629 duplicate: | |
630 | |
631 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
632 "duplicate parameter \"%V\", value: \"%V\", " | |
633 "old value: \"%V\"", | |
634 &value[0], var, old); | |
635 | |
636 return NGX_CONF_OK; | |
637 } | 510 } |