這篇是記錄一些 lighttpd 轉 nginx rewrite rule 的實作與一些注意事項,最後會講一些 squid 轉 nginx 的技巧。
這裡先講一些跟 nginx rewrite 有關的重點。
首先 nginx 算是分成 location 跟 rewrite,lighttpd 是有 url.rewrite、url.rewrite-repeat 跟 url.redirect,其中 lighttpd 的 url.rewrite 就是 rewrite once 而 url.rewrite-repeat 則是重複一直 rewrite 的意思,這個則對應到 nginx rewrite 後面接的參數,也就是 break 跟 last,break 就是 rewrite 到此為止不要再跑 rewrite 了,但是 last 就會在重頭跑 rewrite 一次,而且 last 也是 rewrite 這個 directive 的預設值,所以如果你的 rewrite 不小心變成 loop (nginx 預設是 rewrite 10 次後就噴 500)請加上 break。至於 lighttpd 的 url.redirect 其實在 nginx 也是透過 rewrite 完成的,主要是加 redirect 跟 permanent 的參數,分別是回 302 跟 301。rewrite 的用法大約如下:
1 | rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last; |
注意的是 rewrite 可以擺在 server location if 這三種 block 裡。
在完成了 rewrite 這個階段之後,也就是不管是被 break 或是 last 後重跑了一輪沒比對到,之後會開始比對所謂的 location,location 是用來處理 url 地址(被 rewrite 後)真正的地方,大概會長的像下面這樣。
1 | location = / { |
要注意的是 location 有比對的順序,依序是先從有 = 的,然後是 ^~,再來就是依照順序,而 location / 則可以當成一個預設值,因為他會 match 到剩下的所有 url。location 可以放在 server block 裡。
粗略的介紹完,接下來進入一些實務的介紹:
- lighttpd 原本的
url.redirect就對應成 nginx 的rewrite http://foo.bar/ redirect - 如果原本的 lighttpd 後端因為是 zend 所以就會有一些 rewrite (像是特定的 static file) 是不能送到 zend 去做的,在 lighttpd 就會在
url.rewrite-once看到一些"^/images/.*$" => "$0"這種的寫法,但是 nginx 沒有 $0 這種東西,這時候就直接把 $0 轉成 $uri 即可,也就是rewrite ^/images/ $uri last - 承上面那點,如果 nginx 背後的 php 是跑 zend 這類有 single entry point (什麼都交給 index.php 做 route)的架構,那樣設定會如下
1 | location ~ \.php$ { |
- 因為 lighttpd 的 rewrite 可以連 arguments (也就是 ? 後面的那串參數)都一起 rewrite,但是 nginx 不行,所以就變成需要在 location 裡面做(也就是先 rewrite 完 uri),因此會變成類似這樣
1 | location ^~ /abc { |
像這個例子就會把 /abc?post 變成 /dispatch?type=post 然後丟給 dispatch 這個 location (假設存在 location = /dispatch 之類的)
- 前面提到的 location 有比較順序,要注意的是只有兩種是可以接正規表示式的也就是
~跟~*,~是有大小寫區分的,~*則不分大小寫,然後=跟^~後面都是接一般的表示法,也就是下面這種都是不合法的
1 | # misusing |
但是下列的就是合法的
1 | # right |
- 另外就是關於
last跟break的詳細用法,rewrite預設是last,兩個最基本的差異前面有提到break會停止任何rewrite進入找location的階段,但是last會從第一個rewrite重新 rewrite 階段,但是這裡其實隱含了一個潛規則,就是如果你的rewrite是在location裡面的話,搭配last就會回到server這個 scope 的rewrite重新跑一次,但是搭配break就只會在這個location裡面找location,這是值得注意的規則,所以有時候建議把 location ~ .php$ {…} 擺在第一個,因為有時候location內的rewrite又會不小心掉回來這個location,把 ~ .php$ 擺最前面時,這樣rewrite ... last回到 server scope 遇到 php 就會給 ~ .php$ 處理了。