Score:1

nginx - how to functionally achieve an "internal 307 redirect"

in flag

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.

Michael Hampton avatar
cz flag
Yes, that's the way to do it. The answer I was going to write would have been identical. Of course you should supply 307 and your own URL.
Brosilio avatar
in flag
@MichaelHampton this question isn't a duplicate because the answer on that question doesn't work, or at least, I don't know how to implement it properly.
Michael Hampton avatar
cz flag
There is nothing in your question about any problems you had implementing it. Please edit your question to provide the relevant details.
Brosilio avatar
in flag
turns out what I wanted to do was effectively allow POST requests to static files which is (understandably) not allowed - ended up writing a webserver to accept POST requests to static files and just proxy error_pages to those using named locations like you would've suggested.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.