nginx http rewrite module 详解

大家好,我是 17。

今天和大家聊聊 nginx http rewrite module 。

简单来说, ngx_http_rewrite_module module 用正则匹配请求,改写请求,然后做跳转。可以是内部跳转,也可以是外部跳转。

学习这个模块的时候,把 rewrite_log 打开,可以在 error log 里查看跳转信息

 rewrite_log on; 
 error_log /home/log/test-error.log notice;

注意 notice 是必须的

顺序执行和循环跳转

  1. 直接写在 server level 的 指令,顺序执行。
  2. 写在 location 中的指定顺序执行。可以跳到其它 location ,最多不超过 10次。
server{
    rewrite ^/users/(.*)$ /show?user=$1 ;
    rewrite ^/teachers/(.*)$ /show?teacher=$1 ;
}

请求 /users/1 ,先执行第一条 rewrite ^/users/(.*)$ /show?user=$1
再执行第二条 rewrite ^/teachers/(.*)$ /show?teacher=$1 ; 虽然第一条匹配到了,还是会执行第二条。这就是顺序执行的意思。

location /{
    rewrite ^/teachers/(.*)$ /show/$1;
    rewrite ^/users/(.*) /show/$1;
}
location /show/{
    rewrite ^/show/(.*)$ /users/$1 ;
}

请求 /users/1,命中第一个location 。顺序执行第一个 rewrite,没命中,即使命中也会继续执行第二 rewrite ,命中。执行 rewirte 指令跳转到第二个location /show/,执行 rewirte 又回跳回 / ,这样循环10次,报 500 错误,查看 error 日志可以看到说明。

rewrite or internal redirection cycle while processing "/show/1"

这个过程演示了 location 中 rewrite 的执行逻辑。顺序执行,循环跳转。

rewrite module 中还有 5 个指令 break, if, return, rewrite, and set

return

return 可以直接返回,打断后面的 rewrite module 指令的执行。

location / {
 return 409;
 rewrite ^/teachers/(.*)$ /show/$1;
}

执行 return 后,后面的指令就没有机会执行了。

return code [text];
return code URL;
return URL;
location /admin/{
    return 403 '没有访问权限';
}
location / {
    return 302 $scheme://www.baidu.com$request_uri;
}

location /abc/{
    return 404;
}

set,break 比较简单,和其它语言差不多。下面着重讲下 rewirte 指令的 flag。

rewrite 指令的 flag

rewrite regex replacement [flag]

flag有四种

  • last 停止执行后面的 ngx_http_rewrite_module 指令,并发起新的 location 匹配。
  • break 停止执行后面的 ngx_http_rewrite_module 指令,然后没有后续了,不再发起 location 匹配。
  • redirect 执行 302跳转,后面的指令不再执行。
  • permanent 执行 301跳转,后面的指令不再执行。

last、break 停止执行的是 ngx_http_rewrite_module 指令,其它指令不受影响,还是会执行的。

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

因为 last 会终止后面的  ngx_http_rewrite_module 指令,所以 第二句 rewrite ^/teacher/(.*) /show2/$1 不会执行。第一句执行完后,跳到 /show1,返回 900

如果把 last 换成  break
HTTP/1.1 404

因为 break 不再执行跳转,直接查找 show1/1 找不到,报 404.

把 last 换成 redirect.
HTTP/1.1 302 

浏览器会请求两次。

把 last 换成 permanent.
HTTP/1.1 301 

浏览器会请求两次。

如果 replacement 是 http开头,是可以直接跳转的

location / {
  rewrite ^/teacher/ http://juejin.cn
}

curl http://localhost:3000/teacher/1
HTTP/1.1 302 
Location: http://juejin.cn

相当于 redirect 指令的效果。

if 语句

if 语句不复杂,但是非常有用,可以这样说,用 if 可以实现很多指令,但是用内置指令更简洁,还是要优先用指令。

if ($param) 如果 $param 为空字符串或 0 为假,其它情况为真。

注意 if 后面必须要有空格,否则报错。

set $param '0';
set $param 0;
set $param '';

这三种写法 $param 都为假,其它情况都为真

用 = ,!=判断相等。

 if ($request_method = POST){
      return 403;
 }

注意 是一个 = 不是两个=, 等号左右必须要有空格,否则报错

用正则表达式判断

~ 区分大小写
if ($http_user_agent ~ mobile)

~* 不区分大小写
if ($http_referer ~* juejin\.cn)

!~ 和 !~* 是对应的两个否定写法,不再举例了。

用 flag

-f !-f  文件是否存在
if (-f $request_filename)
if (!-f $request_filename)

-d !-d 目录是否存在
-e !-e 文件或目录是否存在
-x !-e 是否可执行


## url 美化
http rewrite 一个应用就是 url 美化。
我们在开发的时候用的 url 是这样的 

/users?id=1

让别人访问的时候可能是这样的

/users/1

所以我们需要把 `/users/1` 转为 `/users?id=1` ,这时就需要 rewrite 出场了。

location /users/{
rewrite ^/users/(.*)$ /nodejs/id=$1? last;
}
location /nodejs/{
proxy_pass http://127.0.0.1:3000;
}

当请求`/users/1` 的时候,命中 location /users/ ,执行rewrite 指令, last flag 指示停止后面的rewrite 指令并做内部跳转,匹配到 location /nodejs/ ,经过 proxy_pass 指令,转到 /nodejs/ 。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IAM17前端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值