nginx重寫和重定向關(guān)系與配置方式
前言
一直對(duì)nginx的重寫和重定向都是只有一個(gè)模糊的認(rèn)識(shí),只是知道在nginx里return、rewrite、proxy_pass能實(shí)現(xiàn)我想要的轉(zhuǎn)發(fā)。
每次查閱資料時(shí),各種關(guān)鍵詞充斥在眼前:“重寫”、“重定向”、“隱式轉(zhuǎn)發(fā)”、“內(nèi)部重定向”......一直沒有區(qū)分清楚他們之前的區(qū)別或聯(lián)系。
隨之產(chǎn)生幾個(gè)問題,想要花點(diǎn)時(shí)間搞清楚它們:
- 重寫和重定向的區(qū)別是什么?
- nginx中“重寫”、“重定向”、“隱式轉(zhuǎn)發(fā)”、“內(nèi)部重定向”......這些名詞的關(guān)系是什么?在nginx是否都由一個(gè)獨(dú)立的模塊、關(guān)鍵字來實(shí)現(xiàn)這些的?
- nginx中return、rewrite、proxy_pass它們的區(qū)別是什么?對(duì)于重寫和重定向,它們是否各自實(shí)現(xiàn)不同的功能?
1.重寫和重定向的區(qū)別是什么?
首先說說關(guān)聯(lián)
首先重寫和重定向的最終目的是一樣的。假如你通過瀏覽器和固定的鏈接經(jīng)常訪問一張“好看的圖片”,有一天圖片的維護(hù)者將它移動(dòng)了位置(服務(wù)器上的目錄、移動(dòng)到其他域名),那意味著你訪問不到這張圖片了?
為了避免這樣的情況給用戶帶來的困擾,可以使用重寫、或者重定向,將你的請(qǐng)求轉(zhuǎn)向新的位置(這張圖片新的位置),對(duì)你來說還是用老的固定的鏈接訪問到了你喜歡的圖片。
那他們的區(qū)別呢?
重定向:重定向是用戶請(qǐng)求服務(wù)端后,服務(wù)端向客戶端發(fā)送HTTP 301、302(303、304、307、308),告訴客戶端需要去嘗試另一個(gè)URL。意味著客戶端知道使用另一個(gè)URL并去訪問。(客戶端發(fā)起兩次請(qǐng)求)
重定向的請(qǐng)求路徑如下:
- request1(來自客戶端):訪問“好看的圖片”
- response1(來自服務(wù)端):你要訪問的圖片不在這了,你需要去訪問“好看的圖片新的位置”
- request2(來自客戶端):訪問“好看的圖片新的位置”
- response2(來自服務(wù)端):拿去吧,你要的“好看的圖片新的位置”對(duì)應(yīng)的圖片
重寫:重寫發(fā)生在服務(wù)器上。服務(wù)器內(nèi)部將一個(gè)URL轉(zhuǎn)到另一個(gè)URL,然后返回給客戶端??蛻舳瞬⒉恢雷约旱恼?qǐng)求被轉(zhuǎn)過一次,瀏覽器中的URL也始終是一開始訪問的那個(gè)。(客戶端發(fā)起一次請(qǐng)求)
重寫的請(qǐng)求路徑如下:
- request1(來自客戶端):訪問“好看的圖片”
- 重寫(服務(wù)端處理):將“好看的圖片”改到“好看的圖片新的位置”,獲取到圖片
- response1(來自服務(wù)端):拿去吧,你要的“好看的圖片”對(duì)應(yīng)的圖片
粗暴總結(jié):
從瀏覽器的反饋來看。重寫-客戶端只會(huì)發(fā)送一次請(qǐng)求;重定向-客戶端會(huì)發(fā)送兩次請(qǐng)求。
2.“重寫”、“重定向”、“隱式轉(zhuǎn)發(fā)”、“內(nèi)部重定向”......這些名詞的關(guān)系是什么?
重寫和重定向在上面已經(jīng)解釋過了。關(guān)于其他名詞的解釋,在網(wǎng)上搜羅了一下:
- 隱式轉(zhuǎn)發(fā)/隱形轉(zhuǎn)發(fā)/隱藏式跳轉(zhuǎn):將請(qǐng)求跳轉(zhuǎn)到另一個(gè)網(wǎng)站的頁(yè)面,并且瀏覽器中URL保持不變。
- 顯示轉(zhuǎn)發(fā):將請(qǐng)求跳轉(zhuǎn)到另一個(gè)網(wǎng)站的頁(yè)面,瀏覽器中URL會(huì)發(fā)生改變。
- 內(nèi)部重定向:內(nèi)部重定向(重寫)發(fā)生在server端內(nèi)部,client端不知情,瀏覽器上URL不會(huì)改變。
- 外部重定向:外部重定向是server端通知client端需要訪問新的URL,client端進(jìn)行第二次訪問。瀏覽器中URL也變成新的URL。
思來想去,似乎就是對(duì)重寫和重定向取了好多名字。所以個(gè)人理解的總結(jié):
- 重寫 = 隱式轉(zhuǎn)發(fā) = 內(nèi)部重定向
- 重定向 = 顯示轉(zhuǎn)發(fā) = 外部重定向
3.nginx中return、rewrite、proxy_pass它們的區(qū)別是什么?實(shí)現(xiàn)的功能是什么?
- return和rewrite都是nginx的ngx_http_rewrite_module模塊中的;
- proxy_pass是nginx的ngx_http_proxy_module模塊中的。
3.1 return
語(yǔ)法:return code [text];
return code URL;
return URL;
默認(rèn):—
語(yǔ)境:server, location, if
停止處理請(qǐng)求并返回指定的狀態(tài)碼個(gè)客戶端。非標(biāo)準(zhǔn)代碼444關(guān)閉連接而不發(fā)送響應(yīng)頭。
- return的狀態(tài)碼為301、302、303、307、308時(shí),則為重定向;
- return的狀態(tài)碼為其他時(shí),可以返回響應(yīng)主體[text]。
3.2 rewrite
語(yǔ)法:rewrite regex replacement [flag];
默認(rèn):—
語(yǔ)境:server, location, if
- 如果指定的regex表達(dá)式與請(qǐng)求URI匹配,則按照replacement中指定的規(guī)則更新URL。
- rewrite指令會(huì)根據(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)碼的臨時(shí)重定向;如果替換字符串不以“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)碼報(bào)錯(cuò)。
location /download/ {
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
return 403;
}如果replacement字符串包含新的請(qǐng)求參數(shù),則修改之前的請(qǐng)求參數(shù)會(huì)附加在修改后的URI后面。
如果不需要參數(shù),則在replacement字符串末尾添加問號(hào),這樣修改后的請(qǐng)求不會(huì)被附加之前的請(qǐng)求參數(shù)。
rewrite ^/users/(.*)$ /show?user=$1? last;
如果正則表達(dá)式中包含";"、"}"這種結(jié)束符,則整個(gè)表達(dá)式應(yīng)該用單引號(hào)或雙引號(hào)引起來。
3.3 proxy_pass
ngx_http_proxy_module該模塊允許將請(qǐng)求傳遞到另一臺(tái)服務(wù)器。
語(yǔ)法:proxy_pass URL;
默認(rèn):—
語(yǔ)境: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。如果指定的是域名,會(huì)在配置文件中尋找對(duì)應(yīng)的服務(wù)器組(upstream),找不到才會(huì)按域名解析來;如果域名解析到多個(gè)IP,會(huì)以循環(huán)的方式使用這些IP。
URI——如果proxy_pass指定了URI,則請(qǐng)求傳遞到服務(wù)器時(shí)使用指定的URI替換location部分匹配的URI;如果proxy_pass沒有指定URI,則原始請(qǐng)求的URI會(huì)傳遞給服務(wù)器。
某些情況下,無法確定請(qǐng)求URI中替換的部分,需要用到正則表達(dá)式??梢栽趌ocation中通過rewrite重寫:
location /name/ {
rewrite /name/([^/]+) /users?name=$1 break;
proxy_pass http://127.0.0.1;
}3.4 nginx模塊實(shí)現(xiàn)重寫/重定向總結(jié)
nginx的模塊在實(shí)現(xiàn)重寫或者重定向時(shí),并不是獨(dú)立的。不是某個(gè)模塊只能實(shí)現(xiàn)重寫,而另一個(gè)模塊只能實(shí)現(xiàn)重定向,并不是這種關(guān)系(至少對(duì)于rewrite來說不是)。
重定向:
- return狀態(tài)碼為301、302、303、304、307、308時(shí),則為重定向
- rewrite的replacement中替換字符串以“http://”、“https://”、"$scheme"開頭,則為重定向
- rewrite的flag為redirect,則為302重定向
- rewrite的flag為permanent,則為301重定向
重寫:
- rewrite的flag為last時(shí),且replacement中替換字符串不以“http://”、“https://”、"$scheme"開頭,則為重寫
- rewrite的flag為break時(shí),且replacement中替換字符串不以“http://”、“https://”、"$scheme"開頭,則為重寫
- 使用proxy_pass,則為重寫
4.關(guān)于重寫/重定向時(shí)規(guī)則的匹配效率
在重寫和重定向時(shí),經(jīng)常會(huì)用到正則表達(dá)式來匹配我們想要的URI。但是我們需要注意的時(shí),應(yīng)該努力保持正則的整潔,越復(fù)雜會(huì)越影響效率。
下面的示例,通過盡量避免捕獲或匹配,從而提高效率:
- 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 什么是重寫和重定向?
重定向:重定向是用戶請(qǐng)求服務(wù)端后,服務(wù)端向客戶端發(fā)送HTTP 301、302(303、304、307、308),告訴客戶端需要去嘗試另一個(gè)URL。意味著客戶端知道使用另一個(gè)URL并去訪問。(客戶端發(fā)起兩次請(qǐng)求)
重寫:重寫發(fā)生在服務(wù)器上。服務(wù)器內(nèi)部將一個(gè)URL轉(zhuǎn)到另一個(gè)URL,然后返回給客戶端??蛻舳瞬⒉恢雷约旱恼?qǐng)求被轉(zhuǎn)過一次,瀏覽器中的URL也始終是一開始訪問的那個(gè)。(客戶端發(fā)起一次請(qǐng)求)
5.2 相關(guān)名詞是什么對(duì)應(yīng)關(guān)系?
人理解的總結(jié):
- 重寫 = 隱式轉(zhuǎn)發(fā) = 內(nèi)部重定向
- 重定向 = 顯示轉(zhuǎn)發(fā) = 外部重定向
5.3 nginx模塊實(shí)現(xiàn)重寫和重定向地對(duì)應(yīng)關(guān)系
nginx的模塊在實(shí)現(xiàn)重寫或者重定向時(shí),并不是獨(dú)立的。不是某個(gè)模塊只能實(shí)現(xiàn)重寫,而另一個(gè)模塊只能實(shí)現(xiàn)重定向,并不是這種關(guān)系(至少對(duì)于rewrite來說不是)。
重定向:
- return狀態(tài)碼為301、302、303、304、307、308時(shí),則為重定向
- rewrite的replacement中替換字符串以“http://”、“https://”、"$scheme"開頭,則為重定向
- rewrite的flag為redirect,則為302重定向
- rewrite的flag為permanent,則為301重定向
重寫:
- rewrite的flag為last時(shí),且replacement中替換字符串不以“http://”、“https://”、"$scheme"開頭,則為重寫
- rewrite的flag為break時(shí),且replacement中替換字符串不以“http://”、“https://”、"$scheme"開頭,則為重寫
- 使用proxy_pass,則為重寫
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- nginx 老網(wǎng)站域名重定向到新網(wǎng)站的方法(親測(cè))
- 在Nginx中實(shí)現(xiàn)URL重寫與重定向
- Nginx地址重定向的實(shí)現(xiàn)
- nginx的服務(wù)配置及重定向問題
- nginx重定向解決(rewrite or internal redirection cycle)
- Nginx重定向后請(qǐng)求參數(shù)丟失的原因分析及解決方案
- nginx反向代理后無限重定向的問題解決方法
- Nginx中rewrite(地址重定向)的深入剖析
- 利用Nginx實(shí)現(xiàn)URL重定向的簡(jiǎn)單方法
- 配置nginx 重定向到系統(tǒng)維護(hù)頁(yè)面
- nginx中重定向的實(shí)現(xiàn)
相關(guān)文章
Nginx中配置過濾爬蟲的User-Agent的簡(jiǎn)單方法
這篇文章主要介紹了Nginx中配置過濾爬蟲的User-Agent的簡(jiǎn)單方法,文中羅列了一些常用搜索引擎的爬蟲名稱以免造成不必要的過濾,需要的朋友可以參考下2016-01-01
Nginx大并發(fā)優(yōu)化實(shí)戰(zhàn)
這篇文章主要介紹了Nginx大并發(fā)優(yōu)化實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
HipChat上傳文件報(bào)未知錯(cuò)誤的原因分析及解決方案
HipChat的功能類似于Campfire、Sazneo等在線協(xié)同工具,并且和Yammer以及Salesforce的Chatter等企業(yè)社交平臺(tái)有一定相似之處。你可以為單個(gè)項(xiàng)目或者小組搭建自有的聊天室,也可以很方便的發(fā)起一對(duì)一聊天2016-01-01
Nginx反向代理出現(xiàn)502與504錯(cuò)誤問題詳解及排查指南
Nginx 作為反向代理服務(wù)器時(shí),502(Bad Gateway)和 504(Gateway Timeout)錯(cuò)誤是常見的兩類問題,下面我們就來看看這兩個(gè)錯(cuò)誤問題的排查與解決吧2025-05-05

