Search code examples
nginxhttp-proxynginx-reverse-proxynginx-config

Set proxy_pass in nginx based on request_method


I have two application and a nginx server on top of that. I want to proxy all GET requests coming on nginx to one app running on http://127.0.0.1:9101/ and proxy all other request methods to http://10.41.115.241:8000/

I have tried couple of options but none worked I have tried using limit_exempt

  location /api/v1/executions {
    error_page 502 = @apiError;

    rewrite ^/api/(.*)  /$1 break;

    proxy_pass            http://127.0.0.1:9101/;

    limit_except PUT POST DELETE {
      proxy_pass http://10.41.115.241:8000/;
    }


    proxy_read_timeout    90;
    proxy_connect_timeout 90;
    proxy_redirect        off;

    proxy_set_header      Host $host;
    #proxy_set_header      X-Real-IP $remote_addr;
    proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;

    #proxy_set_header Connection '';
    chunked_transfer_encoding off;
    proxy_buffering off;
    proxy_cache off;
    #proxy_set_header Host $host;
  }

I have also tried if condition

  location /api/v1/executions {
    error_page 502 = @apiError;

    rewrite ^/api/(.*)  /$1 break;


    proxy_pass http://10.41.115.241:8000/;

    if ($request_method = GET) {
      proxy_pass            http://127.0.0.1:9101/;
    }

    proxy_read_timeout    90;
    proxy_connect_timeout 90;
    proxy_redirect        off;

    proxy_set_header      Host $host;
    #proxy_set_header      X-Real-IP $remote_addr;
    proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;

    #proxy_set_header Connection '';
    chunked_transfer_encoding off;
    proxy_buffering off;
    proxy_cache off;
    #proxy_set_header Host $host;
  }

but in both ways I got this error

"proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /path/to/config

Solution

  • Always try to use map instead of if for conditional logic in NGINX. Unless it's absolutely impossible with map.. In your particular case, it's easy.

    Create a variable $backend which will hold your desired proxy_pass value depending on the request methods:

    http {
        map $request_method $backend {
            default http://10.41.115.241:8000/; 
            GET http://127.0.0.1:9101/;
        }
        ...
    }
    

    Then use it you in your config:

      location /api/v1/executions {
        error_page 502 = @apiError;
    
        rewrite ^/api/(.*)  /$1 break;
    
    
        proxy_pass $backend;
    
        proxy_read_timeout    90;
        proxy_connect_timeout 90;
        proxy_redirect        off;
    
        proxy_set_header      Host $host;
        #proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
    
        #proxy_set_header Connection '';
        chunked_transfer_encoding off;
        proxy_buffering off;
        proxy_cache off;
        #proxy_set_header Host $host;
      }