Mercurial > hg > nginx
changeset 8021:75af96daee97
SCGI: combining headers with identical names (ticket #1724).
SCGI specification explicitly forbids headers with duplicate names
(section "3. Request Format"): "Duplicate names are not allowed in
the headers".
Further, provided headers are expected to follow CGI specification,
which also requires to combine headers (RFC 3875, section "4.1.18.
Protocol-Specific Meta-Variables"): "If multiple header fields with
the same field-name are received then the server MUST rewrite them
as a single value having the same semantics".
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 30 May 2022 21:25:28 +0300 |
parents | f8f6b9fee66a |
children | 8b7a96fdd54c |
files | src/http/modules/ngx_http_scgi_module.c |
diffstat | 1 files changed, 45 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/http/modules/ngx_http_scgi_module.c Mon May 30 21:25:27 2022 +0300 +++ b/src/http/modules/ngx_http_scgi_module.c Mon May 30 21:25:28 2022 +0300 @@ -633,14 +633,14 @@ ngx_http_scgi_create_request(ngx_http_request_t *r) { off_t content_length_n; - u_char ch, *key, *val, *lowcase_key; + u_char ch, sep, *key, *val, *lowcase_key; size_t len, key_len, val_len, allocated; ngx_buf_t *b; ngx_str_t content_length; ngx_uint_t i, n, hash, skip_empty, header_params; ngx_chain_t *cl, *body; ngx_list_part_t *part; - ngx_table_elt_t *header, **ignored; + ngx_table_elt_t *header, *hn, **ignored; ngx_http_scgi_params_t *params; ngx_http_script_code_pt code; ngx_http_script_engine_t e, le; @@ -707,7 +707,11 @@ allocated = 0; lowcase_key = NULL; - if (params->number) { + if (ngx_http_link_multi_headers(r) != NGX_OK) { + return NGX_ERROR; + } + + if (params->number || r->headers_in.multi) { n = 0; part = &r->headers_in.headers.part; @@ -737,6 +741,12 @@ i = 0; } + for (n = 0; n < header_params; n++) { + if (&header[i] == ignored[n]) { + goto next_length; + } + } + if (params->number) { if (allocated < header[i].key.len) { allocated = header[i].key.len + 16; @@ -770,6 +780,15 @@ len += sizeof("HTTP_") - 1 + header[i].key.len + 1 + header[i].value.len + 1; + + for (hn = header[i].next; hn; hn = hn->next) { + len += hn->value.len + 2; + ignored[header_params++] = hn; + } + + next_length: + + continue; } } @@ -869,7 +888,7 @@ for (n = 0; n < header_params; n++) { if (&header[i] == ignored[n]) { - goto next; + goto next_value; } } @@ -893,12 +912,33 @@ val = b->last; b->last = ngx_copy(val, header[i].value.data, header[i].value.len); + + if (header[i].next) { + + if (header[i].key.len == sizeof("Cookie") - 1 + && ngx_strncasecmp(header[i].key.data, (u_char *) "Cookie", + sizeof("Cookie") - 1) + == 0) + { + sep = ';'; + + } else { + sep = ','; + } + + for (hn = header[i].next; hn; hn = hn->next) { + *b->last++ = sep; + *b->last++ = ' '; + b->last = ngx_copy(b->last, hn->value.data, hn->value.len); + } + } + *b->last++ = (u_char) 0; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "scgi param: \"%s: %s\"", key, val); - next: + next_value: continue; }