5

I've got a backend server that, for various reasons, only processes GET requests. This server is located behind nginx proxy (i.e. all access is done to nginx, which proxies it to the backend with proxy_pass). Is it possible to make nginx rewrite POST requests into GET requests, i.e. so that POST /foo with body content type application/x-www-form-urlencoded and body foo=bar would be proxied to GET /foo?foo=bar?

StasM
  • 163
  • 1
  • 1
  • 7
  • The [`proxy_method`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_method) maybe? – HBruijn Sep 10 '15 at 21:11
  • proxy_method does not carry over the foo=bar part, unfortunately. – StasM Sep 10 '15 at 21:42
  • 3
    I *strongly* suspect that you're going to end up going down to lua; you'll need to handle the case where the URL has query params as well, and merge them. I feel for you, having to deal with a backend device this horribly broken, and presumably clients you can't fix to not send POSTs. I'm glad I don't have your job. – womble Sep 11 '15 at 05:34
  • 301/302 HTTP redirect may help but it is highly not recommended, try some kind of middleware that turns POST into GET. – Anatoly Sep 11 '15 at 08:08

2 Answers2

5

The small example is working for me with nginx 1.10.x at ubuntu 16.04 with nginx-extras (contains lua). It doesnt respect query arguments from the request, to merge them with the post body.

server {
    ...
    server_name ...;

    client_max_body_size 4k; # prevent too long post bodies

    location / {
            if ($request_method = POST ) {
                access_by_lua '
                        ngx.req.read_body()
                        local data = ngx.req.get_body_data()
                        ngx.req.set_uri_args(data)
                ';                
            }

            proxy_pass http://yourupstreamdestination;
            proxy_method GET;                    # change method
            include /etc/nginx/proxy_params.inc; # include some params
    }
}
Falk Nisius
  • 66
  • 1
  • 3
  • https://stackoverflow.com/a/51139521/1707015 (not exactly to the question, but maybe helpful). – uav Jul 02 '18 at 15:37
1

Improving Falk Nisius's original answer, but without the caveat:

It doesnt respect query arguments from the request, to merge them with the post body.

You can switch to using get_post_args instead of get_body_data, which returns a table instead of a string.

set_uri_args can take a string OR a table, so in this case, you can combine it with the table from get_post_args.

Combining the 2 tables will get you all arguments, as per example:

server {
    ...
    server_name ...;

    client_max_body_size 4k; # prevent too long post bodies

    location / {
            if ($request_method = POST ) {
                access_by_lua '
                        ngx.req.read_body()

                        local post_data = ngx.req.get_post_args()
                        local get_data = ngx.req.get_uri_args()
                        for k,v in pairs(get_data) do post_data[k] = v end

                        ngx.req.set_uri_args(post_data)
                ';                
            }

            proxy_pass http://yourupstreamdestination;
            proxy_method GET;                    # change method
            include /etc/nginx/proxy_params.inc; # include some params
    }
}
Znuff
  • 31
  • 2