Skip to content

Instantly share code, notes, and snippets.

@agentzh
Created April 24, 2013 01:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agentzh/5448934 to your computer and use it in GitHub Desktop.
Save agentzh/5448934 to your computer and use it in GitHub Desktop.
bugfix: modifying the Connection request header via ngx.req.set_header or ngx.req.clear_header did not update the special internal flags in the Nginx core, "r->headers_in.connection_type" and "r->headers_in.keep_alive_n". Thanks Matthieu Tourne for the patch.
diff --git a/src/ngx_http_lua_headers_in.c b/src/ngx_http_lua_headers_in.c
index f4413b6..bd4af76 100644
--- a/src/ngx_http_lua_headers_in.c
+++ b/src/ngx_http_lua_headers_in.c
@@ -25,6 +25,8 @@ static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r,
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_user_agent_header(ngx_http_request_t *r,
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
+static ngx_int_t ngx_http_set_connection_header(ngx_http_request_t *r,
+ ngx_http_lua_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r,
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r,
@@ -51,7 +53,7 @@ static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = {
{ ngx_string("Connection"),
offsetof(ngx_http_headers_in_t, connection),
- ngx_http_set_builtin_header },
+ ngx_http_set_connection_header },
{ ngx_string("If-Modified-Since"),
offsetof(ngx_http_headers_in_t, if_modified_since),
@@ -268,6 +270,28 @@ ngx_http_set_host_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
}
+static ngx_int_t
+ngx_http_set_connection_header(ngx_http_request_t *r,
+ ngx_http_lua_header_val_t *hv, ngx_str_t *value)
+{
+ r->headers_in.connection_type = 0;
+
+ if (value->len == 0) {
+ return ngx_http_set_builtin_header(r, hv, value);
+ }
+
+ if (ngx_strcasestrn(value->data, "close", 5 - 1)) {
+ r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
+ r->headers_in.keep_alive_n = -1;
+
+ } else if (ngx_strcasestrn(value->data, "keep-alive", 10 - 1)) {
+ r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
+ }
+
+ return ngx_http_set_builtin_header(r, hv, value);
+}
+
+
/* borrowed the code from ngx_http_request.c:ngx_http_process_user_agent */
static ngx_int_t
ngx_http_set_user_agent_header(ngx_http_request_t *r,
diff --git a/t/112-req-header-conn.t b/t/112-req-header-conn.t
new file mode 100644
index 0000000..37f1a2e
--- /dev/null
+++ b/t/112-req-header-conn.t
@@ -0,0 +1,150 @@
+# vim:set ft= ts=4 sw=4 et fdm=marker:
+
+use lib 'lib';
+use Test::Nginx::Socket;
+
+#worker_connections(1014);
+#master_process_enabled(1);
+#log_level('warn');
+
+repeat_each(2);
+
+plan tests => repeat_each() * (4 * blocks());
+
+#no_diff();
+no_long_string();
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: clear the Connection req header
+--- config
+ location /req-header {
+ rewrite_by_lua '
+ ngx.req.set_header("Connection", nil);
+ ';
+
+ echo "connection: $http_connection";
+ }
+--- request
+GET /req-header
+
+--- stap
+F(ngx_http_lua_rewrite_by_chunk) {
+ printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
+}
+
+
+F(ngx_http_core_content_phase) {
+ printf("content: conn type: %d\n", $r->headers_in->connection_type)
+}
+
+--- stap_out
+rewrite: conn type: 1
+content: conn type: 0
+
+--- response_body
+connection:
+--- no_error_log
+[error]
+
+
+
+=== TEST 2: set custom Connection req header (close)
+--- config
+ location /req-header {
+ rewrite_by_lua '
+ ngx.req.set_header("Connection", "CLOSE");
+ ';
+
+ echo "connection: $http_connection";
+ }
+--- request
+GET /req-header
+
+--- stap
+F(ngx_http_lua_rewrite_by_chunk) {
+ printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
+}
+
+
+F(ngx_http_core_content_phase) {
+ printf("content: conn type: %d\n", $r->headers_in->connection_type)
+}
+
+--- stap_out
+rewrite: conn type: 1
+content: conn type: 1
+
+--- response_body
+connection: CLOSE
+--- no_error_log
+[error]
+
+
+
+=== TEST 3: set custom Connection req header (keep-alive)
+--- config
+ location /req-header {
+ rewrite_by_lua '
+ ngx.req.set_header("Connection", "keep-alive");
+ ';
+
+ echo "connection: $http_connection";
+ }
+--- request
+GET /req-header
+
+--- stap
+F(ngx_http_lua_rewrite_by_chunk) {
+ printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
+}
+
+
+F(ngx_http_core_content_phase) {
+ printf("content: conn type: %d\n", $r->headers_in->connection_type)
+}
+
+--- stap_out
+rewrite: conn type: 1
+content: conn type: 2
+
+--- response_body
+connection: keep-alive
+--- no_error_log
+[error]
+
+
+
+=== TEST 4: set custom Connection req header (bad)
+--- config
+ location /req-header {
+ rewrite_by_lua '
+ ngx.req.set_header("Connection", "bad");
+ ';
+
+ echo "connection: $http_connection";
+ }
+--- request
+GET /req-header
+
+--- stap
+F(ngx_http_lua_rewrite_by_chunk) {
+ printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
+}
+
+
+F(ngx_http_core_content_phase) {
+ printf("content: conn type: %d\n", $r->headers_in->connection_type)
+}
+
+--- stap_out
+rewrite: conn type: 1
+content: conn type: 0
+
+--- response_body
+connection: bad
+--- no_error_log
+[error]
+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment