前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【NGINX入门】6.Nginx的rewrite规则详解

【NGINX入门】6.Nginx的rewrite规则详解

作者头像
辉哥
发布2021-02-04 09:52:29
3.9K0
发布2021-02-04 09:52:29
举报
文章被收录于专栏:区块链入门

1.摘要

nginx Rewrite规则可以让网站的url中达到某种状态时定向/跳转到某个规则,本文具体介绍这些规则和说明。

2. 内容

2.1 Rewrite规则

rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。rewrite只能放在server{}, location{}, if{}中,并且只能对域名后边的除去传递的参数外的字符串起作用,例如 http://seanlook.com/a/we/index.php?id=1&u=str 只对/a/we/index.php重写。

语法:

rewrite regex replacement [flag];

如果相对域名或参数字符串起作用,可以使用全局变量匹配,也可以使用proxy_pass反向代理。

表面看rewrite和location功能有点像,都能实现跳转,主要区别在于rewrite是在同一域名内更改获取资源的路径,而location是对一类路径做控制访问或反向代理,可以proxy_pass到其他机器。很多情况下rewrite也会写在location里,它们的执行顺序是:

  • 1,执行server块的rewrite指令
  • 2,执行location匹配
  • 3,执行选定的location中的rewrite指令

如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件;循环超过10次,则返回500 Internal Server Error错误。

2.2 flag标志位

  • last : 相当于Apache的[L]标记,表示完成rewrite
  • break : 停止执行当前虚拟主机的后续rewrite指令集
  • redirect : 返回302临时重定向,地址栏会显示跳转后的地址
  • permanent : 返回301永久重定向,地址栏会显示跳转后的地址
(1)break和last区别

rewrite里面flag中break和last是什么区别?请看下面的例子:

代码语言:javascript
复制
root /opt/app/code; 

location ~ ^/break {
    rewrite ^/break /test/ break;
} 

location ~ ^/last {
     rewrite ^/last /test/ last;
}    

location /test/ {
   default_type application/json;
   return 200 '{"status":"success"}';
}

break是停止处理当前的ngx_http_rewrite_module指令集,就是说不会在向下匹配新的location,last停止处理当前的ngx_http_rewrite_module指令集并开始搜索与更改的URI匹配的新位置;

假设我们在页面上访问的url是http://walidream.com/break,根据上面的nginx规则,肯定会匹配到第一个,匹配到第一个之后,根据rewrite正则,url由原来的/break变为/test/但是在root/opt/code/目录下,没有找到/test/目录下面的内容,所以nginx会返回404错误码。

如果将http://walidream.com/break换成http://walidream.com/last,根据上面的nginx规则,会匹配到第二个location,根据location里面rewrite正则,url由原来的/last变为/test/,但是会重新 匹配loction中,可以简单理解就是将替换后urlhttp://walidream.com/test重新发起一次请求。这个时候会匹配到第三个loaction,根据location里的rewrite正则,会返回200码,并且会返回json内容’{“status”:“success”}’。

总结说明下:

  • last一般写在server和if中,而break一般使用在location中;
  • last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配;
  • break和last都能组织继续执行后面的rewrite指令;
(2)redirect和permanent区别

rewrite里面flag中redirect(临时重定向)和permanent(永久重定向)是什么区别?请看下面的例子:

代码语言:javascript
复制
location ~ ^/imooc { 
    rewrite ^/imooc http://www.imooc.com/ redirect;
} 

location ~ ^/wali {
    rewrite ^/wali http://www.imooc.com/ permanent;
}

redirect会返回带有302代码的临时重定向,permanent会返回带有301代码的永久重定向。

假设我们在页面上访问url是http://walidream.com/imooc,根据nginx匹配规则会匹配到第一个location,会重写url,返回一个带有302状态代码,重写后的url是http://www.imooc.com,浏览器会重定向到这个网址, 当我们再次访问http://walidream.com/imooc,nginx还是会先匹配再替换然后重定向。

如果在页面上输入http://walidream.com/wali,根据nginx匹配规则会匹配到第二个location,会重写url,返回一个带有301状态码,重写后的url是http://www.imooc.com,浏览器会重新定向到这个网址, 当我们再次访问http://walidream.com/wali,这个时候浏览器根本不会在经过nginx,而是直接有浏览器重定向到这个网址。

2.3 全局变量

内置的全局变量如下。

变量名

描述

$args

这个变量等于请求行中的参数,同$query_string

$content_length

请求头中的Content-length字段

$content_type

请求头中的Content-Type字段

$document_root

当前请求在root指令中指定的值

$host

请求主机头字段,否则为服务器名称

$http_user_agent

客户端agent信息

$http_cookie

客户端cookie信息

$limit_rate

这个变量可以限制连接速率

$request_method

客户端请求的动作,通常为GET或POST

$remote_addr

客户端的IP地址

$remote_port

客户端的端口

$remote_user

已经经过Auth Basic Module验证的用户名

$request_filename

当前请求的文件路径,由root或alias指令与URI请求生成

$scheme

HTTP方法(如http,https)

$server_protocol

请求使用的协议,通常是HTTP/1.0或HTTP/1.1

$server_addr

服务器地址,在完成一次系统调用后可以确定这个值

$server_name

服务器名称

$server_port

请求到达服务器的端口号

$request_uri

包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”

$uri

不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”

$document_uri

与$uri相同

2.4 if指令与全局变量使用

if判断指令的语法

if (condition) { ... }

对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容: (1) 当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false (2) 直接比较变量和内容时,使用=或!= (3) 正则表达式匹配,*不区分大小写的匹配,!~区分大小写的不匹配 (4) -f和!-f用来判断是否存在文件 (5) -d和!-d用来判断是否存在目录 (6) -e和!-e用来判断是否存在文件或目录 (7) -x和!-x用来判断文件是否可执行

例如:​

代码语言:javascript
复制
if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含"MSIE",rewrite请求到/msie/目录下

if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
 } //如果cookie匹配正则,设置变量$id等于正则引用部分

if ($request_method = POST) {
    return 405;
} //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302

if ($slow) {
    limit_rate 10k;
} //限速,$slow可以通过 set 指令设置

if (!-f $request_filename){
    break;
    proxy_pass  http://127.0.0.1; 
} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查

if ($args ~ post=140){
    rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com

location ~* \.(gif|jpg|png|swf|flv)$ {
    valid_referers none blocked www.jefflei.com www.leizhenfang.com;
    if ($invalid_referer) {
        return 404;
    } //防盗链
}
valid_referers 指令详解

该指令后面可以接 none blocked serevr_names string或者是正则表达式:

  • none 代表没有referer
  • blocked 代表有referer但是被防火墙或者是代理给去除了
  • string或者正在表达式 用来匹配referer

nginx会通过查看referer字段和valid_referers后面的referer列表进行匹配,如果匹配到了就invalid_referer字段值为0 否则设置该值为1。 现我为公司写出了实现这一功能的代码

代码语言:javascript
复制
valid_referers none blocked server_names;
if ($invalid_referer) {
 rewrite ^/ http://********.com/ redirect;
}

说明: 1.首先当我输入我要打开的网址的时候,因为是直接输入的没有referer所以匹配了valid_referers后面的none或者是blocked 所以invalid_referer值为0 所以不进行跳转. 当我是从这个网站里面的链接跳到该网站首页的时候 因为referer的值是肯定包含srever_names,所以匹配了server_names所以不进行跳转。

2.当我从搜素引擎进去的时候因为referer字段类似于www.google.com.hk/search开始进行匹配 发现没有一个匹配,则此时会设置invalid_referer值为1 if语句成功执行,进行了跳转. 达到功能。

2.4 调试rewrite是否正确

2.4.1 打开rewrite_log

nginx中要检测rewrite是否正确,就需要开启rewrite_log才能排错,rewrite_log会打印错误。检测完后,建议将rewrite_log关闭。

rewrite_log Syntax: rewrite_log on | off; Default: rewrite_log off; Context: http, server, location, if

示例:

代码语言:javascript
复制
rewrite_log on;
error_log /var/log/nginx/rewrite.log notice;

2.4.2 利用变量或者return调试

一般来说,要验证rewrite正则是否正确,就要打开rewrite_log日志,如果匹配错了,日志会记录错误信息。 另外,一般的检测语法,我们可以利用变量return 返回。

代码语言:javascript
复制
location ~ ^/wali {
    default_type application/json;
    return 200 '{"status":"success"}';
}

location ~ ^/yagm {
    default_type application/json;
    return 200 '{"status":"error"}';
}

这样有时候在调试时会让我们变得稍微方便一点,还有nginx扩展模块如echo就能直接输出内容或者打印内部变量。

3. 参考

(1)Nginx系列教程之基于nginx配置请求转发location及rewrite规则详解 https://blog.csdn.net/JunyouYH/article/details/107469699

(2)nginx rewrite规则(23) https://www.imooc.com/article/283363

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.摘要
  • 2. 内容
    • 2.1 Rewrite规则
      • 2.2 flag标志位
        • 2.3 全局变量
          • 2.4 if指令与全局变量使用
            • 2.4 调试rewrite是否正确
              • 2.4.1 打开rewrite_log
              • 2.4.2 利用变量或者return调试
          • 3. 参考
          相关产品与服务
          轻量应用服务器
          轻量应用服务器(TencentCloud Lighthouse)是新一代开箱即用、面向轻量应用场景的云服务器产品,助力中小企业和开发者便捷高效的在云端构建网站、Web应用、小程序/小游戏、游戏服、电商应用、云盘/图床和开发测试环境,相比普通云服务器更加简单易用且更贴近应用,以套餐形式整体售卖云资源并提供高带宽流量包,将热门软件打包实现一键构建应用,提供极简上云体验。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档