大家好,我是 17。
今天和大家聊聊 nginx http rewrite module 。
簡(jiǎn)單來(lái)說(shuō), ngx_http_rewrite_module
module 用正則匹配請(qǐng)求,改寫(xiě)請(qǐng)求,然后做跳轉(zhuǎn)。可以是內(nèi)部跳轉(zhuǎn),也可以是外部跳轉(zhuǎn)。
學(xué)習(xí)這個(gè)模塊的時(shí)候,把 rewrite_log 打開(kāi),可以在 error log 里查看跳轉(zhuǎn)信息
rewrite_log on;
error_log /home/log/test-error.log notice;
注意 notice 是必須的
順序執(zhí)行和循環(huán)跳轉(zhuǎn)
- 直接寫(xiě)在 server level 的 指令,順序執(zhí)行。
- 寫(xiě)在 location 中的指定順序執(zhí)行??梢蕴狡渌?location ,最多不超過(guò) 10次。
server{
rewrite ^/users/(.*)$ /show?user=$1 ;
rewrite ^/teachers/(.*)$ /show?teacher=$1 ;
}
請(qǐng)求 /users/1 ,先執(zhí)行第一條 rewrite ^/users/(.*)$ /show?user=$1
再執(zhí)行第二條 rewrite ^/teachers/(.*)$ /show?teacher=$1 ;
雖然第一條匹配到了,還是會(huì)執(zhí)行第二條。這就是順序執(zhí)行的意思。
location /{
rewrite ^/teachers/(.*)$ /show/$1;
rewrite ^/users/(.*) /show/$1;
}
location /show/{
rewrite ^/show/(.*)$ /users/$1 ;
}
請(qǐng)求 /users/1,命中第一個(gè)location 。順序執(zhí)行第一個(gè) rewrite,沒(méi)命中,即使命中也會(huì)繼續(xù)執(zhí)行第二 rewrite ,命中。執(zhí)行 rewirte 指令跳轉(zhuǎn)到第二個(gè)location /show/,執(zhí)行 rewirte 又回跳回 / ,這樣循環(huán)10次,報(bào) 500 錯(cuò)誤,查看 error 日志可以看到說(shuō)明。
rewrite or internal redirection cycle while processing "/show/1"
這個(gè)過(guò)程演示了 location 中 rewrite 的執(zhí)行邏輯。順序執(zhí)行,循環(huán)跳轉(zhuǎn)。
rewrite module 中還有 5 個(gè)指令 break, if, return, rewrite, and set。
return
return 可以直接返回,打斷后面的 rewrite module 指令的執(zhí)行。
location / {
return 409;
rewrite ^/teachers/(.*)$ /show/$1;
}
執(zhí)行 return 后,后面的指令就沒(méi)有機(jī)會(huì)執(zhí)行了。
return code [text];
return code URL;
return URL;
location /admin/{
return 403 '沒(méi)有訪問(wèn)權(quán)限';
}
location / {
return 302 $scheme://www.baidu.com$request_uri;
}
location /abc/{
return 404;
}
set,break 比較簡(jiǎn)單,和其它語(yǔ)言差不多。下面著重講下 rewirte 指令的 flag。
rewrite 指令的 flag
rewrite regex
replacement
[flag
]
flag有四種
- last 停止執(zhí)行后面的 ngx_http_rewrite_module 指令,并發(fā)起新的 location 匹配。
- break 停止執(zhí)行后面的 ngx_http_rewrite_module 指令,然后沒(méi)有后續(xù)了,不再發(fā)起 location 匹配。
- redirect 執(zhí)行 302跳轉(zhuǎn),后面的指令不再執(zhí)行。
- permanent 執(zhí)行 301跳轉(zhuǎn),后面的指令不再執(zhí)行。
last、break 停止執(zhí)行的是 ngx_http_rewrite_module 指令,其它指令不受影響,還是會(huì)執(zhí)行的。
regex 匹配的是路徑部分
location / {
rewrite ^/teacher/(.*)$ /show1/$1 last;
rewrite ^/teacher/(.*) /show2/$1;
}
location /show1{
return 900;
}
location /show2{
return 901;
}
curl http://localhost:3000/teacher/1
HTTP/1.1 900
因?yàn)?last 會(huì)終止后面的 ngx_http_rewrite_module 指令,所以 第二句 rewrite ^/teacher/(.*) /show2/$1 不會(huì)執(zhí)行。第一句執(zhí)行完后,跳到 /show1,返回 900
如果把 last 換成 break
HTTP/1.1 404
因?yàn)?break 不再執(zhí)行跳轉(zhuǎn),直接查找 show1/1 找不到,報(bào) 404.
把 last 換成 redirect.
HTTP/1.1 302
瀏覽器會(huì)請(qǐng)求兩次。
把 last 換成 permanent.
HTTP/1.1 301
瀏覽器會(huì)請(qǐng)求兩次。
如果 replacement 是 http開(kāi)頭,是可以直接跳轉(zhuǎn)的
location / {
rewrite ^/teacher/ http://juejin.cn
}
curl http://localhost:3000/teacher/1
HTTP/1.1 302
Location: http://juejin.cn
相當(dāng)于 redirect 指令的效果。
if 語(yǔ)句
if 語(yǔ)句不復(fù)雜,但是非常有用,可以這樣說(shuō),用 if 可以實(shí)現(xiàn)很多指令,但是用內(nèi)置指令更簡(jiǎn)潔,還是要優(yōu)先用指令。
if ($param)
如果 $param 為空字符串或 0 為假,其它情況為真。
注意 if 后面必須要有空格,否則報(bào)錯(cuò)。
set $param '0';
set $param 0;
set $param '';
這三種寫(xiě)法 $param 都為假,其它情況都為真
用 = ,!=判斷相等。
if ($request_method = POST){
return 403;
}
注意 是一個(gè) = 不是兩個(gè)=, 等號(hào)左右必須要有空格,否則報(bào)錯(cuò)
用正則表達(dá)式判斷
~ 區(qū)分大小寫(xiě)
if ($http_user_agent ~ mobile)
~* 不區(qū)分大小寫(xiě)
if ($http_referer ~* juejin\.cn)
!~ 和 !~* 是對(duì)應(yīng)的兩個(gè)否定寫(xiě)法,不再舉例了。
用 flag
-f !-f 文件是否存在
if (-f $request_filename)
if (!-f $request_filename)
-d !-d 目錄是否存在
-e !-e 文件或目錄是否存在
-x !-e 是否可執(zhí)行
## url 美化
http rewrite 一個(gè)應(yīng)用就是 url 美化。
我們?cè)陂_(kāi)發(fā)的時(shí)候用的 url 是這樣的
/users?id=1
讓別人訪問(wèn)的時(shí)候可能是這樣的
/users/1文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-402653.html
所以我們需要把 `/users/1` 轉(zhuǎn)為 `/users?id=1` ,這時(shí)就需要 rewrite 出場(chǎng)了。
location /users/{
rewrite ^/users/(.*)$ /nodejs/id=$1? last;
}
location /nodejs/{
proxy_pass http://127.0.0.1:3000;
}文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-402653.html
當(dāng)請(qǐng)求`/users/1` 的時(shí)候,命中 location /users/ ,執(zhí)行rewrite 指令, last flag 指示停止后面的rewrite 指令并做內(nèi)部跳轉(zhuǎn),匹配到 location /nodejs/ ,經(jīng)過(guò) proxy_pass 指令,轉(zhuǎn)到 /nodejs/ 。
到了這里,關(guān)于nginx http rewrite module 詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!