¿Cómo puedo crear una ubicación en nginx que funcione con AND sin una barra diagonal final?

46

En este momento tengo esta configuración:

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

Sin embargo, si visito www.mysite.com/phpmyadmin(tenga en cuenta la falta de una barra diagonal final), no encontrará lo que estoy buscando un 404. Supongo que no incluyo la barra diagonal final. ¿Cómo puedo arreglar esto?

Robar
fuente
2
Sé que esta pregunta es bastante antigua, sin embargo, me gustaría enfatizar la necesidad de cambiar la respuesta aceptada. Los usuarios sin experiencia (los que buscarán este tipo de QA) pueden crear agujeros de seguridad al usar la respuesta actualmente aceptada.
Bozzy

Respuestas:

34

Puede estar en la expresión regular que está utilizando:

location ~ ^/phpmyadmin/(.*)$

Lo anterior coincidirá con / phpmyadmin /, / phpmyadmin / anything / else / here, pero no coincidirá con / phpmyadmin porque la expresión regular incluye la barra diagonal final.

Probablemente quieras algo como esto:

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

El signo de interrogación es un cuantificador de expresiones regulares y debe indicarle a nginx que coincida con cero o con uno de los caracteres anteriores (la barra inclinada).

Advertencia: la comunidad vio esta solución, como es, como un posible riesgo de seguridad

labrador
fuente
¡Gracias! Y gracias por la explicación, también. Será útil en el futuro.
Rob el
15
El patrón no es del todo correcto. También puede coincidir con la ruta como "/ phpmyadmin1234", obviamente eso no es lo que quieres. La solución de @kbec es la correcta.
Miau
3
Lamento haber rechazado explícitamente esto, pero el comentario de @Meow es muy importante para descuidarlo. Esto puede conducir a un servidor web mal configurado que podría contener agujeros de seguridad.
Daniel F
34

La mejor solución:

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

Asegúrese de que el servidor tenga permisos /home/phpmyadminprimero.


Explicación de la diferencia con la respuesta aceptada:

Se trata de expresiones regulares .

En primer lugar, el ^carácter significa que desea hacer coincidir desde el principio de la cadena y no en el medio. Al $final significa que coincide con el final de la cadena.

El grupo (?:)significa no capturar: no lo queremos en los resultados de captura, pero queremos agrupar algunos caracteres de manera simple. Lo agrupamos así, porque queremos que el /carácter sea una parte no significativa de la ruta secundaria y no una parte significativa de la ruta primaria.

kbec
fuente
¿Por qué es mejor?
Meekohi
2
@Meow respondió esto en respuesta aceptada
kbec
2
Esta debería ser la respuesta aceptada
Yonn Trimoreau
@Meekohi escribí una explicación
kbec
8

¿Por qué no usarías

location /phpmyadmin {
    alias /home/phpmyadmin;
}

?

womble
fuente
Porque eso no estaba funcionando para mí. Ver aquí: serverfault.com/questions/375602/…
Rob el
1
@Rob ¿Lo probaste sin la barra diagonal de la aliasdirectiva?
Shane Madden
Esta es realmente la respuesta correcta y la forma correcta de hacerlo. Simplemente excluya la barra diagonal final y funciona para las URL escritas con y sin la barra diagonal final. No es necesario complicar nada en Nginx, manténgalo simple, la expresión regular complicada y otras cosas divertidas solo retrasarán a Nginx.
MitchellK
44
El problema con esto es que también coincidirá con /phpmyadminblahblahblahblahcualquier otra combinación
Gary Green
6

Sé que esta es una vieja pregunta, pero para cualquiera que termine aquí a través de Google, la resolví de la siguiente manera (variación de la de @ kbec, que fue bastante buena):

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

Esto capturará cualquier variación /fooy la redireccionará a /barotra url (incluidos los parámetros). Lo estoy mostrando con una proxy_passdirectiva pero también funcionaría alias.

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

Funciona porque $1opcionalmente capturará los recursos secundarios más la barra diagonal, por lo que no capturará cosas como /fooextra/. También redirigirá una barra oblicua final presente o no presente correctamente.

dlouzan
fuente
1
Gracias por considerar el caso de la esquina de querer usar proxy_pass y por lo tanto preocuparse por los argumentos. Tienes mi voto a favor.
Daniel F
2

Esta redirección solo reescribirá las URL con y sin la barra diagonal final. Cualquier cosa que venga después de la barra no se sobrescribirá.

domain.com/location => redirigido a domain.com/new/location
domain.com/location => redirigido a domain.com/new/location
domain.com/location/other => no redirigido

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

¿Has intentado usar la try_filesdirectiva?

try_files $uri $uri/ =404;
Prasanth
fuente
0

Lo hice asi

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

¿Por qué no poner dos reescrituras simplemente:

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