Effect of trailing question mark (?) in nginx rewrite directive's replacement URI

I'm trying to understand the difference between rewrite ^/search/(.*)$ /search.php?q=$1 and rewrite ^/search/(.*)$ /search.php?q=$1?. The difference is the trailing ? in the replacement URI.

If the request URI is /search/apple?opt=123 then how are the URI rewritten differently?

I'm guessing for rewrite ^/search/(.*)$ /search.php?q=$1 it will be /search.php?q=apple&opt=123 and for rewrite ^/search/(.*)$ /search.php?q=$1? it will be /search.php?q=apple? But I'm not sure.


Solution 1:

As per https://nginx.org/r/rewrite...

If a replacement string includes the new request arguments, the previous request arguments are appended after them. If this is undesired, putting a question mark at the end of a replacement string avoids having them appended

Here's the bare minimal code to test this scenario...

# configuration file /etc/nginx/nginx.conf:
events {}

http {
    server {
        rewrite ^/search/(.*)$ /search.php?q=$1 permanent;
        # rewrite ^/search/(.*)$ /search.php?q=$1? permanent;
    }
}

Permanent flag is added only for testing. We can save the above code as nginx.conf and start Nginx. curl output for the above code confirms /search/apple?opt=123 will redirect to /search.php?q=apple&opt=123.

Similarly, for the second rewrite condition...

# configuration file /etc/nginx/nginx.conf:
events {}

http {
    server {
        # rewrite ^/search/(.*)$ /search.php?q=$1 permanent;
        rewrite ^/search/(.*)$ /search.php?q=$1? permanent;
    }
}

curl output for the above code confirms /search/apple?opt=123 will redirect to /search.php?q=apple.

So,

If the request URI is /search/apple?opt=123 then how are the URI rewritten differently?

I'm guessing for rewrite ^/search/(.)$ /search.php?q=$1 it will be /search.php?q=apple&opt=123 and for rewrite ^/search/(.)$ /search.php?q=$1? it will be /search.php?q=apple? But I'm not sure.

You are right and this is the expected result.