36

Right now I have this config:

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

However, if I visit www.mysite.com/phpmyadmin (note the lack of trailing slash), it won't find what I'm looking for a 404. I assume because I don't include the trailing slash. How can I fix this?

34

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).

HTH

  • Thank you! And thank you for the explanation, as well. Will come in handy in the future. – Rob Apr 3 '12 at 6:08
  • 10
    The pattern isn't quite correct. It can also match path like "/phpmyadmin1234", obviously that's no what you want. @kbec's solution is the right one. – Meow Aug 20 '15 at 12:10
  • I'm sorry for explicitly downvoting this, but @Meow comment is way to important to neglect. This can lead to a misconfigured webserver which could contain security holes. – Daniel F Jan 25 at 20:50
25

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.

  • Why is it better? – Meekohi Jul 13 '17 at 14:12
  • 1
    @Meow answered this on accepted answer – kbec Jul 13 '17 at 15:43
  • This should be the accepted answer – Yonn Trimoreau Sep 4 '18 at 8:06
  • @Meekohi I wrote explanation – kbec Sep 4 '18 at 8:23
7

Why wouldn't you just use

location /phpmyadmin {
    alias /home/phpmyadmin;
}

?

  • Because that wasn't working for me. See here: serverfault.com/questions/375602/… – Rob Apr 3 '12 at 5:35
  • 1
    @Rob Did you try it without the trailing slash on the alias directive? – Shane Madden Apr 3 '12 at 17:04
  • This is actually the correct answer and correct way of doing it. Simply exclude the trailing slash and it works for urls typed both with and without the trailing slash. No need for complicating anything on Nginx keep it simple, complicated regex and other funny things will only slow Nginx down. – MitchellK Jun 30 '18 at 8:52
3

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.

  • Thanks for considering the corner case of wanting to use proxy_pass and thus caring about the arguments. You have my upvote. – Daniel F Jan 25 at 21:26
2

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;
}
1

Have you tried using try_files directive?

try_files $uri $uri/ =404;
0

I did it like that

rewrite ^/promo/?$     http://example.com/promo/page43902.html;
location /promo/ {
    root /var/www;
}

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.