comparison src/http/modules/ngx_http_uwsgi_module.c @ 3566:b81d44244cb1

allow uwsgi_param to override client headers using HTTP_ parameters
author Igor Sysoev <igor@sysoev.ru>
date Fri, 04 Jun 2010 12:26:27 +0000
parents 1e86f0ac9a44
children 9bbfce117cfb
comparison
equal deleted inserted replaced
3565:1e86f0ac9a44 3566:b81d44244cb1
16 16
17 ngx_array_t *flushes; 17 ngx_array_t *flushes;
18 ngx_array_t *params_len; 18 ngx_array_t *params_len;
19 ngx_array_t *params; 19 ngx_array_t *params;
20 ngx_array_t *params_source; 20 ngx_array_t *params_source;
21
22 ngx_hash_t headers_hash;
23 ngx_uint_t header_params;
21 24
22 ngx_array_t *uwsgi_lengths; 25 ngx_array_t *uwsgi_lengths;
23 ngx_array_t *uwsgi_values; 26 ngx_array_t *uwsgi_values;
24 27
25 ngx_str_t uwsgi_string; 28 ngx_str_t uwsgi_string;
431 434
432 435
433 static ngx_int_t 436 static ngx_int_t
434 ngx_http_uwsgi_create_request(ngx_http_request_t *r) 437 ngx_http_uwsgi_create_request(ngx_http_request_t *r)
435 { 438 {
436 u_char ch; 439 u_char ch, *lowcase_key;
437 size_t key_len, val_len, len; 440 size_t key_len, val_len, len, allocated;
438 ngx_uint_t i, n; 441 ngx_uint_t i, n, hash, header_params;
439 ngx_buf_t *b; 442 ngx_buf_t *b;
440 ngx_chain_t *cl, *body; 443 ngx_chain_t *cl, *body;
441 ngx_list_part_t *part; 444 ngx_list_part_t *part;
442 ngx_table_elt_t *header; 445 ngx_table_elt_t *header, **ignored;
443 ngx_http_script_code_pt code; 446 ngx_http_script_code_pt code;
444 ngx_http_script_engine_t e, le; 447 ngx_http_script_engine_t e, le;
445 ngx_http_uwsgi_loc_conf_t *uwcf; 448 ngx_http_uwsgi_loc_conf_t *uwcf;
446 ngx_http_script_len_code_pt lcode; 449 ngx_http_script_len_code_pt lcode;
447 450
448 len = 0; 451 len = 0;
452 header_params = 0;
453 ignored = NULL;
449 454
450 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module); 455 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
451 456
452 if (uwcf->params_len) { 457 if (uwcf->params_len) {
453 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); 458 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
471 len += 2 + key_len + 2 + val_len; 476 len += 2 + key_len + 2 + val_len;
472 } 477 }
473 } 478 }
474 479
475 if (uwcf->upstream.pass_request_headers) { 480 if (uwcf->upstream.pass_request_headers) {
481
482 allocated = 0;
483 lowcase_key = NULL;
484
485 if (uwcf->header_params) {
486 ignored = ngx_palloc(r->pool, uwcf->header_params * sizeof(void *));
487 if (ignored == NULL) {
488 return NGX_ERROR;
489 }
490 }
476 491
477 part = &r->headers_in.headers.part; 492 part = &r->headers_in.headers.part;
478 header = part->elts; 493 header = part->elts;
479 494
480 for (i = 0; /* void */ ; i++) { 495 for (i = 0; /* void */ ; i++) {
487 part = part->next; 502 part = part->next;
488 header = part->elts; 503 header = part->elts;
489 i = 0; 504 i = 0;
490 } 505 }
491 506
492 len += 2 + 5 + header[i].key.len + 2 + header[i].value.len; 507 if (uwcf->header_params) {
508 if (allocated < header[i].key.len) {
509 allocated = header[i].key.len + 16;
510 lowcase_key = ngx_pnalloc(r->pool, allocated);
511 if (lowcase_key == NULL) {
512 return NGX_ERROR;
513 }
514 }
515
516 hash = 0;
517
518 for (n = 0; n < header[i].key.len; n++) {
519 ch = header[i].key.data[n];
520
521 if (ch >= 'A' && ch <= 'Z') {
522 ch |= 0x20;
523
524 } else if (ch == '-') {
525 ch = '_';
526 }
527
528 hash = ngx_hash(hash, ch);
529 lowcase_key[n] = ch;
530 }
531
532 if (ngx_hash_find(&uwcf->headers_hash, hash, lowcase_key, n)) {
533 ignored[header_params++] = &header[i];
534 continue;
535 }
536 }
537
538 len += 2 + sizeof("HTTP_") - 1 + header[i].key.len
539 + 2 + header[i].value.len;
493 } 540 }
494 } 541 }
495 542
496 len += uwcf->uwsgi_string.len; 543 len += uwcf->uwsgi_string.len;
497 544
581 part = part->next; 628 part = part->next;
582 header = part->elts; 629 header = part->elts;
583 i = 0; 630 i = 0;
584 } 631 }
585 632
586 key_len = 5 + header[i].key.len; 633 for (n = 0; n < header_params; n++) {
634 if (&header[i] == ignored[n]) {
635 goto next;
636 }
637 }
638
639 key_len = sizeof("HTTP_") - 1 + header[i].key.len;
587 *b->last++ = (u_char) (key_len & 0xff); 640 *b->last++ = (u_char) (key_len & 0xff);
588 *b->last++ = (u_char) ((key_len >> 8) & 0xff); 641 *b->last++ = (u_char) ((key_len >> 8) & 0xff);
589 642
590 b->last = ngx_cpymem(b->last, "HTTP_", 5); 643 b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
591 for (n = 0; n < header[i].key.len; n++) { 644 for (n = 0; n < header[i].key.len; n++) {
592 ch = header[i].key.data[n]; 645 ch = header[i].key.data[n];
593 646
594 if (ch >= 'a' && ch <= 'z') { 647 if (ch >= 'a' && ch <= 'z') {
595 ch &= ~0x20; 648 ch &= ~0x20;
608 661
609 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 662 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
610 "uwsgi param: \"%*s: %*s\"", 663 "uwsgi param: \"%*s: %*s\"",
611 key_len, b->last - (key_len + 2 + val_len), 664 key_len, b->last - (key_len + 2 + val_len),
612 val_len, b->last - val_len); 665 val_len, b->last - val_len);
666 next:
667
668 continue;
613 } 669 }
614 } 670 }
615 671
616 b->last = ngx_copy(b->last, uwcf->uwsgi_string.data, 672 b->last = ngx_copy(b->last, uwcf->uwsgi_string.data,
617 uwcf->uwsgi_string.len); 673 uwcf->uwsgi_string.len);
1128 1184
1129 u_char *p; 1185 u_char *p;
1130 size_t size; 1186 size_t size;
1131 uintptr_t *code; 1187 uintptr_t *code;
1132 ngx_uint_t i; 1188 ngx_uint_t i;
1189 ngx_array_t headers_names;
1133 ngx_keyval_t *src; 1190 ngx_keyval_t *src;
1191 ngx_hash_key_t *hk;
1134 ngx_hash_init_t hash; 1192 ngx_hash_init_t hash;
1135 ngx_http_script_compile_t sc; 1193 ngx_http_script_compile_t sc;
1136 ngx_http_script_copy_code_t *copy; 1194 ngx_http_script_copy_code_t *copy;
1137 1195
1138 if (conf->upstream.store != 0) { 1196 if (conf->upstream.store != 0) {
1322 if (conf->params_source == NULL) { 1380 if (conf->params_source == NULL) {
1323 conf->flushes = prev->flushes; 1381 conf->flushes = prev->flushes;
1324 conf->params_len = prev->params_len; 1382 conf->params_len = prev->params_len;
1325 conf->params = prev->params; 1383 conf->params = prev->params;
1326 conf->params_source = prev->params_source; 1384 conf->params_source = prev->params_source;
1385 conf->headers_hash = prev->headers_hash;
1327 1386
1328 if (conf->params_source == NULL) { 1387 if (conf->params_source == NULL) {
1329 return NGX_CONF_OK; 1388 return NGX_CONF_OK;
1330 } 1389 }
1331 } 1390 }
1338 conf->params = ngx_array_create(cf->pool, 512, 1); 1397 conf->params = ngx_array_create(cf->pool, 512, 1);
1339 if (conf->params == NULL) { 1398 if (conf->params == NULL) {
1340 return NGX_CONF_ERROR; 1399 return NGX_CONF_ERROR;
1341 } 1400 }
1342 1401
1402 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
1403 != NGX_OK)
1404 {
1405 return NGX_CONF_ERROR;
1406 }
1407
1343 src = conf->params_source->elts; 1408 src = conf->params_source->elts;
1344 for (i = 0; i < conf->params_source->nelts; i++) { 1409 for (i = 0; i < conf->params_source->nelts; i++) {
1410
1411 if (src[i].key.len > sizeof("HTTP_") - 1
1412 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
1413 {
1414 hk = ngx_array_push(&headers_names);
1415 if (hk == NULL) {
1416 return NGX_CONF_ERROR;
1417 }
1418
1419 hk->key.len = src[i].key.len - 5;
1420 hk->key.data = src[i].key.data + 5;
1421 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
1422 hk->value = (void *) 1;
1423
1424 if (src[i].value.len == 0) {
1425 continue;
1426 }
1427 }
1345 1428
1346 copy = ngx_array_push_n(conf->params_len, 1429 copy = ngx_array_push_n(conf->params_len,
1347 sizeof(ngx_http_script_copy_code_t)); 1430 sizeof(ngx_http_script_copy_code_t));
1348 if (copy == NULL) { 1431 if (copy == NULL) {
1349 return NGX_CONF_ERROR; 1432 return NGX_CONF_ERROR;
1401 if (code == NULL) { 1484 if (code == NULL) {
1402 return NGX_CONF_ERROR; 1485 return NGX_CONF_ERROR;
1403 } 1486 }
1404 1487
1405 *code = (uintptr_t) NULL; 1488 *code = (uintptr_t) NULL;
1489
1490 conf->header_params = headers_names.nelts;
1491
1492 hash.hash = &conf->headers_hash;
1493 hash.key = ngx_hash_key_lc;
1494 hash.max_size = 512;
1495 hash.bucket_size = 64;
1496 hash.name = "uwsgi_params_hash";
1497 hash.pool = cf->pool;
1498 hash.temp_pool = NULL;
1499
1500 if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK)
1501 {
1502 return NGX_CONF_ERROR;
1503 }
1406 1504
1407 return NGX_CONF_OK; 1505 return NGX_CONF_OK;
1408 } 1506 }
1409 1507
1410 1508