# X-accel-redirect enables caching for POST requests

**URL:** <https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705>\
**Category:** NGINX\
**Created:** [December 23, 2015, 1:54pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705 "2015-12-23T13:54:50Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sadaf\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/858c86/32.png) [@Sadaf\_N](https://www.ruby-forum.com/u/Sadaf_N)\
**Post date:** [December 23, 2015, 1:54pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/1 "2015-12-23T13:54:50Z")

</div>

Hi,

If location /a/ redirects a POST request to location /b/ using  
X-Accel-Redirect then result of the POST request is cached.

Tested this and reproduced with nginx 1.6.3 and 1.9.7.

Setup:

> <https://gist.github.com/ruz/4a66ee78fedf27181799>

Logs from hitting /a/:  
[1450873503.675] 200 HIT 127.0.0.1 “POST /a/ HTTP/1.1” [0.001, 0.001] {  
127.0.0.1:5000}  
[1450873504.113] 200 HIT 127.0.0.1 “POST /a/ HTTP/1.1” [0.001, 0.001] {  
127.0.0.1:5000}  
[1450873504.529] 200 HIT 127.0.0.1 “POST /a/ HTTP/1.1” [0.002, 0.002] {  
127.0.0.1:5000}  
[1450873567.648] 200 EXPIRED 127.0.0.1 “POST /a/ HTTP/1.1” [0.001 :  
0.002,  
0.003] {127.0.0.1:5000 : 127.0.0.1:5000}

Logs from hitting /b/ directly:  
[1450875056.289] 200 - 127.0.0.1 “POST /b/ HTTP/1.1” [0.005, 0.005] {  
127.0.0.1:5000}  
[1450875058.073] 200 - 127.0.0.1 “POST /b/ HTTP/1.1” [0.001, 0.001] {  
127.0.0.1:5000}

Looks like a bug to me. Do I miss something?

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [December 23, 2015, 4:49pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/2 "2015-12-23T16:49:31Z")

</div>

Hello!

On Wed, Dec 23, 2015 at 03:54:31PM +0300, wrote:

> Logs from hitting /a/:  
> [1450875056.289] 200 - 127.0.0.1 “POST /b/ HTTP/1.1” [0.005, 0.005] {  
> 127.0.0.1:5000}  
> [1450875058.073] 200 - 127.0.0.1 “POST /b/ HTTP/1.1” [0.001, 0.001] {  
> 127.0.0.1:5000}
> 
> Looks like a bug to me. Do I miss something?

X-Accel-Redirect changes a request from POST to GET.

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [December 23, 2015, 5:11pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/3 "2015-12-23T17:11:08Z")

</div>

On Wed, Dec 23, 2015 at 6:49 PM, Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> X-Accel-Redirect changes a request from POST to GET.

No, it doesn’t. Getting request method POST on the backend and even form  
data is intact.

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [December 23, 2015, 5:19pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/4 "2015-12-23T17:19:19Z")

</div>

Hello!

On Wed, Dec 23, 2015 at 07:10:43PM +0300, wrote:

> On Wed, Dec 23, 2015 at 6:49 PM, Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > X-Accel-Redirect changes a request from POST to GET.
> 
> No, it doesn’t. Getting request method POST on the backend and even form  
> data is intact.

It does,

> **[hg.nginx.org is decommissioned](http://hg.nginx.org/nginx/file/tip/src/http/ngx_http_upstream.c#l2501:)**

```
        if (r->method != NGX_HTTP_HEAD) {
            r->method = NGX_HTTP_GET;
        }

```

Though it looks like it only does so for nginx itself, and this  
indeed looks like a bug. The code should be similar to one in  
error\_page handling:

```
    if (r->method != NGX_HTTP_HEAD) {
        r->method = NGX_HTTP_GET;
        r->method_name = ngx_http_core_get_method;
    }

```

If you want to get request and request method intact, use  
X-Accel-Redirect to a named location instead.

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [December 23, 2015, 10:17pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/5 "2015-12-23T22:17:14Z")

</div>

On Wed, Dec 23, 2015 at 7:19 PM, Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> It does,  
> [hg.nginx.org is decommissioned](http://hg.nginx.org/nginx/file/tip/src/http/ngx_http_upstream.c#l2501:)
> 
> ```
> if (r->method != NGX_HTTP_HEAD) {
> r->method = NGX_HTTP_GET;
> }
> 
> ```
> 
> Though it looks like it only does so for nginx itself, and this  
> indeed looks like a bug. The code should be similar to one in

Would you create an issue for this in tracker or do I need to so it  
doesn’t  
disappear in archives?

> error\_page handling:
> 
> ```
> if (r->method != NGX_HTTP_HEAD) {
> r->method = NGX_HTTP_GET;
> r->method_name = ngx_http_core_get_method;
> }
> 
> ```
> 
> If you want to get request and request method intact, use  
> X-Accel-Redirect to a named location instead.

Understood and it works for our case. We actually don’t want to send  
POST  
requests to location that issues internal redirects (our HRU service),  
but  
we haven’t found good way to avoid it.

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [December 23, 2015, 5:15pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/6 "2015-12-23T17:15:49Z")

</div>

On Wed, Dec 23, 2015 at 7:10 PM, Руслан Закиров [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Wed, Dec 23, 2015 at 6:49 PM, Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > X-Accel-Redirect changes a request from POST to GET.
> 
> No, it doesn’t. Getting request method POST on the backend and even form  
> data is intact.

Output from the psgi app (updated gist with data dumper):

127.0.0.1 - - [23/Dec/2015:19:05:46 +0300] “POST /a/ HTTP/1.0” 200 0 “-”  
“Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_10\_5) AppleWebKit/537.36  
(KHTML,  
like Gecko) Chrome/47.0.2526.106 Safari/537.36”  
{  
CONTENT\_LENGTH =\> 7,  
CONTENT\_TYPE =\> ‘application/json, application/x-www-form-urlencoded’,  
HTTP\_ACCEPT =\> ‘_/_’,  
HTTP\_ACCEPT\_ENCODING =\> ‘gzip, deflate’,  
HTTP\_ACCEPT\_LANGUAGE =\> ‘en-US,en;q=0.8,ru;q=0.6’,  
HTTP\_CACHE\_CONTROL =\> ‘no-cache’,  
HTTP\_CONNECTION =\> ‘close’,  
HTTP\_HOST =\> ‘127.0.0.1:5000’,  
HTTP\_ORIGIN =\> ‘chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm’,  
HTTP\_PRAGMA =\> ‘no-cache’,  
HTTP\_USER\_AGENT =\> ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_10\_5)  
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106  
Safari/537.36’,  
PATH\_INFO =\> ‘/b/’,  
QUERY\_STRING =\> ‘’,  
REMOTE\_ADDR =\> ‘127.0.0.1’,  
REMOTE\_PORT =\> 56137,  
REQUEST\_METHOD =\> ‘POST’,  
REQUEST\_URI =\> ‘/b/’,  
SCRIPT\_NAME =\> ‘’,  
SERVER\_NAME =\> 0,  
SERVER\_PORT =\> 5000,  
SERVER\_PROTOCOL =\> ‘HTTP/1.0’,  
‘psgi.errors’ =\> \*::STDERR,  
‘psgi.input’ =\> bless( \*{‘Stream::Buffered::PerlIO::$io’},  
‘FileHandle’  
),  
‘psgi.multiprocess’ =\> ‘’,  
‘psgi.multithread’ =\> ‘’,  
‘psgi.nonblocking’ =\> ‘’,  
‘psgi.run\_once’ =\> ‘’,  
‘psgi.streaming’ =\> 1,  
‘psgi.url\_scheme’ =\> ‘http’,  
‘psgi.version’ =\> [  
1,  
1  
],  
‘psgix.harakiri’ =\> 1,  
‘psgix.input.buffered’ =\> 1,  
‘[psgix.io](http://psgix.io)’ =\> bless( \*Symbol::GEN5, ‘IO::Socket::INET’ )  
}  
x=y&y=z  
127.0.0.1 - - [23/Dec/2015:19:05:46 +0300] “POST /b/ HTTP/1.0” 200 22  
“-”  
“Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_10\_5) AppleWebKit/537.36  
(KHTML,  
like Gecko) Chrome/47.0.2526.106 Safari/537.36”

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [February 9, 2016, 7:06pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/7 "2016-02-09T19:06:37Z")

</div>

Hi,

Are POST disallowed for X-Accel-Redirect?  
There is setup:  
nginx sends requests to Apache, which replies with X-Accel-Redirect and  
X-Path-Info.  
In X-Accel-Redirect there is path to php script, then nginx did do POST  
or  
GET to that script, but it stopped to work since 1.9.10.  
Is there a possibility to preserve original $request\_method? How to make  
it  
work without patching nginx?

Posted at Nginx Forum:

> **[Re: x-accel-redirect enables caching for POST requests](https://forum.nginx.org/read.php?2,263661,264437#msg-264437)**
>
> Hi, If location /a/ redirects a POST request to location /b/ using X-Accel-Redirect then result of the POST request is cached. Tested this and reproduced with nginx 1.6.3 and 1.9.7. Setup: https://gist.github.com/ruz/4a66ee78fedf27181799

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [February 9, 2016, 7:15pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/8 "2016-02-09T19:15:58Z")

</div>

Hello!

On Tue, Feb 09, 2016 at 01:06:21PM -0500, gglater62 wrote:

> Hi,
> 
> Are POST disallowed for X-Accel-Redirect?  
> There is setup:  
> nginx sends requests to Apache, which replies with X-Accel-Redirect and  
> X-Path-Info.  
> In X-Accel-Redirect there is path to php script, then nginx did do POST or  
> GET to that script, but it stopped to work since 1.9.10.  
> Is there a possibility to preserve original $request\_method? How to make it  
> work without patching nginx?

Original request method is preserved when using X-Accel-Redirect  
to a named location.

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [December 24, 2015, 7:24pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/9 "2015-12-24T19:24:16Z")

</div>

Hello!

On Thu, Dec 24, 2015 at 12:16:43AM +0300, wrote:

> > > No, it doesn’t. Getting request method POST on the backend and even form  
> > > indeed looks like a bug. The code should be similar to one in
> 
> Would you create an issue for this in tracker or do I need to so it doesn’t  
> disappear in archives?

No real need to open tickets. I’ve submitted a patch for an  
internal review here. Just in case, patch below.

# HG changeset patch

# User Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

# Date 1450981046 -10800

# Thu Dec 24 21:17:26 2015 +0300

# Node ID 10e233c763566b8466f6e302511094866a14e77a

# Parent 78b4e10b4367b31367aad3c83c9c3acdd42397c4

Upstream: fixed changing method on X-Accel-Redirect.

Previously, only r-\>method was changed, resulting in handling of a  
request  
as GET within nginx itself, but not in requests to proxied servers.

See [x-accel-redirect enables caching for POST requests](http://mailman.nginx.org/pipermail/nginx/2015-December/049518.html).

diff --git a/src/http/ngx\_http\_upstream.c b/src/http/ngx\_http\_upstream.c  
— a/src/http/ngx\_http\_upstream.c  
+++ b/src/http/ngx\_http\_upstream.c  
@@ -2499,6 +2499,7 @@ ngx\_http\_upstream\_process\_headers(ngx\_ht

```
         if (r->method != NGX_HTTP_HEAD) {
             r->method = NGX_HTTP_GET;

```

- 

```
           r->method_name = ngx_http_core_get_method;
       }

       ngx_http_internal_redirect(r, &uri, &args);

```

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [February 9, 2016, 9:54pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/10 "2016-02-09T21:54:17Z")

</div>

I found a workaround:

set $method $request\_method;  
if ($request ~ ^POST) { set $method POST; }  
fastcgi\_param REQUEST\_METHOD $method;

Posted at Nginx Forum:

> **[Re: x-accel-redirect enables caching for POST requests](https://forum.nginx.org/read.php?2,263661,264447#msg-264447)**
>
> Hi, If location /a/ redirects a POST request to location /b/ using X-Accel-Redirect then result of the POST request is cached. Tested this and reproduced with nginx 1.6.3 and 1.9.7. Setup: https://gist.github.com/ruz/4a66ee78fedf27181799

---

<div class="post-metadata">

**Author:** ![S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@S\_SSSSS\_S\_SSS\_S\_S](https://www.ruby-forum.com/u/S_SSSSS_S_SSS_S_S)\
**Post date:** [February 9, 2017, 5:00pm UTC](https://www.ruby-forum.com/t/x-accel-redirect-enables-caching-for-post-requests/243705/11 "2017-02-09T17:00:20Z")

</div>

Maxim D. wrote in post #1181273:

> Hello!
> 
> On Tue, Feb 09, 2016 at 01:06:21PM -0500, gglater62 wrote:
> 
> > Hi,
> > 
> > Are POST disallowed for X-Accel-Redirect?  
> > There is setup:  
> > nginx sends requests to Apache, which replies with X-Accel-Redirect and  
> > X-Path-Info.  
> > In X-Accel-Redirect there is path to php script, then nginx did do POST or  
> > GET to that script, but it stopped to work since 1.9.10.  
> > Is there a possibility to preserve original $request\_method? How to make it  
> > work without patching nginx?
> 
> Original request method is preserved when using X-Accel-Redirect  
> to a named location.
> 
> –  
> Maxim D.  
> [http://nginx.org/](http://nginx.org/)

Hi, sorry to necro, would you mind elaborating on how to use the old  
functionality with a named location? I’ve spent a while searching how to  
use a named location and can’t figure it out.

Here’s my nginx config working with an older nginx version, before the  
fix to enforce GET requests:

`
upstream gate_proxy {
    server 127.0.0.1:8889;
}
server {
listen 80 default_server;
```
# Send all traffic to gate first
location / {
    proxy_redirect off;
    proxy_pass_header Server;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For

```
$proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_pass http://gate_proxy;
}
```
# Proxy to Apache after X-Accel
location /proxy-to-web-app/ {
    internal;
    proxy_redirect off;
    proxy_pass_header Server;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Scheme $scheme;

    # Make sure the trailing slash is maintained here, as this

```
`

`affects the URI relayed.
proxy_pass http://127.0.0.1:8081/;
}
}
`

Thanks for any advice 🙂
