26

My iOS app is currently accessing domain A via http POST but I would like to forward all requests to domain B.

If I use the usual rewrite ^/(.*)$ http://mydomain/$1 permanent; the POST data seems to get lost.

How can I pass HTTP POST data to a different domain using NginX?

nkamm
  • 113
  • 7
Jiho Kang
  • 967
  • 2
  • 9
  • 8

2 Answers2

39

Try using the reverse proxy support instead. An example location section would be:

location / {
  proxy_pass      http://localhost:8080;
  proxy_redirect  http://localhost:8080/ /;
  proxy_read_timeout 60s;

  # May not need or want to set Host. Should default to the above hostname.
  proxy_set_header          Host            $host;
  proxy_set_header          X-Real-IP       $remote_addr;
  proxy_set_header          X-Forwarded-For $proxy_add_x_forwarded_for;
}

This example will pass through all requests to this server block to a second server running on localhost:8080. This preserves POST's and should also preserve other request types too if it ever becomes an issue.

The issue is that external redirects will never resend POST data. This is written into the HTTP spec (check the 3xx section). Any client that does do this is violating the spec.

If the 301/302 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

I'm fairly sure that most browsers implement this by simply forcing the redirected request to be a GET request. Theoretically, the spec does allow for a browser that would ask the user whether to redirect the POST data, but I'm unaware of any that currently do.

Matthew Scharley
  • 1,467
  • 2
  • 14
  • 19
  • a little bit confused from comment. Do I generally want to set the `proxy_set_header` values? Otherwise I guess that remote address becomes the remote address of the proxy server but what I usually want is the remote address of the client, correct? – George Pligoropoulos Mar 02 '14 at 12:24
  • Thanks for the answer that saved me! Is there a way to set up nginx so that it passes post requests correctly back to uwsgi but with sockets instead of running uwsgi in http mode? – Greg Jennings Apr 09 '15 at 01:11
  • @GregJennings A little late for a reply, but one would use the 'uwsgi_pass' directive instead of 'proxy_pass'. Just in case someone else wanders by looking... – Kamilion Apr 16 '19 at 18:43
  • I'm curious about `proxy_redirect http://localhost:8080/ /` Why the second individual `/`? What impact does that have? – Will Aug 07 '19 at 10:14
  • 1
    @Will `proxy_redirect` takes two arguments. See the docs: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect – Matthew Scharley Aug 19 '19 at 10:07
0

You can also achieve this in Nginx but using the mirror plugin not rewrite:

location "/post/uri/to/redirect/" {                                        
    mirror "/mirror";                                                       
    mirror_request_body on;                                                 
    return 200;                                                             
}                                                                           

location = "/mirror" {                                                      
    internal;                                                               
    proxy_pass "https://target_domain$request_uri";                   
    proxy_set_header Host "target_domain";                            
    proxy_set_header X-Original-URI $request_uri;                           
    proxy_set_header X-SERVER-PORT $server_port;                            
    proxy_set_header X-SERVER-ADDR $server_addr;                            
    proxy_set_header X-REAL-IP $remote_addr;                                
}                                                                           
faham
  • 101
  • 3