在nginx中配置,使得訪問不帶www的網(wǎng)址自動重定向到帶www的域名秤朗。
http協(xié)議的重定向
在nginx官方文檔中有如下示例代碼:
server {
listen 80;
server_name example.com;
return 301 http://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
...
}
對于return
字段煤蹭,有兩點需要特別注意:
- 必須帶上協(xié)議頭,即
http://
- 必須帶上
$request_uri
參數(shù)
踩坑:return
字段必須帶上協(xié)議頭
經(jīng)踩坑取视,不帶上協(xié)議頭硝皂,訪問example.com
會重定向到example.com/www.example.com/www.example.com/www.example.com/www.example.com...
(url的長度達到8k+),最終出現(xiàn)414 Request-URI Too Large
錯誤贫途。
我在進行測試時發(fā)現(xiàn)chrome會自動緩存301跳轉(zhuǎn)吧彪,因此就算還原了nginx的配置文件,訪問example.com
仍然會重定向到剛才的超長網(wǎng)址上丢早,一直都是414錯誤姨裸。有兩種方法可以解決301緩存的問題:
- 在瀏覽器的設(shè)置中清除緩存數(shù)據(jù)
- 使用隱私窗口進行測試(正確的打開方式?)
踩坑:必須帶上$request_uri
參數(shù)
full original request URI (with arguments)
nginx文檔中對該變量的描述比較簡單,通過搜索可以找到歷史版本的說明怨酝,(stackoverflow,博客園,新浪博客):
This variable is equal to the original request URI as received from the client including the args. It cannot be modified. Look at $uri for the post-rewrite/altered URI. Does not include host name. Example: "/foo/bar.php?arg=baz"
通過這個詳細的描述傀缩,可以了解$request_uri
參數(shù)表示從客戶端發(fā)送來的原生請求URI,包括參數(shù)农猬。
經(jīng)踩坑赡艰,不帶上$request_uri
參數(shù),訪問example.com/abcd?123
會重定向到www.example.com
斤葱,即無論訪問任何子路徑慷垮,都會自動重定向到首頁揖闸。
https協(xié)議的重定向
參考http協(xié)議的重定向,我們添加了如下的配置:
server {
listen 443 ssl;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
...
}
重新加載nginx配置后料身,我們發(fā)現(xiàn) https://example.com 無法訪問汤纸,通過curl測試,返回下述錯誤信息:curl: (35) Server aborted the SSL handshake
芹血,很明顯是ssl方面的問題贮泞。
而在配置前,https://example.com 和 https://www.example.com 都是可以正常訪問的幔烛,原始配置如下:
server {
listen 443 ssl;
server_name www.example.com;
server_name example.com;
ssl_certificate ssl/www.example.com.crt;
ssl_certificate_key ssl/www.example.com.key;
...
}
因此啃擦,我嘗試在重定向的配置中也添加ssl_certificate的配置信息:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate ssl/www.example.com.crt;
ssl_certificate_key ssl/www.example.com.key;
return 301 https://www.example.com$request_uri;
}
再次加載nginx配置后,發(fā)現(xiàn) https://example.com 正常訪問饿悬,并且可以自動重定向到 https://www.example.com 令蛉。
301還是302
- 301: 永久性轉(zhuǎn)移(Permanently Moved)
- 302: 暫時性轉(zhuǎn)移(Temporarily Moved)
共同點:二者都表示重定向,瀏覽器在獲取服務(wù)器的返回碼后會自動根據(jù)頭部的Location值跳轉(zhuǎn)到新的URL地址乡恕;
不同點:301表示舊地址被永久地移除了言询,已經(jīng)不可訪問;302表示舊地址還在傲宜,只是臨時進行跳轉(zhuǎn),后續(xù)還是訪問舊地址夫啊。
問題來了:什么情況下用301跳轉(zhuǎn)函卒?什么情況下用302跳轉(zhuǎn)?
實際案例1撇眯,知乎:
- http://www.zhihu.com 跳轉(zhuǎn)到 https://www.zhihu.com 用的是301跳轉(zhuǎn)
- /za-js-sdk@latest/dist/zap.js 跳轉(zhuǎn)到 /za-js-sdk@2.4.5/dist/zap.js 用的是302跳轉(zhuǎn)
實際案例2报嵌,小米:
- http://mi.com/ 跳轉(zhuǎn)到 http://www.mi.com/ 用的是301跳轉(zhuǎn)
- http://www.mi.com/ 跳轉(zhuǎn)到 https://www.mi.com/ 用的是302跳轉(zhuǎn)
實際案例3,百度:
- http://tieba.baidu.com/ 跳轉(zhuǎn)到 https://tieba.baidu.com/index.html 用的是301跳轉(zhuǎn)
- http://baidu.com/ 跳轉(zhuǎn)到 https://www.baidu.com/ 用的是302跳轉(zhuǎn)
個人感覺熊榛,知乎的使用比較有代表性锚国,從http到https做301永久跳轉(zhuǎn),表示知乎采用的是https的方式訪問玄坦,不會在回退到http的方式血筑;而在獲取zap.js的時候,使用了302臨時跳轉(zhuǎn)煎楣,跳轉(zhuǎn)到當前的版本豺总,后續(xù)zap.js有更新的時候,也會302跳轉(zhuǎn)到更新后的地址择懂。
注:文章中使用到的域名 example.com 為示例代碼喻喳,請根據(jù)項目需要自行修改。