Nginx redirect based on key word in arguments

nginxproxypassredirect

I'm very new to nginx (1 day or so) and we are using it as a reverse proxy for a few applications. We are going to add another app which will process a small subset of existing requests. I'm trying to intercept urls which hit the cod/articles API and contain item.id in the arguments, and then send these requests and their arguments to this new app which I have stubbed for now as its not ready.

I'd like to leave all other requests alone ie API is not "/cod/acticles", request does not contain item.id in the arguments.

Example url which should be sent to the new app.

http://server/mdata/transfer/CUSTOMER/cod/articles?filter={"item.id":"ID00000000123"......}&limit=50&fields=[]&sort=.......

Example urls which should not be sent.

http://server/mdata/transfer/customer/cod/articles?filter{"lang":"en_US","article.id":"123456"}&limit=50....
http://server/mdata/transfer/customer/cod/items?filter{"lang":"en_US","article.id":"123456"}&limit=50....
http://server/mdata/transfer/customer/doc/articles?filter{"lang":"en_US","article.id":"123456"}&limit=50....

Note: …. just means theres other arguments

Below is my current config in Nginx. It appears to do the "intercepting" but there are a couple of things which look wrong to me.

Firstly, I believe using "if" is not ideal, and there might be better ways of doing this. But I have not been successful matching the arguments section.

Secondly, the nginx access logs show 3 requests for a matching url. x2 301 responses, and 1 200 response. Is this expected? If so is there a better way to do this so that there is only 1 request, as it seems like i've created addtional load for nginx.

#existing config for all /mdata/transfer/* APIs
location /mdata/transfer/ {
        add_header Access-Control-Allow-Origin *;
        allow all;
        proxy_pass        http://mds;
}

#static page which acts as a stub end point for testing.
location /proxyapp {
        root /opt/www;
}

#new config where I try to intercept /mdata/transfer/customer/cod/articles API with item.id contained in the arguments.
location ~ /mdata/transfer/customer/cod/articles {
        set $cst_proxy mds/mdata/transfer/customer/cod/articles;
        if ($args ~ "item.id") {
                set $cst_proxy localhost/proxyapp;
        }
        proxy_pass http://$cst_proxy$is_args$args;
        proxy_redirect off;
}

Best Answer

Solved it with the following code

   upstream proxy-app {
    server 127.0.0.1:4000;
}

upstream mds {
    server 127.0.0.1:1234;
}

location /mdata/transfer/CUSTOMER/cod/articles {
        add_header Access-Control-Allow-Origin *;
        set $cst_proxy mds;
        if ($args ~ "item.id") {
                set $cst_proxy proxy-app;
        }
        proxy_pass http://$cst_proxy;
}
Related Topic