From 1dd22ac20f5c343ee30f965d8b785afb116a4390 Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Mon, 30 Jul 2018 12:55:36 +0200 Subject: [PATCH] feature: added the preserve_method_on_error_page patch. --- ...1.13.6-preserve_method_on_error_page.patch | 93 +++++++++++++++++++ t/002-preserve_method_on_error_page.t | 54 +++++++++++ util/mirror-tarballs | 4 + 3 files changed, 151 insertions(+) create mode 100644 patches/nginx-1.13.6-preserve_method_on_error_page.patch create mode 100644 t/002-preserve_method_on_error_page.t diff --git a/patches/nginx-1.13.6-preserve_method_on_error_page.patch b/patches/nginx-1.13.6-preserve_method_on_error_page.patch new file mode 100644 index 0000000..6ee41a2 --- /dev/null +++ b/patches/nginx-1.13.6-preserve_method_on_error_page.patch @@ -0,0 +1,93 @@ +# HG changeset patch +# User Thibault Charbonnier +# Date 1532789509 -7200 +# Sat Jul 28 16:51:49 2018 +0200 +# Node ID af4366d9fec2bc2ccce8fd03fc456621df13f673 +# Parent f7e79596baf209151682f2f7d220161c034657ac +Implemented the 'preserve_method_on_error_page' directive. + +By default, the internal redirect to non-named locations caused by the +'error_page' directive causes the HTTP method to be rewritten to GET (unless it +is HEAD). + +This new directive allows one to disable this behavior, and ensure the HTTP +method is preserved through the internal redirect to the defined error_page. + +diff -r f7e79596baf2 -r af4366d9fec2 src/http/ngx_http_core_module.c +--- a/src/http/ngx_http_core_module.c Tue Jul 24 18:46:54 2018 +0300 ++++ b/src/http/ngx_http_core_module.c Sat Jul 28 16:51:49 2018 +0200 +@@ -654,6 +654,13 @@ + 0, + NULL }, + ++ { ngx_string("preserve_method_on_error_page"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ++ ngx_conf_set_flag_slot, ++ NGX_HTTP_LOC_CONF_OFFSET, ++ offsetof(ngx_http_core_loc_conf_t, preserve_method_on_error_page), ++ NULL }, ++ + { ngx_string("post_action"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_TAKE1, +@@ -3410,6 +3417,7 @@ + clcf->log_not_found = NGX_CONF_UNSET; + clcf->log_subrequest = NGX_CONF_UNSET; + clcf->recursive_error_pages = NGX_CONF_UNSET; ++ clcf->preserve_method_on_error_page = NGX_CONF_UNSET; + clcf->chunked_transfer_encoding = NGX_CONF_UNSET; + clcf->etag = NGX_CONF_UNSET; + clcf->server_tokens = NGX_CONF_UNSET_UINT; +@@ -3679,6 +3687,8 @@ + ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0); + ngx_conf_merge_value(conf->recursive_error_pages, + prev->recursive_error_pages, 0); ++ ngx_conf_merge_value(conf->preserve_method_on_error_page, ++ prev->preserve_method_on_error_page, 0); + ngx_conf_merge_value(conf->chunked_transfer_encoding, + prev->chunked_transfer_encoding, 1); + ngx_conf_merge_value(conf->etag, prev->etag, 1); +diff -r f7e79596baf2 -r af4366d9fec2 src/http/ngx_http_core_module.h +--- a/src/http/ngx_http_core_module.h Tue Jul 24 18:46:54 2018 +0300 ++++ b/src/http/ngx_http_core_module.h Sat Jul 28 16:51:49 2018 +0200 +@@ -393,6 +393,8 @@ + ngx_flag_t log_not_found; /* log_not_found */ + ngx_flag_t log_subrequest; /* log_subrequest */ + ngx_flag_t recursive_error_pages; /* recursive_error_pages */ ++ ngx_flag_t preserve_method_on_error_page; ++ /* preserve_method_on_error_page */ + ngx_uint_t server_tokens; /* server_tokens */ + ngx_flag_t chunked_transfer_encoding; /* chunked_transfer_encoding */ + ngx_flag_t etag; /* etag */ +diff -r f7e79596baf2 -r af4366d9fec2 src/http/ngx_http_special_response.c +--- a/src/http/ngx_http_special_response.c Tue Jul 24 18:46:54 2018 +0300 ++++ b/src/http/ngx_http_special_response.c Sat Jul 28 16:51:49 2018 +0200 +@@ -602,6 +602,8 @@ + return NGX_ERROR; + } + ++ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ++ + if (uri.len && uri.data[0] == '/') { + + if (err_page->value.lengths) { +@@ -611,7 +613,9 @@ + args = err_page->args; + } + +- if (r->method != NGX_HTTP_HEAD) { ++ if (r->method != NGX_HTTP_HEAD ++ && !clcf->preserve_method_on_error_page) ++ { + r->method = NGX_HTTP_GET; + r->method_name = ngx_http_core_get_method; + } +@@ -646,8 +650,6 @@ + + r->headers_out.location = location; + +- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); +- + if (clcf->msie_refresh && r->headers_in.msie) { + return ngx_http_send_refresh(r); + } diff --git a/t/002-preserve_method_on_error_page.t b/t/002-preserve_method_on_error_page.t new file mode 100644 index 0000000..d66f841 --- /dev/null +++ b/t/002-preserve_method_on_error_page.t @@ -0,0 +1,54 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +repeat_each(1); + +plan tests => repeat_each() * (blocks() * 3); + +no_long_string(); + +run_tests(); + +__DATA__ + +=== TEST 1: error_page overrides HTTP method if not HEAD +--- config + error_page 400 /err; + + location /t { + return 400; + } + + location /err { + return 200 '$request_method'; + } +--- request +POST /t +--- error_code: 400 +--- response_body chomp +GET +--- no_error_log +[error] + + + +=== TEST 2: error_page does not override HTTP method if preserve_method_on_error_page is on +--- config + error_page 400 /err; + preserve_method_on_error_page on; + + location /t { + return 400; + } + + location /err { + return 200 '$request_method'; + } +--- request +POST /t +--- error_code: 400 +--- response_body chomp +POST +--- no_error_log +[error] diff --git a/util/mirror-tarballs b/util/mirror-tarballs index c183dac..79ef411 100755 --- a/util/mirror-tarballs +++ b/util/mirror-tarballs @@ -147,6 +147,10 @@ echo "$info_txt applying the no_error_pages patch for nginx" patch -p1 < $root/patches/nginx-$main_ver-no_error_pages.patch || exit 1 echo +echo "$info_txt applying the preserve_method_on_error_page patch for nginx" +patch -p1 < $root/patches/nginx-$main_ver-preserve_method_on_error_page.patch || exit 1 +echo + echo "$info_txt applying the no_Werror patch for nginx" patch -p1 < $root/patches/nginx-$main_ver-no_Werror.patch || exit 1 echo