這篇是記錄一些 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$ 處理了。