Nginx – use rewrite nginx matching location with arg key

nginx

I am using one URL for different purposes:

  1. /path/items : returns a list of items
  2. /path/items?id=XXX : redirects to URL /path/items/item?id=XXX

EDIT: Added solution based on Tero's input

I've tried that rule in my nginx conf file:

location ~ / {
    rewrite '^/path/items\?id=([0-9]*)$' /items/item?id=$1? break;
}

When I access the page /path/items?id=XXX, I get the following log:

2016/08/25 14:08:53 [notice] 22903#0: 1 "^/path/items\?id=([0-9])$"
does not match "/path/items", client: XXX, server: local.xxx.ins,
request: "GET /path/items?id=32442305 HTTP/1.1", host: "local.xxx.ins"

I understand from that log that nginx remove the args before doing the match. but I cannot find out how to get a match including the args.

I came up with a solution realy close to Tero's one.

location ~ /(path1|path2|path3) {
    if ($arg_id) {
        rewrite ^ $uri/item break;
     }
     proxy_pass http://local.xxx.ins:8080;
}

Best Answer

You cannot process query strings within rewrite directives. You can only process URI there.

You can try this configuration:

location /path/items {
    if ($arg_item) {
        rewrite ^ /items/item break;
    }
    try_files $uri $uri/ =404;
}

The location /path/items restricts this behavior only to URIs that have /path/items prefix. We test if a query argument item is defined in the HTTP request. If it is, we rewrite the URI. Otherwise we just try the URIs given by the client.

You might need modification of the try_files directive depending on how the items list is made. You might also need a root directive if it is not defined in the server level.