Как я могу создать местоположение в nginx, которое работает с AND без завершающего слеша?


46

Прямо сейчас у меня есть этот конфиг:

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

Однако, если я зайду www.mysite.com/phpmyadmin(заметьте отсутствие косой черты), он не найдет то, что я ищу 404. Я предполагаю, потому что я не включаю косую черту. Как я могу это исправить?


2
Я знаю, что этот вопрос довольно старый, но я хотел бы подчеркнуть необходимость изменить принятый ответ. Неопытные пользователи (те, кто будет искать этот вид QAs) могут создать дыры в безопасности, используя принятый в настоящее время ответ.
Bozzy

Ответы:


34

Это может быть в регулярном выражении, которое вы используете -

location ~ ^/phpmyadmin/(.*)$

Выше будет соответствовать / phpmyadmin /, / phpmyadmin / что-нибудь / еще / здесь, но это не будет соответствовать / phpmyadmin, потому что регулярное выражение включает в себя завершающий слеш.

Вы, вероятно, хотите что-то вроде этого:

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

Знак вопроса является квантификатором регулярного выражения и должен указывать nginx, что он соответствует нулю или одному из предыдущих символов (косая черта).

Предупреждение . Сообщество рассматривает это решение как возможную угрозу безопасности


Спасибо! И спасибо за объяснение. Пригодится в будущем.
Роб

15
Шаблон не совсем правильный. Он также может соответствовать пути типа "/ phpmyadmin1234", очевидно, это не то, что вы хотите. Решение @ kbec - правильное.
Мяу

3
Я прошу прощения за явное опровержение этого, но комментарий @Meow - способ, которым важно пренебречь. Это может привести к неправильной настройке веб-сервера, который может содержать дыры в безопасности.
Даниэль Ф

34

Лучшее решение:

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

Убедитесь, что у сервера есть права доступа в /home/phpmyadminпервую очередь.


Объяснение разницы с принятым ответом:

Это все о регулярных выражениях .

Прежде всего, ^символ означает, что вы хотите соответствовать с начала строки, а не где-то посередине. Знак $в конце означает совпадение с концом строки.

В (?:)средства , не захватив группу - мы не хотим его в результатах съемки, но мы хотим простую группу несколько символов. Мы группируем это следующим образом, потому что мы хотим, чтобы /символ был незначительной частью дочернего пути, а не существенной частью родительского пути.


Почему лучше?
Meekohi

2
@Meow ответил на принятый ответ
kbec

2
Это должен быть принятый ответ
Yonn Trimoreau

@Meekohi Я написал объяснение
kbec

8

Почему бы тебе просто не использовать

location /phpmyadmin {
    alias /home/phpmyadmin;
}

?


Потому что это не сработало для меня. Смотрите здесь: serverfault.com/questions/375602/…
Роб

1
@Rob Вы пробовали это без косой черты в aliasдирективе?
Шейн Мэдден

Это на самом деле правильный ответ и правильный способ сделать это. Просто исключите косую черту, и она работает для URL, введенных как с косой чертой, так и без нее. Нет необходимости усложнять что-либо в Nginx, будьте проще, сложные регулярные выражения и другие забавные вещи только замедляют работу Nginx.
MitchellK

4
Проблема с этим состоит в том, что это также будет соответствовать /phpmyadminblahblahblahblahили любой другой комбинации
Гэри Грин

6

Я знаю, что это старый вопрос, но для всех, кто попадает сюда через Google, я решил его следующим образом (вариант @ kbec, который был довольно хорошим):

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

Это захватит любой вариант /fooи перенаправит его /barна другой URL (включая параметры). Я показываю это с proxy_passдирективой, но она также будет работать alias.

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

Это работает, потому $1что опционально будет захватывать подресурсы плюс начальный слеш, поэтому не будет захватывать подобные вещи /fooextra/. Он также будет правильно перенаправлять текущий или отсутствующий завершающий слеш.


1
Спасибо за рассмотрение углового случая желания использовать proxy_pass и таким образом заботиться об аргументах. У тебя есть мой голос.
Даниэль Ф

2

Это перенаправление будет переписывать только URL с косой чертой и без нее. Все, что придет после косой черты, не будет перезаписано.

domain.com/location => перенаправлен на domain.com/new/location
domain.com/location => перенаправлен на domain.com/new/location
domain.com/location/other => не перенаправлен

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


0

Я сделал это так

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

0

Почему бы не написать две переписки просто:

location ~ ^/phpmyadmin
{
    rewrite /phpmyadmin /home/phpmyadmin/ break;
    rewrite /phpmyadmin/(.*) /home/phpmyadmin/$1 break;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.