reescritura de URL nginx: diferencia entre break y last

45

No entiendo la diferencia entre break y last (banderas de reescritura). La documentación es bastante abstrusa. Intenté cambiar entre los dos en algunas de mis configuraciones, pero no pude detectar ninguna diferencia en el comportamiento. ¿Alguien puede explicar estas banderas con más detalle? Preferiblemente con un ejemplo que muestra un comportamiento diferente cuando se voltea una bandera a otra.


fuente
No sé la respuesta, pero actualice wiki.nginx.org cuando reciba su respuesta. Además, la lista de correo nginx en inglés está bastante activa, e Igor (el desarrollador principal) responde cientos de preguntas por mes, así que quizás pregunte allí.
rmalayter
@rmalayter: esta pregunta se hizo en la lista de correo nginx. Igor respondió, pero la respuesta tampoco tenía mucho sentido para mí: pubbs.net/nginx/200908/46047
El enlace pubbs.net está roto ya que el dominio fue tomado. Lo sentimos, no pude encontrar a dónde debería apuntar. ; (
Tino

Respuestas:

40

Puede tener diferentes conjuntos de reglas de reescritura para diferentes ubicaciones. Cuando se reúne el módulo de reescritura last, deja de procesar el conjunto actual y la solicitud reescrita se pasa una vez más para encontrar la ubicación adecuada (y el nuevo conjunto de reglas de reescritura). Si la regla termina con break, la reescritura también se detiene, pero la solicitud reescrita no se pasa a otra ubicación.

Es decir, si hay dos ubicaciones: loc1 y loc2, y hay una regla de reescritura en loc1 que cambia loc1 a loc2 Y termina con last, la solicitud se reescribirá y pasará a la ubicación loc2. Si la regla termina con break, pertenecerá a la ubicación loc1.

minaev
fuente
Quiere decir que si la reescritura tiene el indicador de ruptura, no buscará un bloque de ubicación coincidente, por lo que pertenece a la ubicación loc1.
Martin Fjordvald
Exactamente. Fijo.
minaev
43

OP prefirió un ejemplo. Además, ¡lo que escribió @minaev fue solo una parte de la historia! Así que, aquí vamos...

Ejemplo 1: sin banderas (interrupción o ú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

Explicación:

¡Para rewrite, las banderas son opcionales!

Ejemplo 2: bloque de ubicación exterior (descanso o ú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

Explicación:

Fuera del bloque de ubicación, ambos breaky se lastcomportan de la manera exacta ...

  • no más análisis de las condiciones de reescritura
  • El motor interno de Nginx pasa a la siguiente fase (búsqueda de locationcoincidencias)

Ejemplo 3: Bloque de ubicación interior - "descanso"

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 /

Explicación:

Dentro de un bloque de ubicación, la breakbandera haría lo siguiente ...

  • no más análisis de las condiciones de reescritura
  • El motor interno de Nginx continúa analizando el locationbloque actual

Ejemplo 4: Bloque de ubicación interior - "último"

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

Explicación:

Dentro de un bloque de ubicación, la lastbandera haría lo siguiente ...

  • no más análisis de las condiciones de reescritura
  • El motor interno de Nginx comienza a buscar otra coincidencia de ubicación en función del resultado del rewriteresultado.
  • ¡No más análisis de las condiciones de reescritura, incluso en la próxima coincidencia de ubicación!

Resumen:

  • Cuando una rewritecondición con la bandera breako lastcoincide, ¡Nginx deja de analizar más rewrites!
  • Fuera de un bloque de ubicación, con breako last, Nginx hace el mismo trabajo (deja de procesar las condiciones de reescritura).
  • Dentro de un bloque de ubicación, con break, Nginx solo deja de procesar las condiciones de reescritura.
  • Dentro de un bloque de ubicación, con last, Nginx deja de procesar las condiciones de reescritura y luego comienza a buscar una nueva coincidencia de locationbloque. ¡Nginx también ignora a cualquiera rewritesen el nuevo locationbloque!

Nota final:

Olvidé incluir algunos casos más extremos (en realidad, un problema común con reescrituras, como 500 internal error). Pero eso estaría fuera del alcance de esta pregunta. ¡Probablemente, el ejemplo 1 también está fuera de alcance!

Pothi Kalimuthu
fuente
ERROR : "nginx.service falló porque el proceso de control salió con código de error" ... directiva desconocida "echo"
Peter Krauss
nginx.com/resources/wiki/modules/echo . Algunas distribuciones de Linux como Ubuntu 14.04 en adelante incluyen este módulo en ciertos paquetes (como en nginx-extras). Espero que eso ayude.
Pothi Kalimuthu
1
En el ejemplo 1, ¿marcaría una diferencia si las reglas de reescritura se colocaran sobre las tres directivas de ubicación?
Craig Hicks
1
@ CraigHicks No, no lo haría. Una regla de reescritura tiene mayor prioridad y se ejecuta al principio antes de que las ubicaciones coincidan.
Pothi Kalimuthu
1
Esta debería ser la mejor respuesta. Es fácil de entender haciendo referencia a estos ejemplos y leyendo la documentación de nginx.
Don Dilanga