I'm not sure how to describe the functionality I'm trying to achieve in a way other than "an internal 307 redirect".
Using nginx's error_page
directive causes nginx to change POST requests to GET requests.
In my config, Nginx proxies requests to some upstream server with proxy_intercept_errors on
so that I can serve error pages from nginx.
Example:
error_page 500 502 503 =500 /50x.html;
location = /50x.html {
root /some/document/root/;
}
location / {
proxy_intercept_errors on;
proxy_pass https://somewhere;
}
With that config in place, POST requests that result in a 500, 502, or a 503 on the proxy will "secretly" become GET requests to the original URI (/someurl).
Here's a line in the nginx log showing this behavior (I have changed the log format to show $request_method):
1.2.3.4 - - [27/Sep/2021:10:04:50 -0400] request_method=GET "POST /someurl HTTP/1.1 500 123 "https://domain.tld/someurl"...
You can see that nginx has changed the POST request to a GET request.
(Update: apparently the nginx docs for error_page state exactly that...)
After some research, it seems like this is intentional behavior and is the result of an internal redirect. Apparently the 307 and 308 response codes were created because of similar behavior (albeit on the client, not server).
Is there anything I can do that would have the functionality of an "internal 307 redirect"? i.e., serve an error page but preserve the request method and body? Example, for clarity:
Client POSTs to /someurl, upstream server responds with 500, nginx swallows it and serves "/mygreat500errorpage.html" while preserving the original request method (POST), the original request URI (/someurl) and the original request body.
Update, while still writing this:
I found this answer that suggests using a named location block to avoid changing the request method. This seems to work with the exception that I can't seem to serve "/mygreat500errorpage.html" from inside the named location. I'm not sure if this is even the correct way of solving the issue, so I'm going to post this question anyways.