nginx url rewriting: différence entre pause et dernière

45

Je ne comprends pas la différence entre break et last (drapeaux de réécriture). La documentation est plutôt abstruse. J'ai essayé de basculer entre les deux dans certaines de mes configurations, mais je ne remarquais aucune différence de comportement. Quelqu'un peut-il s'il vous plaît expliquer ces drapeaux plus en détail? De préférence, avec un exemple qui présente un comportement différent lors du basculement d’un drapeau à un autre.


la source
Je ne connais pas la réponse, mais veuillez mettre à jour le fichier wiki.nginx.org lorsque vous aurez la réponse. De plus, la liste de diffusion en langue anglaise nginx est très active et Igor (le développeur principal) répond à des centaines de questions par mois, alors posez-le.
rmalayter
@rmalayter - cette question a été posée sur la liste de diffusion de nginx. Igor y a répondu, mais la réponse n'a pas non plus beaucoup de sens pour moi: pubbs.net/nginx/200908/46047
Le lien pubbs.net est rompu lors de la reprise du domaine. Désolé, n'a pas été en mesure de trouver où il devrait pointer. ; (
Tino

Réponses:

40

Vous pouvez avoir différents ensembles de règles de réécriture pour différents emplacements. Lorsque le module de réécriture se réunit last, il arrête le traitement de l'ensemble actuel et la demande de réécriture est transmise à nouveau pour rechercher l'emplacement approprié (et le nouvel ensemble de règles de réécriture). Si la règle se termine par break, la réécriture s’arrête également, mais la demande de réécriture n’est pas transmise à un autre emplacement.

Autrement dit, s'il y a deux emplacements: loc1 et loc2, et qu'il existe une règle de réécriture dans loc1 qui modifie loc1 en loc2 ET se termine par last, la demande sera réécrite et transmise à l'emplacement loc2. Si la règle se termine par break, elle appartiendra à l'emplacement loc1.

minaev
la source
Vous voulez dire que si la réécriture a le drapeau break, elle ne cherchera pas un bloc d’emplacement correspondant, ce qui le fera appartenir à l’emplacement loc1.
Martin Fjordvald
Exactement. Fixé.
minaev
43

OP a préféré un exemple. En outre, ce que @minaev a écrit n'était qu'une partie de l'histoire! Alors on y va ...

Exemple 1: aucun drapeau (pause ou dernier)

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;
}

Résultat:

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

Explication:

Pour rewrite, les drapeaux sont optionnels!

Exemple 2: bloc d'emplacement extérieur (pause ou dernier)

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
}

Résultat:

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

Explication:

En dehors du bloc d'emplacement, les deux breaket lastse comportent de la manière exacte ...

  • plus d'analyse des conditions de réécriture
  • Le moteur interne de Nginx passe à la phase suivante (recherche d'une locationcorrespondance)

Exemple 3: Bloc de localisation interne - "pause"

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';
    }
}

Résultat:

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

Explication:

Dans un bloc d'emplacement, breakflag ferait ce qui suit ...

  • plus d'analyse des conditions de réécriture
  • Le moteur interne de Nginx continue d'analyser le locationbloc actuel

Exemple 4: bloc de lieu intérieur - "dernier"

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';
    }
}

Résultat:

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

Explication:

Dans un bloc d'emplacement, lastflag ferait ce qui suit ...

  • plus d'analyse des conditions de réécriture
  • Le moteur interne de Nginx commence à rechercher une autre correspondance d'emplacement en fonction du résultat du rewriterésultat.
  • plus d'analyse des conditions de réécriture, même lors du prochain match de localisation!

Sommaire:

  • Lorsqu'une rewritecondition avec le drapeau breakou lastcorrespond, Nginx cesse d'analyser plus rewrites!
  • En dehors d'un bloc d'emplacement, avec breakou last, Nginx effectue le même travail (cesse de traiter les conditions de réécriture).
  • Dans un bloc d'emplacement, avec break, Nginx n'interrompt que le traitement des conditions de réécriture
  • Dans un bloc d’emplacement, avec last, Nginx arrête de traiter les conditions de réécriture et commence ensuite à rechercher une nouvelle correspondance de locationbloc! Nginx en ignore également tous les éléments rewritesdans le nouveau locationbloc!

Note finale:

J'ai manqué d'inclure quelques cas supplémentaires (problème courant avec les réécritures, tel que 500 internal error). Mais ce serait hors de portée de cette question. Probablement, l'exemple 1 est également hors de propos!

Pothi Kalimuthu
la source
ERREUR : "nginx.service a échoué car le processus de contrôle s'est terminé avec un code d'erreur." ... directive inconnue "echo"
Peter Krauss
nginx.com/resources/wiki/modules/echo . Certaines distributions Linux telles que Ubuntu 14.04 et suivantes regroupent ce module dans certains packages (tels que nginx-extras). J'espère que ça aide.
Pothi Kalimuthu
1
Dans l'exemple 1, cela ferait-il une différence si les règles de réécriture étaient placées au-dessus des trois directives d'emplacement?
Craig Hicks
1
@CraigHicks Non, ce ne serait pas. Une règle de réécriture a une priorité plus élevée et est exécutée avant que les emplacements ne correspondent.
Pothi Kalimuthu
1
Cela devrait être la meilleure réponse. Il est facile à comprendre en consultant ces exemples et en lisant la documentation de nginx.
Don Dilanga