underscores_in_headers
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 049c113..b4a07d0 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1031,7 +1031,7 @@
part_start = u->buffer.pos;
- rc = ngx_http_parse_header_line(r, &u->buffer);
+ rc = ngx_http_parse_header_line(r, &u->buffer, 1);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http fastcgi parser: %d", rc);
@@ -1076,7 +1076,7 @@
f->split_parts->nelts = 0;
- rc = ngx_http_parse_header_line(r, &buf);
+ rc = ngx_http_parse_header_line(r, &buf, 1);
h->key.len = r->header_name_end - r->header_name_start;
h->key.data = r->header_name_start;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 6c0e28a..d8392ee 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1214,7 +1214,7 @@
for ( ;; ) {
- rc = ngx_http_parse_header_line(r, &r->upstream->buffer);
+ rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
if (rc == NGX_OK) {
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index 762d85c..79b2187 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -72,7 +72,8 @@
ngx_uint_t merge_slashes);
ngx_int_t ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
ngx_str_t *args, ngx_uint_t *flags);
-ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b);
+ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
+ ngx_uint_t allow_underscores);
ngx_int_t ngx_http_parse_multi_header_lines(ngx_array_t *headers,
ngx_str_t *name, ngx_str_t *value);
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index e1d5a8f..050f81e 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -231,6 +231,13 @@
offsetof(ngx_http_core_srv_conf_t, merge_slashes),
NULL },
+ { ngx_string("underscores_in_headers"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ offsetof(ngx_http_core_srv_conf_t, underscores_in_headers),
+ NULL },
+
{ ngx_string("location"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
ngx_http_core_location,
@@ -2527,6 +2534,7 @@
cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
cscf->ignore_invalid_headers = NGX_CONF_UNSET;
cscf->merge_slashes = NGX_CONF_UNSET;
+ cscf->underscores_in_headers = NGX_CONF_UNSET;
return cscf;
}
@@ -2605,6 +2613,9 @@
ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);
+ ngx_conf_merge_value(conf->underscores_in_headers,
+ prev->underscores_in_headers, 0);
+
return NGX_CONF_OK;
}
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index a3d8940..e28aad5 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -155,6 +155,7 @@
ngx_flag_t ignore_invalid_headers;
ngx_flag_t merge_slashes;
+ ngx_flag_t underscores_in_headers;
ngx_http_core_loc_conf_t **named_locations;
} ngx_http_core_srv_conf_t;
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 2fce7ac..b08d5ea 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -700,7 +700,8 @@
ngx_int_t
-ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
+ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
+ ngx_uint_t allow_underscores)
{
u_char c, ch, *p;
ngx_uint_t hash, i;
@@ -720,7 +721,7 @@
static u_char lowcase[] =
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0-\0\0" "0123456789\0\0\0\0\0\0"
- "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0_"
+ "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0"
"\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
@@ -779,6 +780,19 @@
break;
}
+ if (ch == '_') {
+ if (allow_underscores) {
+ hash = ngx_hash(hash, ch);
+ r->lowcase_header[i++] = ch;
+ i &= (NGX_HTTP_LC_HEADER_LEN - 1);
+
+ } else {
+ r->invalid_header = 1;
+ }
+
+ break;
+ }
+
if (ch == ':') {
r->header_name_end = p;
state = sw_space_before_value;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index ae3bb03..3970852 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -902,7 +902,8 @@
}
}
- rc = ngx_http_parse_header_line(r, r->header_in);
+ rc = ngx_http_parse_header_line(r, r->header_in,
+ cscf->underscores_in_headers);
if (rc == NGX_OK) {