reescrita de URL do nginx: diferença entre pausa e última

45

Não entendo a diferença entre break e last (sinalizadores de reescrita). A documentação é bastante obscura. Eu tentei alternar entre os dois em algumas das minhas configurações, mas não consegui detectar nenhuma diferença no comportamento. Alguém pode explicar essas bandeiras com mais detalhes? De preferência com um exemplo que mostra um comportamento diferente ao virar um sinalizador para outro.


fonte
Não sei a resposta, mas atualize o wiki.nginx.org quando receber sua resposta. Além disso, a lista de discussão nginx no idioma inglês é bastante ativa e Igor (o desenvolvedor principal) responde centenas de perguntas por mês, então talvez pergunte lá.
precisa saber é o seguinte
@ rmalayter - essa pergunta foi feita na lista de discussão nginx. Igor respondeu ele, mas a resposta não faz muito sentido para mim também: pubbs.net/nginx/200908/46047
O link pubbs.net está quebrado à medida que o domínio foi assumido. Desculpe, não foi possível encontrar para onde apontar. ; (
Tino

Respostas:

40

Você pode ter diferentes conjuntos de regras de reescrita para diferentes locais. Quando o módulo de reescrita se encontra last, ele para de processar o conjunto atual e a solicitação reescrita é passada novamente para encontrar o local apropriado (e o novo conjunto de regras de reescrita). Se a regra terminar break, a reescrita também será interrompida, mas a solicitação reescrita não será passada para outro local.

Ou seja, se houver dois locais: loc1 e loc2, e houver uma regra de reescrita em loc1 que altere loc1 para loc2 AND termina com last, a solicitação será reescrita e transmitida para o local loc2. Se a regra terminar com break, ela pertencerá ao local loc1.

minaev
fonte
Você quer dizer que, se a reescrita tiver o sinalizador de interrupção, não procurará um bloco de local correspondente, fazendo com que ele pertença ao local loc1.
Martin Fjordvald 15/04
Exatamente. Fixo.
Minaev 15/04
43

O OP preferiu um exemplo. Além disso, o que @minaev escreveu, era apenas uma parte da história! Aqui vamos nos...

Exemplo 1: Nenhum sinalizador (interrupção ou último)

server {
    server_name example.com;
    root 'path/to/somewhere';

    location / {
        echo 'finally matched location /';
    }

    location /notes {
        echo 'finally matched location /notes';
    }

    location /documents {
        echo 'finally matched location /documents';
    }

    rewrite ^/([^/]+.txt)$ /notes/$1;
    rewrite ^/notes/([^/]+.txt)$ /documents/$1;
}

Resultado:

# curl example.com/test.txt
finally matched location /documents

Explicação:

Pois rewrite, as bandeiras são opcionais!

Exemplo 2: Bloco de localização externo (pausa ou último)

server {
    server_name example.com;
    root 'path/to/somewhere';

    location / {
        echo 'finally matched location /';
    }

    location /notes {
        echo 'finally matched location /notes';
    }

    location /documents {
        echo 'finally matched location /documents';
    }

    rewrite ^/([^/]+.txt)$ /notes/$1 break; # or last
    rewrite ^/notes/([^/]+.txt)$ /documents/$1; # this is not parsed
}

Resultado:

# curl example.com/test.txt
finally matched location /notes

Explicação:

Fora do bloco de localização, ambos breake lastse comportam da maneira exata ...

  • não é mais necessário analisar as condições de reescrita
  • O mecanismo interno do Nginx passa para a próxima fase (procurando por locationcorrespondência)

Exemplo 3: Bloco de localização interno - "pausa"

server {
    server_name example.com;
    root 'path/to/somewhere';

    location / {
        echo 'finally matched location /';
        rewrite ^/([^/]+.txt)$ /notes/$1 break;
        rewrite ^/notes/([^/]+.txt)$ /documents/$1; # this is not parsed
    }

    location /notes {
        echo 'finally matched location /notes';
    }

    location /documents {
        echo 'finally matched location /documents';
    }
}

Resultado:

# curl example.com/test.txt
finally matched location /

Explicação:

Dentro de um bloco de localização, o breaksinalizador faria o seguinte ...

  • não é mais necessário analisar as condições de reescrita
  • O mecanismo interno do Nginx continua analisando o locationbloco atual

Exemplo 4: Bloco de localização interno - "last"

server {
    server_name example.com;
    root 'path/to/somewhere';

    location / {
        echo 'finally matched location /';
        rewrite ^/([^/]+.txt)$ /notes/$1 last;
        rewrite ^/notes/([^/]+.txt)$ /documents/$1;  # this is not parsed
    }

    location /notes {
        echo 'finally matched location /notes';
        rewrite ^/notes/([^/]+.txt)$ /documents/$1;  # this is not parsed, either!
    }

    location /documents {
        echo 'finally matched location /documents';
    }
}

Resultado:

# curl example.com/test.txt
finally matched location /notes

Explicação:

Dentro de um bloco de localização, o lastsinalizador faria o seguinte ...

  • não é mais necessário analisar as condições de reescrita
  • O mecanismo interno do Nginx começa a procurar outra correspondência de local com base no resultado do rewriteresultado.
  • não é mais necessário analisar as condições de reescrita, mesmo na próxima partida de localização!

Resumo:

  • Quando uma rewritecondição com a bandeira breakou lastcorresponde, o Nginx para de analisar mais rewrites!
  • Fora de um bloco de localização, com breakou last, o Nginx faz o mesmo trabalho (para de processar mais as condições de reescrita).
  • Dentro de um bloco de localização, com break, o Nginx só para de processar mais condições de reescrita
  • Dentro de um bloco de localização, com last, o Nginx para de processar mais as condições de reescrita e começa a procurar uma nova correspondência de locationbloco! Nginx também ignora qualquer um rewritesno novo locationbloco!

Nota final:

Eu esqueci de incluir mais alguns casos extremos (problema realmente comum com reescritas, como 500 internal error). Mas isso estaria fora do escopo desta questão. Provavelmente, o exemplo 1 também está fora do escopo!

Pothi Kalimuthu
fonte
ERRO : "nginx.service falhou porque o processo de controle saiu com o código de erro." ... directiva desconhecida "echo"
Peter Krauss
nginx.com/resources/wiki/modules/echo . Algumas distribuições Linux como o Ubuntu 14.04 em diante empacotam este módulo em certos pacotes (como no nginx-extras). Espero que ajude.
Pothi Kalimuthu
1
No exemplo 1, faria diferença se as regras de reescrita fossem colocadas acima das três diretivas de localização?
Craig Hicks
1
@CraigHicks Não, não seria. Uma regra de reescrita tem precedência mais alta e é executada primeiro antes dos locais serem correspondidos.
Pothi Kalimuthu
1
Essa deve ser a melhor resposta. É fácil de entender consultando esses exemplos e lendo a documentação do nginx.
Don Dilanga