Comment puis-je créer un emplacement dans nginx qui fonctionne avec AND sans barre oblique finale?

46

En ce moment j'ai cette config:

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

Cependant, si je visite www.mysite.com/phpmyadmin(notez le manque de barre oblique), il ne trouvera pas ce que je recherche comme un 404. Je suppose que je n'inclus pas la barre oblique. Comment puis-je réparer cela?

Rob
la source
2
Je sais que cette question est assez ancienne, mais je voudrais néanmoins insister sur la nécessité de changer la réponse acceptée. Les utilisateurs inexpérimentés (ceux qui recherchent ce type de QA) peuvent créer des failles de sécurité en utilisant la réponse actuellement acceptée.
Bozzy

Réponses:

34

C'est peut-être dans l'expression régulière que vous utilisez -

location ~ ^/phpmyadmin/(.*)$

Ce qui précède correspondra à / phpmyadmin /, / phpmyadmin / n'importe quoi / d'autre / ici, mais il ne correspondra pas à / phpmyadmin car l'expression régulière inclut la barre oblique finale.

Vous voulez probablement quelque chose comme ça:

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

Le point d'interrogation est un quantificateur d'expression régulière et doit indiquer à nginx de correspondre à zéro ou à l'un des caractères précédents (la barre oblique).

Avertissement: La communauté a vu cette solution, telle quelle, comme un risque possible pour la sécurité

faneur
la source
Je vous remercie! Et merci pour l'explication, aussi. Sera utile dans le futur.
Rob
15
Le modèle n'est pas tout à fait correct. Il peut également correspondre à un chemin comme "/ phpmyadmin1234", ce n'est évidemment pas ce que vous voulez. La solution de @ kbec est la bonne.
Meow
3
Je suis désolé d’avoir explicitement voté contre cela, mais le commentaire @Meow est un moyen important de le négliger. Cela peut conduire à un serveur Web mal configuré qui pourrait contenir des failles de sécurité.
Daniel F
34

La meilleure solution:

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

Assurez-vous que le serveur dispose des autorisations nécessaires en /home/phpmyadminpremier.


Explication de la différence avec réponse acceptée:

Tout est question d' expressions régulières .

Tout d'abord, le caractère ^signifie que vous voulez faire correspondre le début de la chaîne et non quelque part au milieu. Le $à la fin signifie correspondre à la fin de la chaîne.

Les (?:)groupes moyens ne capturant pas - nous ne le voulons pas dans les résultats de la capture, mais nous voulons simplement grouper certains caractères. Nous le regroupons comme ceci, car nous voulons que le caractère /soit une partie non significative du chemin enfant et non une partie importante du chemin parent.

kbec
la source
Pourquoi est-ce mieux?
Meekohi
2
@Meow a répondu à cela sur la réponse acceptée
kbec le
2
Cela devrait être la réponse acceptée
Yonn Trimoreau
@ Meekohi, j'ai écrit une explication
kbec
8

Pourquoi ne pas simplement utiliser

location /phpmyadmin {
    alias /home/phpmyadmin;
}

?

femme
la source
Parce que ça ne marchait pas pour moi. Voir ici: serverfault.com/questions/375602/…
Rob
1
@Rob L'avez-vous essayé sans la dernière barre oblique de la aliasdirective?
Shane Madden
C'est en fait la bonne réponse et la bonne façon de le faire. Excluez simplement la barre oblique finale et cela fonctionne pour les URL tapées avec et sans la barre oblique finale. Pas besoin de compliquer quoi que ce soit sur Nginx, restez simple, des regex compliquées et d’autres choses amusantes ne feront que ralentir Nginx.
MitchellK
4
Le problème, c’est qu’il va également correspondre à /phpmyadminblahblahblahblahou à une autre combinaison
Gary Green
6

Je sais que c'est une vieille question, mais pour tous ceux qui se retrouvent ici via Google, je l'ai résolue de la manière suivante (variation de celle de @ kbec, qui était plutôt bonne):

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

Cela capturera toute variation de /fooet le redirigera vers /barune autre URL (y compris les paramètres). Je le montre avec une proxy_passdirective mais cela fonctionnerait aussi avec alias.

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

Cela fonctionne parce $1que capturera éventuellement les sous-ressources ainsi que la barre oblique, de sorte qu'il ne capture pas les éléments tels que /fooextra/. Il redirigera également correctement un slash de fin présent ou non présent.

dlouzan
la source
1
Merci de prendre en compte le cas de vouloir utiliser proxy_pass et de se soucier des arguments. Vous avez mon upvote.
Daniel F
2

Cette redirection ne fera que réécrire les URL avec et sans la barre oblique finale. Tout ce qui vient après la barre oblique ne sera pas écrasé.

domain.com/location => redirigé vers domain.com/new/location
domain.com/location => redirigé vers domain.com/new/location
domain.com/location/other => non redirigé

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

Avez-vous essayé d'utiliser try_filesdirective?

try_files $uri $uri/ =404;
Prasanth
la source
0

Je l'ai fait comme ça

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

Pourquoi ne pas mettre deux réécrit simplement:

location ~ ^/phpmyadmin
{
    rewrite /phpmyadmin /home/phpmyadmin/ break;
    rewrite /phpmyadmin/(.*) /home/phpmyadmin/$1 break;
}
木 郷
la source