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;
  • Instead of $args ~ id=(.+) test in the if statement, you should be able to simply use $arg_id. It is a bit faster, since the regex engine isn't used. – Tero Kilkanen Aug 26 '16 at 7:58
  • I overlooked it, thanks so much for the feedback again – Alexandre Mélard Aug 26 '16 at 8:00

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.

  • I came up with a pretty close solution yesterday, I'll edit my question using a mix of your solution and mine, thanks for your time ! – Alexandre Mélard Aug 26 '16 at 7:34
  • you don't need to add the $args in rewrite as the arguments are automatically passed on. – Alexandre Mélard Aug 26 '16 at 7:39

One possible way to do this is to have the /location be handled by a CGI, or PHP script (see here for nginx and php) and the have them inspect the QUERY_STRING and issue back a location header

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.