diff options
| -rw-r--r-- | src/core/ngx_hash.h | 7 | ||||
| -rw-r--r-- | src/http/modules/ngx_http_fastcgi_module.c | 66 | ||||
| -rw-r--r-- | src/http/ngx_http_core_module.c | 74 | ||||
| -rw-r--r-- | src/http/ngx_http_core_module.h | 2 | ||||
| -rw-r--r-- | src/http/ngx_http_request.h | 2 |
5 files changed, 138 insertions, 13 deletions
diff --git a/src/core/ngx_hash.h b/src/core/ngx_hash.h index abc3cbe5d..3b5709928 100644 --- a/src/core/ngx_hash.h +++ b/src/core/ngx_hash.h @@ -89,12 +89,15 @@ typedef struct { } ngx_hash_keys_arrays_t; -typedef struct { +typedef struct ngx_table_elt_s ngx_table_elt_t; + +struct ngx_table_elt_s { ngx_uint_t hash; ngx_str_t key; ngx_str_t value; u_char *lowcase_key; -} ngx_table_elt_t; + ngx_table_elt_t *next; +}; void *ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len); diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 4a8dc338e..17b7e83a3 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -835,14 +835,14 @@ static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r) { off_t file_pos; - u_char ch, *pos, *lowcase_key; + u_char ch, sep, *pos, *lowcase_key; size_t size, len, key_len, val_len, padding, allocated; ngx_uint_t i, n, next, hash, skip_empty, header_params; ngx_buf_t *b; 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_upstream_t *u; ngx_http_script_code_pt code; ngx_http_script_engine_t e, le; @@ -900,7 +900,11 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) 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; @@ -930,6 +934,12 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) 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; @@ -959,15 +969,23 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) ignored[header_params++] = &header[i]; continue; } + } - n += sizeof("HTTP_") - 1; + key_len = sizeof("HTTP_") - 1 + header[i].key.len; - } else { - n = sizeof("HTTP_") - 1 + header[i].key.len; + val_len = header[i].value.len; + + for (hn = header[i].next; hn; hn = hn->next) { + val_len += hn->value.len + 2; + ignored[header_params++] = hn; } - len += ((n > 127) ? 4 : 1) + ((header[i].value.len > 127) ? 4 : 1) - + n + header[i].value.len; + len += ((key_len > 127) ? 4 : 1) + key_len + + ((val_len > 127) ? 4 : 1) + val_len; + + next_length: + + continue; } } @@ -1109,7 +1127,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) for (n = 0; n < header_params; n++) { if (&header[i] == ignored[n]) { - goto next; + goto next_value; } } @@ -1125,6 +1143,11 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) } val_len = header[i].value.len; + + for (hn = header[i].next; hn; hn = hn->next) { + val_len += hn->value.len + 2; + } + if (val_len > 127) { *b->last++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80); *b->last++ = (u_char) ((val_len >> 16) & 0xff); @@ -1150,13 +1173,34 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) *b->last++ = ch; } - b->last = ngx_copy(b->last, header[i].value.data, val_len); + b->last = ngx_copy(b->last, 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); + } + } ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "fastcgi param: \"%*s: %*s\"", key_len, b->last - (key_len + val_len), val_len, b->last - val_len); - next: + next_value: continue; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index c7463dcdc..ad8caad19 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2802,6 +2802,80 @@ ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr, } +ngx_int_t +ngx_http_link_multi_headers(ngx_http_request_t *r) +{ + ngx_uint_t i, j; + ngx_list_part_t *part, *ppart; + ngx_table_elt_t *header, *pheader, **ph; + + if (r->headers_in.multi_linked) { + return NGX_OK; + } + + r->headers_in.multi_linked = 1; + + part = &r->headers_in.headers.part; + header = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + header[i].next = NULL; + + /* + * search for previous headers with the same name; + * if there are any, link to them + */ + + ppart = &r->headers_in.headers.part; + pheader = ppart->elts; + + for (j = 0; /* void */; j++) { + + if (j >= ppart->nelts) { + if (ppart->next == NULL) { + break; + } + + ppart = ppart->next; + pheader = ppart->elts; + j = 0; + } + + if (part == ppart && i == j) { + break; + } + + if (header[i].key.len == pheader[j].key.len + && ngx_strncasecmp(header[i].key.data, pheader[j].key.data, + header[i].key.len) + == 0) + { + ph = &pheader[j].next; + while (*ph) { ph = &(*ph)->next; } + *ph = &header[i]; + + r->headers_in.multi = 1; + + break; + } + } + } + + return NGX_OK; +} + + static char * ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) { diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 004a98eef..7ba64947b 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -532,6 +532,8 @@ ngx_int_t ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr, ngx_array_t *headers, ngx_str_t *value, ngx_array_t *proxies, int recursive); +ngx_int_t ngx_http_link_multi_headers(ngx_http_request_t *r); + extern ngx_module_t ngx_http_core_module; diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index b1269d22d..52165793a 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -242,6 +242,8 @@ typedef struct { unsigned connection_type:2; unsigned chunked:1; + unsigned multi:1; + unsigned multi_linked:1; unsigned msie:1; unsigned msie6:1; unsigned opera:1; |
