Como eu descubro qual location o nginx selecionou?
Cole a configuração e a URI da requisição neste testador para ver o bloco vencedor e por que cada um dos outros foi eliminado. Num servidor em execução, adicione error_log /var/log/nginx/debug.log debug; e procure a linha "using configuration", que nomeia o location selecionado. As duas abordagens respondem perguntas diferentes: o log conta o que um servidor ativo fez, e esta página conta o que uma configuração que você ainda não implantou faria.
Por que meu regex de location no nginx não funciona?
Normalmente por um de três motivos, e a tabela de decisão diz qual. Um regex anterior já casou, então o seu nunca rodou — os regex são testados na ordem do arquivo e o primeiro que casar vence. Ou o prefixo mais longo que casou carrega ^~, que pula a fase de regex por completo. Ou o regex está certo mas a URI não é o que você pensa: a correspondência roda contra o caminho normalizado, depois da decodificação de percentuais e da resolução de .., e com a query string removida.
Por que meu casamento exato não dispara?
Um location = exige que a URI inteira seja igual, não que ela comece com o padrão. location = /a/ não casa com /a, e location = /a não casa com /a/b. Barras finais são caracteres comuns aqui, então as duas formas são strings diferentes. Quando um location exato casa, a busca para na hora e nada mais chega a ser comparado.
O nginx compara a query string num bloco location?
Não. A query string é separada durante a normalização e a seleção de location roda só contra o caminho. É por isso que location = /a casa com uma requisição para /a?x=/b. Se você precisa ramificar por um parâmetro, tem que ler $arg_name ou $args dentro do bloco. Uma sutileza que vale conhecer: %3F decodifica para uma interrogação literal que permanece no caminho, então /a%3Fx=1 tem query string vazia e um caminho contendo ?.
Posso usar sintaxe de regex do JavaScript num location do nginx?
Não — o nginx usa PCRE, e as diferenças importam. Esta página roda no seu navegador, onde só existem expressões regulares ECMAScript, então construções exclusivas do PCRE são detectadas e sinalizadas em vez de avaliadas errado em silêncio: grupos atômicos, quantificadores possessivos, modificadores inline como (?i), classes POSIX como [[:alpha:]] e escapes como \A e \K, que o JavaScript lê discretamente como letras comuns. Quando um location é sinalizado, os candidatos restantes continuam sendo avaliados na ordem do nginx, mas o veredito daquele bloco precisa ser conferido num servidor real. Se você está escrevendo o próprio padrão, o testador de regex cobre a sintaxe ECMAScript a fundo. Os casamentos de prefixo de location no nginx diferenciam maiúsculas de minúsculas?
No Linux, sim — location /Static/ não casa com /static/x. Em sistemas de arquivos que não diferenciam maiúsculas, como macOS e Cygwin, o nginx compara prefixos sem diferenciar e ainda força todo location de regex a se comportar como ~*. Esta página modela o comportamento do Linux, que é o que servidores de produção quase sempre rodam. Se você desenvolve no Mac e implanta no Linux, essa diferença pode esconder uma regra quebrada até ela subir.
O try_files muda qual bloco location foi selecionado?
Não. A seleção de location termina primeiro; o try_files roda depois, dentro do bloco que já venceu. Se uma requisição nunca chega ao bloco que contém o seu try_files, a diretiva é irrelevante — a causa habitual é um regex ~ \.php$ pegando a requisição antes que o bloco de prefixo com o fallback tenha chance de agir. Um redirecionamento interno emitido depois reinicia a correspondência, então uma URI reescrita é resolvida contra a lista de locations de novo, do começo.
Por que o nginx retorna 301 quando peço um diretório sem barra?
Dois mecanismos diferentes produzem isso. Se um location cujo nome termina em / carrega proxy_pass ou outra diretiva *_pass, uma requisição para o mesmo caminho sem a barra é respondida com 301 durante a seleção de location — antes de qualquer regex ser avaliado. Em separado, o módulo de arquivos estáticos emite um 301 quando o caminho resolve para um diretório real em disco. O primeiro é visível aqui; o segundo depende do seu sistema de arquivos. Adicionar location = /path suprime o primeiro.
Blocos location aninhados mudam o resultado?
Mudam, e de um jeito fácil de deixar passar. O nginx desce para dentro do location de prefixo vencedor e pesquisa os filhos dele, então um regex aninhado é testado antes dos regex do nível pai. Um ^~ no bloco externo não o protege dos regex aninhados dentro dele mesmo, e o aninhamento pode tornar inalcançável um prefixo globalmente mais longo quando um irmão do nível externo vence antes. Blocos aninhados são modelados aqui com a mesma indentação com que você os escreveu.
Minha configuração do nginx é enviada para algum lugar?
Não. O parsing e a correspondência acontecem localmente no seu navegador, com operações simples de string — não há chamada a servidor e nada é retido. Isso importa mais aqui do que na maioria das ferramentas, porque um bloco server real contém hostnames de upstream, portas internas, caminhos de certificado e regras de autenticação. Você não precisa acreditar na nossa palavra: abra as ferramentas de desenvolvedor do navegador e veja o painel Network permanecer em silêncio enquanto você digita, ou desconecte-se da rede e continue testando. A ausência de qualquer requisição externa também é garantida por um teste de contrato automatizado a cada build, então não dá para regredir sem alarde.