¿Cómo averiguo qué location seleccionó nginx?
Pega la configuración y la URI de la petición en este probador para ver el bloque ganador y por qué se eliminó cada uno de los demás. En un servidor en marcha, añade error_log /var/log/nginx/debug.log debug; y busca la línea «using configuration», que nombra el location seleccionado. Los dos enfoques responden preguntas distintas: el log cuenta lo que hizo un servidor vivo, y esta página cuenta lo que haría una configuración que aún no has desplegado.
¿Por qué no funciona mi expresión regular de location en nginx?
Normalmente por uno de tres motivos, y la tabla de decisión dice cuál. Una regex anterior ya coincidió, así que la tuya nunca se ejecutó — las regex se prueban en el orden del archivo y gana la primera coincidencia. O el prefijo coincidente más largo lleva ^~, que omite la fase de regex por completo. O la regex está bien pero la URI no es la que crees: la coincidencia se ejecuta contra la ruta normalizada, después de decodificar los porcentajes y resolver los .., y con la query string eliminada.
¿Por qué no se dispara mi coincidencia exacta?
Un location = exige que la URI entera sea igual, no que empiece por el patrón. location = /a/ no coincide con /a, y location = /a no coincide con /a/b. Aquí las barras finales son caracteres corrientes, así que las dos formas son cadenas distintas. Cuando un location exacto coincide, la búsqueda se detiene de inmediato y nada más llega siquiera a compararse.
¿nginx compara la query string en un bloque location?
No. La query string se separa durante la normalización y la selección de location se ejecuta solo contra la ruta. Por eso location = /a coincide con una petición a /a?x=/b. Si necesitas ramificar por un parámetro tienes que leer $arg_name o $args dentro del bloque. Una sutileza que conviene conocer: %3F se decodifica como un signo de interrogación literal que permanece en la ruta, así que /a%3Fx=1 tiene la query string vacía y una ruta que contiene ?.
¿Puedo usar la sintaxis de regex de JavaScript en un location de nginx?
No — nginx usa PCRE, y las diferencias importan. Esta página se ejecuta en tu navegador, donde solo existen las expresiones regulares de ECMAScript, así que las construcciones exclusivas de PCRE se detectan y se marcan en lugar de evaluarse mal en silencio: grupos atómicos, cuantificadores posesivos, modificadores en línea como (?i), clases POSIX como [[:alpha:]] y escapes como \A y \K que JavaScript lee tranquilamente como letras corrientes. Cuando un location queda marcado, los candidatos restantes se siguen evaluando en el orden de nginx, pero el veredicto de ese bloque hay que comprobarlo en un servidor real. Si estás escribiendo el patrón en sí, el probador de expresiones regulares cubre a fondo la sintaxis de ECMAScript. ¿Las coincidencias de prefijo de location en nginx distinguen mayúsculas y minúsculas?
En Linux, sí — location /Static/ no coincide con /static/x. En sistemas de archivos que no distinguen mayúsculas, como macOS y Cygwin, nginx compara los prefijos sin distinguirlas y además fuerza a que todo location de regex se comporte como ~*. Esta página modela el comportamiento de Linux, que es lo que los servidores de producción ejecutan casi siempre. Si desarrollas en Mac y despliegas en Linux, esa diferencia puede ocultar una regla rota hasta que llega a producción.
¿try_files cambia qué bloque location se seleccionó?
No. La selección de location termina primero; try_files se ejecuta después, dentro del bloque que ya ganó. Si una petición nunca llega al bloque que contiene tu try_files, la directiva es irrelevante — la causa habitual es una regex ~ \.php$ que se lleva la petición antes de que el bloque de prefijo con el fallback pueda actuar. Una redirección interna emitida más tarde sí reinicia la coincidencia, así que una URI reescrita se resuelve otra vez contra la lista de location desde el principio.
¿Por qué nginx devuelve 301 cuando pido un directorio sin barra?
Lo producen dos mecanismos distintos. Si un location cuyo nombre termina en / lleva proxy_pass u otra directiva *_pass, una petición a la misma ruta sin la barra se responde con un 301 durante la selección de location — antes de evaluar ninguna regex. Aparte de eso, el módulo de archivos estáticos emite un 301 cuando la ruta se resuelve en un directorio real en disco. El primero se ve aquí; el segundo depende de tu sistema de archivos. Añadir location = /path suprime el primero.
¿Los bloques location anidados cambian el resultado?
Sí, y de una manera fácil de pasar por alto. nginx desciende dentro del location de prefijo ganador y busca entre sus hijos, así que una regex anidada se prueba antes que las regex del nivel padre. Un ^~ en el bloque exterior no lo protege de sus propias regex anidadas, y el anidamiento puede volver inalcanzable un prefijo globalmente más largo cuando un hermano del nivel exterior gana primero. Aquí los bloques anidados se modelan con la misma indentación con la que los escribiste.
¿Se sube mi configuración de nginx a alguna parte?
No. El análisis y la coincidencia ocurren localmente en tu navegador con simples operaciones sobre cadenas — no hay ninguna llamada a servidor y no se conserva nada. Aquí importa más que en la mayoría de las herramientas, porque un bloque server real contiene nombres de host de upstream, puertos internos, rutas de certificados y reglas de autenticación. No tienes que creernos: abre las herramientas de desarrollo del navegador y observa cómo el panel Red se mantiene en silencio mientras escribes, o desconéctate del todo y sigue probando. La ausencia de cualquier petición externa también la impone una prueba de contrato automatizada en cada build, así que no puede degradarse sin que nadie se entere.