nginx重寫和重定向關(guān)系與配置方式
前言
一直對nginx的重寫和重定向都是只有一個模糊的認(rèn)識,只是知道在nginx里return、rewrite、proxy_pass能實現(xiàn)我想要的轉(zhuǎn)發(fā)。
每次查閱資料時,各種關(guān)鍵詞充斥在眼前:“重寫”、“重定向”、“隱式轉(zhuǎn)發(fā)”、“內(nèi)部重定向”......一直沒有區(qū)分清楚他們之前的區(qū)別或聯(lián)系。
隨之產(chǎn)生幾個問題,想要花點時間搞清楚它們:
- 重寫和重定向的區(qū)別是什么?
- nginx中“重寫”、“重定向”、“隱式轉(zhuǎn)發(fā)”、“內(nèi)部重定向”......這些名詞的關(guān)系是什么?在nginx是否都由一個獨立的模塊、關(guān)鍵字來實現(xiàn)這些的?
- nginx中return、rewrite、proxy_pass它們的區(qū)別是什么?對于重寫和重定向,它們是否各自實現(xiàn)不同的功能?
1.重寫和重定向的區(qū)別是什么?
首先說說關(guān)聯(lián)
首先重寫和重定向的最終目的是一樣的。假如你通過瀏覽器和固定的鏈接經(jīng)常訪問一張“好看的圖片”,有一天圖片的維護(hù)者將它移動了位置(服務(wù)器上的目錄、移動到其他域名),那意味著你訪問不到這張圖片了?
為了避免這樣的情況給用戶帶來的困擾,可以使用重寫、或者重定向,將你的請求轉(zhuǎn)向新的位置(這張圖片新的位置),對你來說還是用老的固定的鏈接訪問到了你喜歡的圖片。
那他們的區(qū)別呢?
重定向:重定向是用戶請求服務(wù)端后,服務(wù)端向客戶端發(fā)送HTTP 301、302(303、304、307、308),告訴客戶端需要去嘗試另一個URL。意味著客戶端知道使用另一個URL并去訪問。(客戶端發(fā)起兩次請求)
重定向的請求路徑如下:
- request1(來自客戶端):訪問“好看的圖片”
- response1(來自服務(wù)端):你要訪問的圖片不在這了,你需要去訪問“好看的圖片新的位置”
- request2(來自客戶端):訪問“好看的圖片新的位置”
- response2(來自服務(wù)端):拿去吧,你要的“好看的圖片新的位置”對應(yīng)的圖片
重寫:重寫發(fā)生在服務(wù)器上。服務(wù)器內(nèi)部將一個URL轉(zhuǎn)到另一個URL,然后返回給客戶端。客戶端并不知道自己的請求被轉(zhuǎn)過一次,瀏覽器中的URL也始終是一開始訪問的那個。(客戶端發(fā)起一次請求)
重寫的請求路徑如下:
- request1(來自客戶端):訪問“好看的圖片”
- 重寫(服務(wù)端處理):將“好看的圖片”改到“好看的圖片新的位置”,獲取到圖片
- response1(來自服務(wù)端):拿去吧,你要的“好看的圖片”對應(yīng)的圖片
粗暴總結(jié):
從瀏覽器的反饋來看。重寫-客戶端只會發(fā)送一次請求;重定向-客戶端會發(fā)送兩次請求。
2.“重寫”、“重定向”、“隱式轉(zhuǎn)發(fā)”、“內(nèi)部重定向”......這些名詞的關(guān)系是什么?
重寫和重定向在上面已經(jīng)解釋過了。關(guān)于其他名詞的解釋,在網(wǎng)上搜羅了一下:
- 隱式轉(zhuǎn)發(fā)/隱形轉(zhuǎn)發(fā)/隱藏式跳轉(zhuǎn):將請求跳轉(zhuǎn)到另一個網(wǎng)站的頁面,并且瀏覽器中URL保持不變。
- 顯示轉(zhuǎn)發(fā):將請求跳轉(zhuǎn)到另一個網(wǎng)站的頁面,瀏覽器中URL會發(fā)生改變。
- 內(nèi)部重定向:內(nèi)部重定向(重寫)發(fā)生在server端內(nèi)部,client端不知情,瀏覽器上URL不會改變。
- 外部重定向:外部重定向是server端通知client端需要訪問新的URL,client端進(jìn)行第二次訪問。瀏覽器中URL也變成新的URL。
思來想去,似乎就是對重寫和重定向取了好多名字。所以個人理解的總結(jié):
- 重寫 = 隱式轉(zhuǎn)發(fā) = 內(nèi)部重定向
- 重定向 = 顯示轉(zhuǎn)發(fā) = 外部重定向
3.nginx中return、rewrite、proxy_pass它們的區(qū)別是什么?實現(xiàn)的功能是什么?
- return和rewrite都是nginx的ngx_http_rewrite_module模塊中的;
- proxy_pass是nginx的ngx_http_proxy_module模塊中的。
3.1 return
語法:return code [text];
return code URL;
return URL;
默認(rèn):—
語境:server, location, if
停止處理請求并返回指定的狀態(tài)碼個客戶端。非標(biāo)準(zhǔn)代碼444關(guān)閉連接而不發(fā)送響應(yīng)頭。
- return的狀態(tài)碼為301、302、303、307、308時,則為重定向;
- return的狀態(tài)碼為其他時,可以返回響應(yīng)主體[text]。
3.2 rewrite
語法:rewrite regex replacement [flag];
默認(rèn):—
語境:server, location, if
- 如果指定的regex表達(dá)式與請求URI匹配,則按照replacement中指定的規(guī)則更新URL。
- rewrite指令會根據(jù)配置文件中的順序依次執(zhí)行,可以使用[flag]參數(shù)終止指令向下繼續(xù)執(zhí)行。
- 如果replacement中替換字符串以“http://”、“https://”、"$scheme"開頭,則處理停止,并將重定向返回給客戶端。
可選[flag]參數(shù):
- last——停止當(dāng)前處理的ngx_http_rewrite_module指令集,重新開始搜索與修改后的URI匹配的location;(重寫)
- break——停止當(dāng)前處理的ngx_http_rewrite_module指令集;(重寫)
- redirect——返回帶有302狀態(tài)碼的臨時重定向;如果替換字符串不以“http://”、“https://”、"$scheme"開頭,則使用;(重定向)
- permanent——返回帶有301狀態(tài)碼的永久重定向。(重定向)
如果"rewrite ... last;"在location中,且location和rewrite的匹配規(guī)則能匹配到相同的URL,則"rewrite ... last;"的flag需要改成break。
否則,nginx將進(jìn)行10次循環(huán)匹配,并最終返回500狀態(tài)碼報錯。
location /download/ { rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break; return 403; }
如果replacement字符串包含新的請求參數(shù),則修改之前的請求參數(shù)會附加在修改后的URI后面。
如果不需要參數(shù),則在replacement字符串末尾添加問號,這樣修改后的請求不會被附加之前的請求參數(shù)。
rewrite ^/users/(.*)$ /show?user=$1? last;
如果正則表達(dá)式中包含";"、"}"這種結(jié)束符,則整個表達(dá)式應(yīng)該用單引號或雙引號引起來。
3.3 proxy_pass
ngx_http_proxy_module該模塊允許將請求傳遞到另一臺服務(wù)器。
語法:proxy_pass URL;
默認(rèn):—
語境:location, if in location, limit_except
設(shè)置代理服務(wù)器的協(xié)議、地址、端口、可選的URI。
- 協(xié)議:http、https
- 地址:域名、IP、upstream
- 端口:(可選)
- URI:(可選)
- 可以使用變量,如:“proxy_pass http://127.0.0.1$request_uri;”
- 可以代理到Unix套接字路徑,如:“proxy_pass http://unix:/tmp/backend.socket:/uri/;”
地址——除了IP+端口外,還可以指定域名和upstream。如果指定的是域名,會在配置文件中尋找對應(yīng)的服務(wù)器組(upstream),找不到才會按域名解析來;如果域名解析到多個IP,會以循環(huán)的方式使用這些IP。
URI——如果proxy_pass指定了URI,則請求傳遞到服務(wù)器時使用指定的URI替換location部分匹配的URI;如果proxy_pass沒有指定URI,則原始請求的URI會傳遞給服務(wù)器。
某些情況下,無法確定請求URI中替換的部分,需要用到正則表達(dá)式??梢栽趌ocation中通過rewrite重寫:
location /name/ { rewrite /name/([^/]+) /users?name=$1 break; proxy_pass http://127.0.0.1; }
3.4 nginx模塊實現(xiàn)重寫/重定向總結(jié)
nginx的模塊在實現(xiàn)重寫或者重定向時,并不是獨立的。不是某個模塊只能實現(xiàn)重寫,而另一個模塊只能實現(xiàn)重定向,并不是這種關(guān)系(至少對于rewrite來說不是)。
重定向:
- return狀態(tài)碼為301、302、303、304、307、308時,則為重定向
- rewrite的replacement中替換字符串以“http://”、“https://”、"$scheme"開頭,則為重定向
- rewrite的flag為redirect,則為302重定向
- rewrite的flag為permanent,則為301重定向
重寫:
- rewrite的flag為last時,且replacement中替換字符串不以“http://”、“https://”、"$scheme"開頭,則為重寫
- rewrite的flag為break時,且replacement中替換字符串不以“http://”、“https://”、"$scheme"開頭,則為重寫
- 使用proxy_pass,則為重寫
4.關(guān)于重寫/重定向時規(guī)則的匹配效率
在重寫和重定向時,經(jīng)常會用到正則表達(dá)式來匹配我們想要的URI。但是我們需要注意的時,應(yīng)該努力保持正則的整潔,越復(fù)雜會越影響效率。
下面的示例,通過盡量避免捕獲或匹配,從而提高效率:
- BAD:
rewrite ^/(.*)$ http://example.com/$1 permanent;
- GOOD:
rewrite ^ http://example.com$request_uri? permanent;
- BETTER:
return 301 http://example.com$request_uri;
5.總結(jié)
5.1 什么是重寫和重定向?
重定向:重定向是用戶請求服務(wù)端后,服務(wù)端向客戶端發(fā)送HTTP 301、302(303、304、307、308),告訴客戶端需要去嘗試另一個URL。意味著客戶端知道使用另一個URL并去訪問。(客戶端發(fā)起兩次請求)
重寫:重寫發(fā)生在服務(wù)器上。服務(wù)器內(nèi)部將一個URL轉(zhuǎn)到另一個URL,然后返回給客戶端??蛻舳瞬⒉恢雷约旱恼埱蟊晦D(zhuǎn)過一次,瀏覽器中的URL也始終是一開始訪問的那個。(客戶端發(fā)起一次請求)
5.2 相關(guān)名詞是什么對應(yīng)關(guān)系?
人理解的總結(jié):
- 重寫 = 隱式轉(zhuǎn)發(fā) = 內(nèi)部重定向
- 重定向 = 顯示轉(zhuǎn)發(fā) = 外部重定向
5.3 nginx模塊實現(xiàn)重寫和重定向地對應(yīng)關(guān)系
nginx的模塊在實現(xiàn)重寫或者重定向時,并不是獨立的。不是某個模塊只能實現(xiàn)重寫,而另一個模塊只能實現(xiàn)重定向,并不是這種關(guān)系(至少對于rewrite來說不是)。
重定向:
- return狀態(tài)碼為301、302、303、304、307、308時,則為重定向
- rewrite的replacement中替換字符串以“http://”、“https://”、"$scheme"開頭,則為重定向
- rewrite的flag為redirect,則為302重定向
- rewrite的flag為permanent,則為301重定向
重寫:
- rewrite的flag為last時,且replacement中替換字符串不以“http://”、“https://”、"$scheme"開頭,則為重寫
- rewrite的flag為break時,且replacement中替換字符串不以“http://”、“https://”、"$scheme"開頭,則為重寫
- 使用proxy_pass,則為重寫
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
nginx 反向代理之 proxy_pass的實現(xiàn)
這篇文章主要介紹了nginx 反向代理之 proxy_pass的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11iis+nginx實現(xiàn)負(fù)載均衡的詳細(xì)步驟
這篇文章主要為大家詳細(xì)介紹了iis+nginx實現(xiàn)負(fù)載均衡的詳細(xì)步驟 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07Nginx 出現(xiàn) 403 Forbidden 最終解決方法
這篇文章給大家介紹了Nginx 出現(xiàn) 403 Forbidden 最終解決方法,下面分步驟給大家介紹的非常詳細(xì),感興趣的的朋友一起看看吧2017-08-08配置解決Nginx服務(wù)器中WordPress路徑不自動加斜杠問題
這篇文章主要介紹了配置解決Nginx服務(wù)器中WordPress路徑不自動加斜杠問題,nginx不會自動在請求的最后加上一個斜線的問題文中也有提到通用的規(guī)則改寫方法,需要的朋友可以參考下2016-01-01nginx.conf配置文件結(jié)構(gòu)小結(jié)
本文主要介紹了nginx.conf配置文件結(jié)構(gòu)小結(jié),nginx.conf主要由events、http、server、location、upstream等塊配置項和一些行配置項組成,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04Nginx實現(xiàn)三種常見的虛擬主機(jī)配置方法
Nginx 是一款高性能的 Web 服務(wù)器,支持多種虛擬主機(jī)配置方式,能夠根據(jù)域名、IP 或端口區(qū)分不同的站點,這種靈活性讓 Nginx 成為搭建多站點服務(wù)的首選工具,本文將帶你一步步實現(xiàn)三種常見的虛擬主機(jī)配置方法,需要的朋友可以參考下2025-03-03