nginx でリライトルールを書くには return
または rewrite
を使う。
rewrite を使った時の フラグ last
と break
の違いがわかりにくかったので、簡単にメモ。
return を使ったリライト
syntax
- return code [ text ] (ex.
return 403
やreturn 404 "not found"
) - return code URL (ex.
return 301 http://www.example.org$request_uri;
) - return URL (ex.
return http://www.example.org$request_uri;
)code は 302
rewrite を使ったリライト
Apache の mod_rewrite に近い。
syntax
rewrite regex replacement [ flag ]
オプションの flag には以下の 4 つの中から指定可能
- last – completes processing of current rewrite directives and restarts the process (including rewriting) with a search for a match on the URI from all available locations.
- break – completes processing of current rewrite directives and non-rewrite processing continues within the current location block only.
- redirect – returns temporary redirect with code 302; it is used if the substituting line begins with http:// (デフォルト)
- permanent – returns permanent redirect with code 301
ex. rewrite ^ http://example.com/new-address.html? permanent;
最後2つの redirect
と permanent
はいいとして last
と break
の違いがわかりにくかったので、シンプルなリライトルールを書いて違いを確認してみた。
breakとlastの違いを確認
環境
OS は Cent6
nginx は 1.4.4 を利用
検証用設定
/etc/nginx/conf.d/default.conf
の localhsot server の設定に location ルールを追加
root /usr/share/nginx/html; rewrite_log on; location /rewrite { rewrite ^/rewrite /foo; rewrite ^/foo /bar; add_header H-rewrite dummy; } location /last { rewrite ^/last /foo last; rewrite ^/foo /bar last; add_header H-last dummy; } location /break { rewrite ^/break /foo break; rewrite ^/foo /bar break; add_header H-break dummy; } location /foo { add_header H-foo dummy; } location /bar { add_header H-bar dummy; } location / { index index.html index.htm; add_header H-index dummy; }
また、リダイレクト先のページも用意
# echo foo > /usr/share/nginx/html/foo # echo bar > /usr/share/nginx/html/bar
ログ設定
rewrite 処理がログ出力されるようにする
/etc/nginx/conf.d/default.conf
の server ディレククティブで rewrite_log on;
にする。
次に /etc/nginx/nginx.conf
でログ出力レベルを notice
にする
error_log /var/log/nginx/error.log notice;
デフォルトの rewrite
レスポンスヘッダー
$ curl -D - http://localhost/rewrite HTTP/1.1 200 OK Server: nginx/1.4.4 Date: Sun, 16 Feb 2014 06:05:42 GMT Content-Type: application/octet-stream Content-Length: 4 Last-Modified: Sat, 15 Feb 2014 15:12:05 GMT Connection: keep-alive ETag: "52ff83c5-4" H-bar: dummy Accept-Ranges: bytes bar
nginx log
2014/02/16 15:05:42 [notice] 21738#0: *4 "^/rewrite" matches "/rewrite", client: 127.0.0.1, server: localhost, request: "GET /rewrite HTTP/1.1", host: "localhost" 2014/02/16 15:05:42 [notice] 21738#0: *4 rewritten data: "/foo", args: "", client: 127.0.0.1, server: localhost, request: "GET /rewrite HTTP/1.1", host: "localhost" 2014/02/16 15:05:42 [notice] 21738#0: *4 "^/foo" matches "/foo", client: 127.0.0.1, server: localhost, request: "GET /rewrite HTTP/1.1", host: "localhost" 2014/02/16 15:05:42 [notice] 21738#0: *4 rewritten data: "/bar", args: "", client: 127.0.0.1, server: localhost, request: "GET /rewrite HTTP/1.1", host: "localhost"
/rewrite
の location では rewrite を2回定義している
まず /rewrite を /foo にリライトし、2回目のリライトルールで /foo を /bar にリライトする
add_header
は /bar location のもの(H-bar: dummy
)が有効になっている
結果的に /bar にリクエストするのと同じレスポンスが返ってくる。
break rewrite
レスポンスヘッダー
$ curl -D - http://localhost/break HTTP/1.1 200 OK Server: nginx/1.4.4 Date: Sun, 16 Feb 2014 06:06:14 GMT Content-Type: application/octet-stream Content-Length: 4 Last-Modified: Sat, 15 Feb 2014 15:12:01 GMT Connection: keep-alive ETag: "52ff83c1-4" H-break: dummy Accept-Ranges: bytes foo
nginx log
2014/02/16 15:06:14 [notice] 21738#0: *5 "^/break" matches "/break", client: 127.0.0.1, server: localhost, request: "GET /break HTTP/1.1", host: "localhost" 2014/02/16 15:06:14 [notice] 21738#0: *5 rewritten data: "/foo", args: "", client: 127.0.0.1, server: localhost, request: "GET /break HTTP/1.1", host: "localhost"
/break の location では rewrite を2回定義している。
まず /break を /foo にリライトする。
ここで break のおかげで、2回目の /foo から /bar へのリライトルールは適用されない。(break より後ろにある rewrite ルールは適用されない)
/break
location ブロックで rewrite より後ろにある add_header
は処理され、レスポンスヘッダーに "H-break: dummy"
が付く。(break より後ろにある rewrite 以外のルールは適用される)
rewrite 先の /foo location の add_header
は処理されていない。
last rewrite
/last の location では rewrite を2回定義している
/break location との違いは rewrite ルールのフラグが break ではなく last であること。
レスポンスヘッダー
$ curl -D - http://localhost/last HTTP/1.1 200 OK Server: nginx/1.4.4 Date: Sun, 16 Feb 2014 06:06:38 GMT Content-Type: application/octet-stream Content-Length: 4 Last-Modified: Sat, 15 Feb 2014 15:12:01 GMT Connection: keep-alive ETag: "52ff83c1-4" H-foo: dummy Accept-Ranges: bytes foo
nginx log
2014/02/16 15:06:38 [notice] 21738#0: *6 "^/last" matches "/last", client: 127.0.0.1, server: localhost, request: "GET /last HTTP/1.1", host: "localhost" 2014/02/16 15:06:38 [notice] 21738#0: *6 rewritten data: "/foo", args: "", client: 127.0.0.1, server: localhost, request: "GET /last HTTP/1.1", host: "localhost"
/break と同じく、2回目の /foo から /bar へのリライトルールは適用されない。(last より後ろにある rewrite ルールは適用されない)
また、/break と異なり、/last location ブロックで last より後ろにある add_header も処理されない。
代わりに、リライト先の /foo location の add_header(H-foo: dummy
)が処理されているる。(last の rewrite に出くわすと、今いる location を抜けて rewrite 先の location に処理が移る)
References
- nginx : Module ngx_http_rewrite_module
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html - nginx : Converting rewrite rules
http://nginx.org/en/docs/http/converting_rewrite_rules.html - server fault : nginx url rewriting: difference between break and last
http://serverfault.com/questions/131474/nginx-url-rewriting-difference-between-break-and-last - Mastering nginx(packt pub.) : Appendix B: Rewrite Rule Guide