web-dev-qa-db-ja.com

nginx url rewrite:breakとlastの違い

Breakとlast(書き換えのフラグ)の違いがわかりません。ドキュメントはかなり厄介です。一部の構成で2つを切り替えようとしましたが、動作の違いを見つけることができませんでした。誰かがこれらのフラグをより詳細に説明できますか?あるフラグを別のフラグにフリップしたときの異なる動作を示す例が望ましい。

49
user39883

場所によって、書き換えルールのセットが異なる場合があります。書き換えモジュールがlastに一致すると、現在のセットの処理が停止し、書き換えられたリクエストがもう一度渡されて、適切な場所(および新しい書き換えルールのセット)が検索されます。ルールがbreakで終了する場合、書き換えも停止しますが、書き換えられたリクエストは別の場所に渡されません。

つまり、loc1とloc2の2つの場所があり、loc1にloc1をloc2に変更し、かつlastで終わる書き換えルールがある場合、リクエストは書き換えられ、場所loc2に渡されます。ルールがbreakで終わる場合、ロケーションloc1に属します。

43
minaev

OPは例を好んだ。また、@ minaevが書いたのは話の一部に過ぎませんでした!さあ、行きましょう...

例1:フラグなし(ブレークまたは最後)

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

結果:

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

説明:

rewriteの場合、フラグはオプションです!

例2:ロケーションブロックの外側(breakまたはlast)

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
}

結果:

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

説明:

ロケーションブロックの外では、breaklastの両方が正確に動作します...

  • 書き換え条件の解析は不要
  • Nginx内部エンジンは次のフェーズに進みます(location一致の検索)

例3:ロケーションブロックの内側-「ブレーク」

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

結果:

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

説明:

ロケーションブロック内では、breakフラグは次のことを行います...

  • 書き換え条件の解析は不要
  • Nginx内部エンジンは現在のlocationブロックを解析し続けます

例4:ロケーションブロックの内側-「最後」

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

結果:

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

説明:

ロケーションブロック内では、lastフラグは次のことを行います...

  • 書き換え条件の解析は不要
  • Nginx内部エンジン検索を開始rewrite結果の結果に基づく別の場所の一致。
  • 次の場所が一致しても、書き換え条件の解析は行われません。

概要:

  • フラグrewriteまたはbreakを持つlast条件が一致すると、Nginxはそれ以上のrewritesの解析を停止します。
  • ロケーションブロックの外で、breakまたはlastを使用すると、Nginxは同じジョブを実行します(書き換え条件の処理を停止します)。
  • ロケーションブロック内でbreakを使用すると、Nginxはもう書き換え条件の処理のみを停止します
  • ロケーションブロック内でlastを使用すると、Nginxはリライト条件の処理を停止し、次に検索を開始locationブロックの新しい一致を求めます! Nginxは、新しいrewritesブロック内のlocationも無視します!

最終メモ:

さらにいくつかのEdgeケース(500 internal errorなどの書き換えに関する実際の一般的な問題)を含めることができませんでした。しかし、それはこの質問の範囲外です。おそらく、例1も対象外です!

48
Pothi Kalimuthu