# HG changeset patch # User Igor Sysoev # Date 1275654387 0 # Node ID b81d44244cb160b8e8c5b17bcdbdc28c09618ad3 # Parent 1e86f0ac9a44560c56675bd9de668b9feb3ab575 allow uwsgi_param to override client headers using HTTP_ parameters diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -19,6 +19,9 @@ typedef struct { ngx_array_t *params; ngx_array_t *params_source; + ngx_hash_t headers_hash; + ngx_uint_t header_params; + ngx_array_t *uwsgi_lengths; ngx_array_t *uwsgi_values; @@ -433,19 +436,21 @@ ngx_http_uwsgi_eval(ngx_http_request_t * static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r) { - u_char ch; - size_t key_len, val_len, len; - ngx_uint_t i, n; + u_char ch, *lowcase_key; + size_t key_len, val_len, len, allocated; + ngx_uint_t i, n, hash, header_params; ngx_buf_t *b; ngx_chain_t *cl, *body; ngx_list_part_t *part; - ngx_table_elt_t *header; + ngx_table_elt_t *header, **ignored; ngx_http_script_code_pt code; ngx_http_script_engine_t e, le; ngx_http_uwsgi_loc_conf_t *uwcf; ngx_http_script_len_code_pt lcode; len = 0; + header_params = 0; + ignored = NULL; uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module); @@ -474,6 +479,16 @@ ngx_http_uwsgi_create_request(ngx_http_r if (uwcf->upstream.pass_request_headers) { + allocated = 0; + lowcase_key = NULL; + + if (uwcf->header_params) { + ignored = ngx_palloc(r->pool, uwcf->header_params * sizeof(void *)); + if (ignored == NULL) { + return NGX_ERROR; + } + } + part = &r->headers_in.headers.part; header = part->elts; @@ -489,7 +504,39 @@ ngx_http_uwsgi_create_request(ngx_http_r i = 0; } - len += 2 + 5 + header[i].key.len + 2 + header[i].value.len; + if (uwcf->header_params) { + if (allocated < header[i].key.len) { + allocated = header[i].key.len + 16; + lowcase_key = ngx_pnalloc(r->pool, allocated); + if (lowcase_key == NULL) { + return NGX_ERROR; + } + } + + hash = 0; + + for (n = 0; n < header[i].key.len; n++) { + ch = header[i].key.data[n]; + + if (ch >= 'A' && ch <= 'Z') { + ch |= 0x20; + + } else if (ch == '-') { + ch = '_'; + } + + hash = ngx_hash(hash, ch); + lowcase_key[n] = ch; + } + + if (ngx_hash_find(&uwcf->headers_hash, hash, lowcase_key, n)) { + ignored[header_params++] = &header[i]; + continue; + } + } + + len += 2 + sizeof("HTTP_") - 1 + header[i].key.len + + 2 + header[i].value.len; } } @@ -583,11 +630,17 @@ ngx_http_uwsgi_create_request(ngx_http_r i = 0; } - key_len = 5 + header[i].key.len; + for (n = 0; n < header_params; n++) { + if (&header[i] == ignored[n]) { + goto next; + } + } + + key_len = sizeof("HTTP_") - 1 + header[i].key.len; *b->last++ = (u_char) (key_len & 0xff); *b->last++ = (u_char) ((key_len >> 8) & 0xff); - b->last = ngx_cpymem(b->last, "HTTP_", 5); + b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1); for (n = 0; n < header[i].key.len; n++) { ch = header[i].key.data[n]; @@ -610,6 +663,9 @@ ngx_http_uwsgi_create_request(ngx_http_r "uwsgi param: \"%*s: %*s\"", key_len, b->last - (key_len + 2 + val_len), val_len, b->last - val_len); + next: + + continue; } } @@ -1130,7 +1186,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t size_t size; uintptr_t *code; ngx_uint_t i; + ngx_array_t headers_names; ngx_keyval_t *src; + ngx_hash_key_t *hk; ngx_hash_init_t hash; ngx_http_script_compile_t sc; ngx_http_script_copy_code_t *copy; @@ -1324,6 +1382,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t conf->params_len = prev->params_len; conf->params = prev->params; conf->params_source = prev->params_source; + conf->headers_hash = prev->headers_hash; if (conf->params_source == NULL) { return NGX_CONF_OK; @@ -1340,9 +1399,33 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t return NGX_CONF_ERROR; } + if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + src = conf->params_source->elts; for (i = 0; i < conf->params_source->nelts; i++) { + if (src[i].key.len > sizeof("HTTP_") - 1 + && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) + { + hk = ngx_array_push(&headers_names); + if (hk == NULL) { + return NGX_CONF_ERROR; + } + + hk->key.len = src[i].key.len - 5; + hk->key.data = src[i].key.data + 5; + hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len); + hk->value = (void *) 1; + + if (src[i].value.len == 0) { + continue; + } + } + copy = ngx_array_push_n(conf->params_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { @@ -1404,6 +1487,21 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *code = (uintptr_t) NULL; + conf->header_params = headers_names.nelts; + + hash.hash = &conf->headers_hash; + hash.key = ngx_hash_key_lc; + hash.max_size = 512; + hash.bucket_size = 64; + hash.name = "uwsgi_params_hash"; + hash.pool = cf->pool; + hash.temp_pool = NULL; + + if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) + { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; }