2

I'm struggling with nginx config. I have a server block where I want all requests to go to index.php?tags=$uri, unless $uri exists (like index.php?a=b or /?a=b).

I would expect:

try_files $uri index.php?tags=$uri;

but, no, that would be too simple. That doesn't work for /?a=b, which is apparently not found, so it directs to index.php?tags=/

Maybe if I explicitly include an index, which is reasonable:

index index.php;

Nope. No dice. Same exact result across the board.

Also nothing with $args, $request_uri or combinations. Also not it:

try_files $request_uri/index.php $request_uri index.php?tags=$request_uri; // now I'm just guessing

Apache somehow knew what I meant always. Why doesn't nginx? I'd like these redirects (without redirect or if):

/   => /index.php
/index.php   => /index.php
/index.php?a=b   => /index.php?a=b
/?a=b   => /index.php?a=b
/foo   => /index.php?tags=foo (or /index.php?tags=/foo)
/foo/bar   => /index.php?tags=foo/bar (or /index.php?tags=/foo/bar)
/foo?bar=yes   => /index.php?tags=/foo%3Fbar%3Dyes

I'd like the query string to be encoded when redirected, but not the path, but really that's not so important.

(I also don't understand the practical difference between $uri and $request_uri. They seem to be doing the same half the time. But that's for another day.)

Much thanks.

Rudie
  • 769

1 Answers1

5

I am achieving the wished result with the following configuration snippet:

location = / {
    index index.php;
}

location / {
    try_files $uri /index.php?tags=$request_uri;
}

try_files tries... files. When you seek / with it, you search for a file with the same name, it is not interpreted as 'find the index file'. index does that job. Hence you need to separate this special case from the default, fall-back location.

The best part is your last wish: the arguments won't even be encoded since they do not need to (only the first question mark of a URI is relevant as everything following is an argument anyway).

Mind the use of $request_uri (which contains the requested URI, with arguments, but does not normalize/cleanse it) instead of the normalized $uri (which cleans up the URI and remove arguments). Thus you may end up with:

///foo?bar=yes => index.php?tags=///foo?bar=yes

If you mind about it, you may use $uri in combination with $args:

location = / {
    index index.php;
}

location / {
    try_files $uri /index.php?tags=$uri?$args;
}

producing:

///foo?bar=yes => index.php?tags=/foo?bar=yes