商業,創業,美食,葡萄酒,閱讀,網路科技。
這是我的 FB粉專 以及 IG,我比較常使用 Threads,歡迎大家追蹤互動~
相信稍微有 SEO 和網站概念的讀者,應該都清楚,如果網站網址有改變的話,要用 301 轉址,Google 搜尋上的權重才會整個轉移過去。這也都是舊聞了。
Nginx 除了 return 301 的寫法,另外還有一種 rewrite 的寫法。這篇文章 larry 想聊一聊什麼是 Nginx rewrite,還有跟 return 301 的差別在哪。
什麼是 Nginx rewrite?
首先,什麼是 Nginx rewrite?我們先看 rewrite 的語法:
rewrite 原網址的regex 新網址的url (flag,可不寫);
官方文件
https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
“The rewrite directives are executed sequentially in order of their appearance in the configuration file. It is possible to terminate further processing of the directives using flags. If a replacement string starts with “http://”, “https://”, or “$scheme”, the processing stops and the redirect is returned to a client.”
意思是如果有寫多筆 rewrite 語法,會依照順序都會執行。如果新網址的url,開頭是 "http://"
, "https://"
, "$scheme"
,則會停止執行下去。
另外,最後一個參數 flag 可以有四個選擇
- last: 停止接下來的
ngx_http_rewrite_module
directives (包含rewrite),並直接跳到符合新網址的 location block。 - break: 停止接下來的
ngx_http_rewrite_module
directives (包含rewrite),不重新再找。 - redirect: 新網址開頭不可以是
"http://"
,"https://"
,"$scheme"
,才能用此 flag,並 return 302 轉址。 - permanent: return 301 轉址。
那 rewrite 的效果到底是什麼?例如
rewrite /path1 /path2 last;
這樣 /path1 就會顯示 /path2 的內容,而使用者網址列還是 /path1。
但如果 location /path2 中有 try_files
,例如
rewrite /path1 /path2 last;
location /path2 {
try_files $uri $uri/ /index.php$is_args$args;
}
雖然 last
flag 的意思是直接跳到 location /path2,但 $uri
參數還是 path1。也就是即使跳到 location /path2,仍然會顯示 /path1 的內容。換句話說,上例並未真正產生效果。
那如果
location /path1 {
rewrite /path1 /path2 break;
rewrite /path1 /path2 last;
return 200 'my path1';
add_header Content-Type text/plain;
}
這樣前端 /path1 會 return 自定義的字串 “my path1” 嗎?不會,因為 break
已經跳過第二個 rewrite,而且 return 也是屬於 ngx_http_rewrite_module
directive,也跳過。
config 中如果有 try_files,要特別注意
break
flag 會跳過後面所有 ngx_http_rewrite_module
directives。但注意如果有 try_files
,它不屬於 ngx_http_rewrite_module
,仍然會執行。
例如
location /path1 {
rewrite /path1 /path2 break;
rewrite /path1 /path2 last;
try_files $uri $uri/ /index.php$is_args$args;
}
這樣前端 /path1 是顯示什麼?仍然顯示原 /path1 的內容。的確第二個 rewrite 被跳過了,但碰到 try_files
,仍然執行。
那如果
location /path1 {
rewrite /path1 /path2 last;
try_files $uri $uri/ /index.php$is_args$args;
}
這樣前端 /path1 是顯示什麼?前端 /path1 會顯示 /path2 的內容,因為 last
指令會直接跳到 location /path2。但如果 last
改成 break
,則仍顯示原 /path1 的內容。
以上是 last
與 break
的差異。last
似乎可以說是「跳的更乾脆」,甚至底下有 try_files
都不管。break
則是底下有 try_files
的話,仍會執行。
break
的獨特性,如果是寫在 location block,可以避免 Nginx 無窮轉址。相對的,last
因為會重新找符合新網址的 location block,可能會造成無窮迴圈,使用上要小心。
因為 try_files
本身就有重寫網址的意涵,隨著 try_files
的參數往右一直 fallback。所以 rewrite 與 try_files 都有重寫網址的意涵,也可能衝突,使用上要特別小心。
另外還有兩個 flag: redirect、permanent
redirect / permanent 與 last / break 的基本行為邏輯完全不同。
rewrite /path1 /path2 permanent;
不管是 permanent
或是 redirect
,使用者網址列顯示的都是 /path2。差別只在 permanent 是先發一個 301 給使用者,通知前端轉到新網址。redirect 則是發 302 給使用者,通知前端轉到新網址。
這裡重複提醒一下,新網址開頭不可以是 "http://"
, "https://"
, "$scheme"
,才能用 redirect。
rewrite 與 return 301 的差別在哪
一般 return 301,可能是這樣寫
return 301 新網址;
我們對比一下 permanent rewrite
rewrite 原網址的regex 新網址的url permanent;
如果是簡單網址的轉址,都是 301 轉址的機制,效果應該一樣。但是 rewrite 可以用 regex,新網址也可以用 $1
、$2
組合,變化更多。
換句話說,return 301 是 permanent rewrite 的簡單版。
結論
Nginx rewrite 是很久的東西,但研究起來卻很有內容。走一遍,會很踏實的了解 Nginx config 轉址的機制。
flag last
/ break
的行為很有趣,但要小心會與 try_files
衝到。
last
/ break
通常有一個使用情境是「美化網址」。例如將要顯示的網址填在 path1,圖片、影音等多媒體檔案填在 path2。這樣使用者 request path1,就可以顯示 path2 的檔案,而不用輸入真實路徑和副檔名。
last
/ break
還有一個使用情境是將對外網址,與實際存取的網址分開。例如對外網址是 path1,不要動它,內部實際存取可以是 path2, path3,在 Nginx config 裡面換就好。例如某一條路徑的程式有更新,就切換成 path2 或 path3,不影響客戶端 (他使用的還是 path1)。
permanent
/ redirect
則是相對單純,就是 301, 302 轉址。
商業,創業,美食,葡萄酒,閱讀,網路科技。