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?

4
  • The proxy_method maybe?
    – HBruijn
    Commented Sep 10, 2015 at 21:11
  • proxy_method does not carry over the foo=bar part, unfortunately.
    – StasM
    Commented Sep 10, 2015 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
    Commented Sep 11, 2015 at 5:34
  • 301/302 HTTP redirect may help but it is highly not recommended, try some kind of middleware that turns POST into GET.
    – Anatoly
    Commented Sep 11, 2015 at 8:08

2 Answers 2

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
    }
}
1
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
    }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .