Cómo elige nginx un location
- El URI se normaliza primero: decodificación porcentual, barras repetidas fusionadas,
.y..resueltos. La cadena de consulta nunca forma parte de la coincidencia de location. - Se comparan todos los locations de prefijo (sin modificador,
=,^~). Una coincidencia exacta=gana de inmediato. Si no, se recuerda el prefijo coincidente más largo. - Si ese prefijo más largo tiene
^~, gana y se saltan las regex. - Los locations regex (
~sensible a mayúsculas,~*insensible) se prueban en el orden en que aparecen en el archivo. Gana la primera coincidencia, aunque antes haya coincidido un prefijo más largo. - Si ninguna regex coincide, se usa el prefijo más largo recordado.
- Dentro del location ganador, el mismo procedimiento se repite para los locations anidados.
Dos consecuencias sorprenden más: un simple location /images/ pierde frente a location ~ \.png$ para /images/a.png, porque las regex se comprueban después de los prefijos; y location /api coincide también con /apiary, porque los prefijos son prefijos de cadena, no segmentos de ruta. Usa /api/ o ^~ cuando eso es lo que quieres decir.
proxy_pass y la barra final
Si proxy_pass tiene una parte de URI (cualquier cosa después del host, aunque sea solo /), nginx sustituye la parte del URI de la petición que coincidió con el prefijo del location por ella. location /api/ { proxy_pass http://app/; } convierte /api/users en /users. Sin parte de URI, el URI de la petición pasa sin cambios. Las barras desparejadas (/api frente a /api/, o http://app frente a http://app/) producen //users o users — el probador imprime el URI upstream exacto para que lo veas. En un location regex no se permite una parte de URI a menos que un rewrite haya cambiado antes el URI.
root frente a alias
root añade el URI entero al directorio: root /srv; location /static/ sirve /srv/static/x.css. alias sustituye el prefijo del location: alias /srv/assets/; location /static/ sirve /srv/assets/x.css. Con alias, las barras finales del location y del alias deben coincidir, y en un location regex el alias debe usar capturas.
Flags de rewrite
| Flag | Efecto |
|---|---|
| last | dejar de procesar rewrites, volver a empezar la coincidencia de location con el nuevo URI (máx. 10 veces, luego 500) |
| break | dejar los rewrites, quedarse en el location actual con el nuevo URI |
| redirect | enviar un 302 al cliente |
| permanent | enviar un 301 al cliente |
| (ninguno) | continuar con el siguiente rewrite; a nivel server el resultado se compara después con los locations |
try_files
Cada argumento se comprueba como archivo (o directorio, con barra final) relativo a root/alias; se sirve el primero que existe. El último argumento es la alternativa y no se comprueba: es una redirección interna a un URI (que pasa otra vez por la coincidencia de location), un location con nombre @name o un código de estado del estilo =404. El probador no puede ver tu sistema de archivos, así que lista las rutas que se comprobarían.
Herencia de add_header
add_header se hereda del nivel server solo cuando el location no tiene ningún add_header propio. Un solo add_header Cache-Control en un location elimina silenciosamente las cabeceras de seguridad fijadas a nivel server. La traza lo señala.
Preguntas
¿Admite toda la sintaxis de configuración de nginx?
El analizador maneja la sintaxis real: bloques anidados, comentarios, cadenas entrecomilladas, argumentos regex; las directivas include se listan pero no se siguen (pega también el archivo incluido). Las variables distintas de $uri, $request_uri, $args y las capturas regex se dejan como texto, y los bloques «if» se muestran pero no se evalúan.
¿Por qué mi regex se comporta distinto en nginx?
nginx usa PCRE; esta página usa expresiones regulares de JavaScript. Coinciden en casi todo lo que se usa en bloques location, pero los cuantificadores posesivos, la recursión y algunas formas de lookbehind difieren. La traza indica cuándo una regex no pudo compilarse.
¿Puede probar qué bloque server responde para un Host?
Sí. Pega varios bloques server y rellena el campo Host. La selección sigue a nginx: nombre exacto, comodín más largo que empieza por *, comodín más largo que termina por *, primera regex que coincide, luego default_server, luego el primer server de ese puerto.
¿Cómo lo pruebo en el servidor real?
nginx -T imprime la configuración completa fusionada (todos los include resueltos), que puedes pegar aquí. Para una comprobación en vivo, curl -sI -H "Host: example.com" http://127.0.0.1/ruta y lee la respuesta; añade temporalmente add_header X-Debug-Location "$uri" si necesitas ver qué bloque respondió.