[nginx] Upstream: duplicate headers ignored or properly linked.
Sergey Kandaurov
pluknet at nginx.com
Mon May 30 22:32:54 UTC 2022
details: https://hg.nginx.org/nginx/rev/413dbda22f7d
branches:
changeset: 8034:413dbda22f7d
user: Maxim Dounin <mdounin at mdounin.ru>
date: Mon May 30 21:25:49 2022 +0300
description:
Upstream: duplicate headers ignored or properly linked.
Most of the known duplicate upstream response headers are now ignored
with a warning.
If syntax permits multiple headers, these are now properly linked to
the lists, notably Vary and WWW-Authenticate. This makes it possible
to further handle such lists where it makes sense.
diffstat:
src/http/ngx_http_upstream.c | 114 +++++++++++++++++++++++++++++++++++++++---
src/http/ngx_http_upstream.h | 1 +
2 files changed, 105 insertions(+), 10 deletions(-)
diffs (216 lines):
diff -r 2bf7792c262e -r 413dbda22f7d src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c Mon May 30 21:25:48 2022 +0300
+++ b/src/http/ngx_http_upstream.c Mon May 30 21:25:49 2022 +0300
@@ -101,6 +101,9 @@ static void ngx_http_upstream_finalize_r
static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t
+ ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
@@ -226,7 +229,7 @@ static ngx_http_upstream_header_t ngx_h
offsetof(ngx_http_headers_out_t, server), 0 },
{ ngx_string("WWW-Authenticate"),
- ngx_http_upstream_process_header_line,
+ ngx_http_upstream_process_multi_header_lines,
offsetof(ngx_http_upstream_headers_in_t, www_authenticate),
ngx_http_upstream_copy_header_line, 0, 0 },
@@ -236,7 +239,8 @@ static ngx_http_upstream_header_t ngx_h
ngx_http_upstream_rewrite_location, 0, 0 },
{ ngx_string("Refresh"),
- ngx_http_upstream_ignore_header_line, 0,
+ ngx_http_upstream_process_header_line,
+ offsetof(ngx_http_upstream_headers_in_t, refresh),
ngx_http_upstream_rewrite_refresh, 0, 0 },
{ ngx_string("Set-Cookie"),
@@ -2804,6 +2808,10 @@ ngx_http_upstream_process_headers(ngx_ht
i = 0;
}
+ if (h[i].hash == 0) {
+ continue;
+ }
+
hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
h[i].lowcase_key, h[i].key.len);
@@ -2857,6 +2865,10 @@ ngx_http_upstream_process_headers(ngx_ht
i = 0;
}
+ if (h[i].hash == 0) {
+ continue;
+ }
+
if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
h[i].lowcase_key, h[i].key.len))
{
@@ -4608,10 +4620,35 @@ ngx_http_upstream_process_header_line(ng
ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
- if (*ph == NULL) {
- *ph = h;
- h->next = NULL;
- }
+ if (*ph) {
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "upstream sent duplicate header line: \"%V: %V\", "
+ "previous value: \"%V: %V\", ignored",
+ &h->key, &h->value,
+ &(*ph)->key, &(*ph)->value);
+ h->hash = 0;
+ return NGX_OK;
+ }
+
+ *ph = h;
+ h->next = NULL;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset)
+{
+ ngx_table_elt_t **ph;
+
+ ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
+
+ while (*ph) { ph = &(*ph)->next; }
+
+ *ph = h;
+ h->next = NULL;
return NGX_OK;
}
@@ -4673,6 +4710,17 @@ ngx_http_upstream_process_last_modified(
u = r->upstream;
+ if (u->headers_in.last_modified) {
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "upstream sent duplicate header line: \"%V: %V\", "
+ "previous value: \"%V: %V\", ignored",
+ &h->key, &h->value,
+ &u->headers_in.last_modified->key,
+ &u->headers_in.last_modified->value);
+ h->hash = 0;
+ return NGX_OK;
+ }
+
h->next = NULL;
u->headers_in.last_modified = h;
u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data,
@@ -4842,6 +4890,18 @@ ngx_http_upstream_process_expires(ngx_ht
ngx_http_upstream_t *u;
u = r->upstream;
+
+ if (u->headers_in.expires) {
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "upstream sent duplicate header line: \"%V: %V\", "
+ "previous value: \"%V: %V\", ignored",
+ &h->key, &h->value,
+ &u->headers_in.expires->key,
+ &u->headers_in.expires->value);
+ h->hash = 0;
+ return NGX_OK;
+ }
+
u->headers_in.expires = h;
h->next = NULL;
@@ -4883,6 +4943,18 @@ ngx_http_upstream_process_accel_expires(
ngx_http_upstream_t *u;
u = r->upstream;
+
+ if (u->headers_in.x_accel_expires) {
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "upstream sent duplicate header line: \"%V: %V\", "
+ "previous value: \"%V: %V\", ignored",
+ &h->key, &h->value,
+ &u->headers_in.x_accel_expires->key,
+ &u->headers_in.x_accel_expires->value);
+ h->hash = 0;
+ return NGX_OK;
+ }
+
u->headers_in.x_accel_expires = h;
h->next = NULL;
@@ -4943,6 +5015,18 @@ ngx_http_upstream_process_limit_rate(ngx
ngx_http_upstream_t *u;
u = r->upstream;
+
+ if (u->headers_in.x_accel_limit_rate) {
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "upstream sent duplicate header line: \"%V: %V\", "
+ "previous value: \"%V: %V\", ignored",
+ &h->key, &h->value,
+ &u->headers_in.x_accel_limit_rate->key,
+ &u->headers_in.x_accel_limit_rate->value);
+ h->hash = 0;
+ return NGX_OK;
+ }
+
u->headers_in.x_accel_limit_rate = h;
h->next = NULL;
@@ -5021,10 +5105,15 @@ static ngx_int_t
ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
- ngx_http_upstream_t *u;
+ ngx_table_elt_t **ph;
+ ngx_http_upstream_t *u;
u = r->upstream;
- u->headers_in.connection = h;
+ ph = &u->headers_in.connection;
+
+ while (*ph) { ph = &(*ph)->next; }
+
+ *ph = h;
h->next = NULL;
if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
@@ -5086,10 +5175,15 @@ static ngx_int_t
ngx_http_upstream_process_vary(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset)
{
- ngx_http_upstream_t *u;
+ ngx_table_elt_t **ph;
+ ngx_http_upstream_t *u;
u = r->upstream;
- u->headers_in.vary = h;
+ ph = &u->headers_in.vary;
+
+ while (*ph) { ph = &(*ph)->next; }
+
+ *ph = h;
h->next = NULL;
#if (NGX_HTTP_CACHE)
diff -r 2bf7792c262e -r 413dbda22f7d src/http/ngx_http_upstream.h
--- a/src/http/ngx_http_upstream.h Mon May 30 21:25:48 2022 +0300
+++ b/src/http/ngx_http_upstream.h Mon May 30 21:25:49 2022 +0300
@@ -280,6 +280,7 @@ typedef struct {
ngx_table_elt_t *last_modified;
ngx_table_elt_t *location;
+ ngx_table_elt_t *refresh;
ngx_table_elt_t *www_authenticate;
ngx_table_elt_t *transfer_encoding;
ngx_table_elt_t *vary;
More information about the nginx-devel
mailing list