[PATCH] HTTP: added the preserve_method option to the error_page directive.

Thibault Charbonnier thibaultcha at fastmail.com
Tue Sep 3 19:07:53 UTC 2019


# HG changeset patch
# User Thibault Charbonnier <thibaultcha at me.com>
# Date 1567537546 25200
#      Tue Sep 03 12:05:46 2019 -0700
# Node ID 68ba3d36bff4213e3fedc538021e8cbece85e508
# Parent  52b5ee64fe11ec267a0767cbb9874c8cae652299
HTTP: added the preserve_method option to the error_page directive.

As of today, the `error_page` directive will override the request method
if redirecting to a non-named location and if said method is not `HEAD`.

As for using named location (which preserve the request method), some
error cases won't be able to perform the redirect (e.g. HTTP 414).

This patch allows users who wish to set a single "catch-all" error
location block to preserve the client method for logging purposes.

A new option `preserve_method` is added to the directive:

    error_page 400 preserve_method /error_handler;

diff -r 52b5ee64fe11 -r 68ba3d36bff4 src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c	Tue Sep 03 17:26:56 2019 +0300
+++ b/src/http/ngx_http_core_module.c	Tue Sep 03 12:05:46 2019 -0700
@@ -4587,6 +4587,7 @@
 
     u_char                            *p;
     ngx_int_t                          overwrite;
+    ngx_flag_t                         preserve_method;
     ngx_str_t                         *value, uri, args;
     ngx_uint_t                         i, n;
     ngx_http_err_page_t               *err;
@@ -4601,35 +4602,40 @@
         }
     }
 
+    overwrite = -1;
+    preserve_method = 0;
+
+    n = 1;
     value = cf->args->elts;
 
-    i = cf->args->nelts - 2;
-
-    if (value[i].data[0] == '=') {
-        if (i == 1) {
+    for (i = cf->args->nelts - 3; i < cf->args->nelts - 1; i++) {
+        if (value[i].data[0] == '=') {
+            if (value[i].len > 1) {
+                overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
+                if (overwrite == NGX_ERROR) {
+                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                       "invalid value \"%V\"", &value[i]);
+                    return NGX_CONF_ERROR;
+                }
+
+                n++;
+
+            } else {
+                overwrite = 0;
+            }
+
+            n++;
+
+        } else if (ngx_strncmp(value[i].data, "preserve_method", 15) == 0) {
+            preserve_method = 1;
+            n++;
+        }
+
+        if (n > 1 && i == 1) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "invalid value \"%V\"", &value[i]);
             return NGX_CONF_ERROR;
         }
-
-        if (value[i].len > 1) {
-            overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
-
-            if (overwrite == NGX_ERROR) {
-                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                                   "invalid value \"%V\"", &value[i]);
-                return NGX_CONF_ERROR;
-            }
-
-        } else {
-            overwrite = 0;
-        }
-
-        n = 2;
-
-    } else {
-        overwrite = -1;
-        n = 1;
     }
 
     uri = value[cf->args->nelts - 1];
@@ -4680,6 +4686,7 @@
         }
 
         err->overwrite = overwrite;
+        err->preserve_method = preserve_method;
 
         if (overwrite == -1) {
             switch (err->status) {
diff -r 52b5ee64fe11 -r 68ba3d36bff4 src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h	Tue Sep 03 17:26:56 2019 +0300
+++ b/src/http/ngx_http_core_module.h	Tue Sep 03 12:05:46 2019 -0700
@@ -294,6 +294,7 @@
     ngx_int_t                  overwrite;
     ngx_http_complex_value_t   value;
     ngx_str_t                  args;
+    ngx_flag_t                 preserve_method;
 } ngx_http_err_page_t;
 
 
diff -r 52b5ee64fe11 -r 68ba3d36bff4 src/http/ngx_http_special_response.c
--- a/src/http/ngx_http_special_response.c	Tue Sep 03 17:26:56 2019 +0300
+++ b/src/http/ngx_http_special_response.c	Tue Sep 03 12:05:46 2019 -0700
@@ -611,7 +611,7 @@
             args = err_page->args;
         }
 
-        if (r->method != NGX_HTTP_HEAD) {
+        if (!err_page->preserve_method && r->method != NGX_HTTP_HEAD) {
             r->method = NGX_HTTP_GET;
             r->method_name = ngx_http_core_get_method;
         }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch
Type: application/octet-stream
Size: 4168 bytes
Desc: not available
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20190903/fd7fbef0/attachment.obj>


More information about the nginx-devel mailing list