How can I create a location in nginx that works with AND without a trailing slash?

Solution 1:

The better solution:

location ~ ^/phpmyadmin(?:/(.*))?$ {
    alias /home/phpmyadmin/$1;
}

Ensure that server has permissions to /home/phpmyadmin first.


Explanation of difference with accepted answer:

It's all about regular expressions.

First of all, the ^ char means that you want to match from beginning of string and not somewhere in the middle. The $ at the end means matching to the end of the string.

The (?:) means non-capturing group - we don't want it in the capturing results, but we want to simple group some chars. We group it like this, because we want the / char to be a nonsignificant part of the child path, and not a significant part of the parent path.

Solution 2:

It might be in the regular expression that you're using --

location ~ ^/phpmyadmin/(.*)$

The above will match /phpmyadmin/, /phpmyadmin/anything/else/here, but it won't match /phpmyadmin because the regular expression includes the trailing slash.

You probably want something like this:

location ~ /phpmyadmin/?(.*)$ {
    alias /home/phpmyadmin/$1;
}

The question mark is a regular expression quantifier and should tell nginx to match zero or one of the previous character (the slash).

Warning: The community seen this solution, as is, as a possible security risk


Solution 3:

Why wouldn't you just use

location /phpmyadmin {
    alias /home/phpmyadmin;
}

?


Solution 4:

I know this is an old question, but for anybody that ends up here via Google, I solved it the following way (variation of @kbec's one, which was quite good):

location ~ ^/foo(/.*)?$ {
  proxy_pass http://$backend$1$is_args$args
}

This will capture any variation of /foo and redirect it to /bar on another url (including parameters). I am showing it with a proxy_pass directive but it would also work with alias.

  • /foo -> /bar
  • /foo/ -> /bar/
  • /foo/sub -> /bar/sub
  • /foo/sub1/sub2/?param=value -> /bar/sub1/sub2/?param=value

It works because $1 will optionally capture the subresources plus the leading slash, so it won't capture things like /fooextra/. It will also redirect a present or non-present ending slash properly.


Solution 5:

This redirect will only rewrite URLs with and without the trailing slash. Anything that comes after the slash won't be overwritten.

domain.com/location => redirected to domain.com/new/location
domain.com/location => redirected to domain.com/new/location
domain.com/location/other => not redirected

server {
  # 301 URL Redirect
  rewrite ^/location/?$ /new/location permanent;
}

Tags:

Nginx