首页 > 系统相关 >15、nginx的rewrite机制

15、nginx的rewrite机制

时间:2024-01-16 18:34:32浏览次数:21  
标签:字符 15 请求 匹配 URL rewrite nginx 服务器

1.概述

  • Rewrite主要的功能就是实现URL的重写。Nginx的Rewrite规则采用PCRE(Perl Compatible Regular Expressions) Perl 兼容正则表达式的语法进行规则匹配。
  • 通过Rewrite规则,可以实现规范的 URL、根据变量来做URL转向及选择配置。例如,一些使用MVC框架的程序只有一个入口,可以通过Rewrite来实现。一些动态URL地址须要伪装成静态HTML,便于搜索引擎抓取,也需要 Rewrite来处理。一些由于目录结构、域名变化的旧URL,须要跳转到新的URL上,也可以通过Rewrite来处理

2.基础规则

  • Nginx Rewrite 规则相关指令有 if、rewrite、set、return、break 等,其中 rewrite 是最关键的指令。一-个简单的 Nginx Rewrite 规则语法如下:

    rewrite ^/b/(.*)\.html  /play.php?video=$l break;
    

    如果加上f语句,示例如下:

    if(!-f $request_filename)
    {
        rewrite ^/img/(.*)$ /site/$host/images/$1 last;
    }
    

2.1 break指令

语法: break
默认值: none
使用环境: server、location、if

该指令的作用是完成当前的规则集,不再处理rewrite 指令。示例如下:

if ($slow){
	limit_rate 10k;
    break;
}

2.2 if 指令

语法: if(condition){ ...}
默认值: none
使用环境: server、location

  • 该指令用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句。if 指令不支持嵌套,不支持多个条件&&||处理。
    以下信息可以被指定为条件:

    • 变量名,错误的值包括: 空字符"",或者任何以0开始的字符串

    • 变量比较可以使用=(表示等于)!=(表示不等于) 运算符;

    • 正则表达式模式匹配可以使用~*~符号

    • ~符号表示区分大小写字母的匹配

    • ~*符号表示不区分大小写字母的匹配(例如 firefox 与 FireFox 是匹配的);

    • !~!~*符号的作用刚好和~!~*相反,表示不匹配;

    • -f!-f用来文件是否存在

    • -d!-d用来判断目录是否存在;

    • -e!-e用来断文件或目录是否存在

    • -x!-x用来判断文件是否可执行。

部分正则表达式可以在圆括号()内,其值可以通过后面的变量$1至$9 访问

if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$l break;
}

if ($http_cookie ~* "id=([^;] +)(?:;|$)”) {
  set $id $l;
}

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

if (!-f $request_filename) {
    break;
    proxy_pass http://127.0.0.1;
}

if ($slow) {
    limit_rate 10k;
}

if ($invalid_referer){
  return 403;  
} 

if ($args ^~ post=140){
    rewrite ^ http://example.com/permanent;
}

2.3 return指令

语法: return code
默认值: none
使用环境:server、location、if

  • 该指令用于结束规则的执行并返回状态码给客户端。状态码可以使用这值:

    204、400、402406、408、410、411、413、416及500504。此外,非标准状态码 444 将以不发送任何 Header头的方式结束连接。示例,如果访问的URL以ShBash结尾,则返回状态码403:

    location ~ .*\.(sh|bash)?${
        return 403;
    }
    
    • 204 No Content
      服务器成功处理了请求,但无须返回任何实体内容,并且希望返回更新了的元信息。响应可能通过实体头部的形式,返回新的或更新后的元信息。如果存在这些头部信息,则应当与所请求的变量相呼应。如果客户端是浏览器,那么用户浏览器应保留发送了该请求的页面,而不产生任何文档视图上的变化,即使按照规范新的或更新后的元信息,也应当被应用到用户浏览器活动视图中的文档。
    • 400 Bad Request
      由于包含语法错误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求。
    • 402 Payment Required
      该状态码是为了将来可能的需求而预留的
    • 403 Forbidden
      服务器已经理解请求,但是拒绝执行它。与401响应不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交。如果这不是一个 HEAD 请求,而且服务器希望能够讲清楚为何请求不能被执行,就应该在实体内描述拒绝的原因。当然服务器也可以返回一个404 响应,假如它不希望让客户端获得任何信息。
    • 404 Not Found
      请求失败,请求所希望得到的资源未在服务器上发现。没有信息能够告诉用户这个状况到底是暂时的还是永久的。假如服务器知道情况,应当使用 410 状态码来告知旧资源因为某些内部的配置机制问题,已经永久地不可用,而且没有任何可以跳转的地址。404 这个状态码被广泛应用丁当服务器不想揭示为何请求被拒绝,或者没有其他适合的响应可用的情况下。
    • 405 Method Not Allowed
      请求行中指定的请求方法不能被用于请求相应的资源。该响应必须返回一个 Alow 头信息,用以表示出当前资源能够接受的请求方法的列表。
      鉴于 PUT,DELETE 方法会对服务器上的资源进行写操作,因而绝大部分的网页服务器都不支持或在默认配置下不支持上述请求方法,对于此类请求均会返回 405 错误。
    • 406 Not Acceptable
      请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体。除非这是一个 HEAD 请求,否则该响应就应当返回一个包含可以让用户或浏览器从中选择最合适的实体特性及地址列表的实体。实体的格式由 Content-Type 头中定义的媒体类型决定。
    • 408 Request Timeout
      请求超时。客户端没有在服务器预备等待的时间内完成一个请求的发送。客户端可以随时再次提交这一请求而无须进行任何更改。
    • 410 Gone
      被请求的资源在服务器上已经不再可用,而且没有任何已知的转发地址。这样的状况应当被认为是永久性的。如果可能,拥有链接编辑功能的客户端应当在获得用户许可后删除所有指向这个地址的引用。如果服务器不知道或无法确定这个状况是否是永久的,就应该使用 404 状态码除非额外说明,否则这个响应是可缓存的。
      410 响应的目的主要是帮助网站管理员维护网站,通知用户该资源已经不再可用,并且服务器拥有者希望所有指向这个资源的远端连接也被删除。这类事件在限时、增值服务中很普遍。同样,410 响应也被用于通知客户端在当前服务器站点上,原本属于某个个人的资源已经不再可用当然,是否要把所有永久不可用的资源标记为410 Gone,以及是否要保持此标记多长时间,完全取决于服务器拥有者。
    • 411 Length Required
      服务器拒绝在没有定义 Content-Length 头的情况下接受请求。在添加了表明请求消息体长度的有效 Content-Length 头之后,客户端可以再次提交该请求。
    • 413 Request Entity Too Large
      服务器拒绝处理当前请求,因为该请求提交的实体数据大小超过了服务器愿意或能够处理的范围。此种情况下,服务器可以关闭连接以免客户端继续发送此请求
      如果这个状况是临时的,服务器应当返回一个 Retry-After 的响应头,以告知客户端可以在多少时间以后重新尝试。
    • 416 Requested Range Not Satisfiable
      如果请求中包含了 Range 请求头,并且 Range 中指定的任何数据范围都与当前资源的可用范围不重合,同时请求中又没有定义 if-Range 请求头,那么服务器就应当返回416状态码。
      假如 Range 使用的是字节范围,那么这种情况就是指请求指定的所有数据范围的首字节位置都超过了当前资源的长度。服务器也应当在返回416 状态码的同时,包含一个 Content-Range实体头,用以指明当前资源的长度。这个响应也被禁止使用 multipart/byteranges 作为其Content-Type.
    • 500 Internal Server Error
      服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器的程序码出错时出现。
    • 501 Not Implemented
      服务器不支持当前请求所需要的某个功能。当服务器无法识别请求的方法,并且无法支持其对任何资源的请求时。
    • 502 Bad Gateway
      作为网关或代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应
    • 503 Service Unavailable
      由于临时的服务器维护或过载,服务器当前无法处理请求。这个状况是临时的,并且将在一段时间以后恢复。如果能够预计延迟时间,那么响应中可以包含一个 Retry-After 头用以标明这个延迟时间。如果没有给出这个 Retry-After 信息,那么客户端应当以处理500 响应的方式处理它。注意:503 状态码的存在并不意味着服务器在过载的时候必须使用它。某些服务器只不过是希望拒绝客户端的连接
    • 504 Gateway Timeout
      作为网关或代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTPFTP、LDAP)或辅助服务器(例如DNS)收到响应。
      注意:某些代理服务器在DNS查询超时时会返回400或500错误。

2.4 rewrite指令

语法: rewrite regex replacement flag
默认值: none
使用环境: server、location、if

  • 该指令根据表达式来重定向 URI,或者修改字符串。指令根据配置文件中的顺序来执行。
    注意重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句,代码如下:

    if($host ~* www\.(.*)){
    	set $host_without_www $1;
    	rewrite ^(*)$ http://$host_without_wwwsl permanent;
        # $1 contains '/foo',not' www.mydomain.com/foo!
    }
    
  • 如果替换串以http://开头,将会采用301或302跳转进行URL重定向。rewrite指令的最后一项参数为flag标记,支持的flag标记有:

    • last 相当于Apache里的[L]标记,表示完成rewrite;
    • break 本条规则匹配完成后,终止匹配,不再匹配后面的规则
    • redirect 返回302临时重定向,浏览器地址栏会显示跳转后的URL地址
    • permanent 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址。

    在以上的标记中,last和break 用来实现URI重写,浏览器地址栏的URL地址不变,但在服务器端访问的路径发生了变化。redirect和permanent用来实现URL跳转,浏览器地址栏会显示跳转后的URL地址。
    last和break 标记的实现功能类似,但二者之间有细微的差别,使用alias 指令时必须用 last标记,使用proxy_pass指令时要使用break标记。last标记在本条rewrite规则执行完毕后,会对其所在的server{...}标签重新发起请求,而 break 标记则在本条规则匹配完成后,终止匹配,不再匹配后面的规则。例如以下这段规则,就必须使用 break 标记,使用 last 标记会导致死循环

location /cms/ {
    proxy_pass http://testyourdomain.com;
    rewrite “^/cms/(.*)\.html$" /cms/index.html break;
}

因此,一般在根 location 中或直接在 server 标签中编写 rewrite 规则推荐使用 last 标记,在非根 location 中,则使用 brea 标记。

rewrite ^(/download/.*)/media/(.*)\..*S $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*S $1/mp3/$2.ra last;
return403

location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  break;
}

如果被替换的 URI中含有参数 (即类似/app/test.php?id=5 之类的URI),默认情况下参数会被自动附加到替换串上,你可以通过在替换串的末尾加上?标记来解决这一问题。

rewrite  ^/users/(.*)$ /show?user=$1? last;

不加 ?标记和加上?标记的 URL跳转区别:

rewrite  ^/test(.*)$ http://www.yourdomain.com/home? permanent;

访问 http://www.yourdomain.com/test?id=5 经过301 跳转后的 URL地址为 http://www.yourdomain.com/home
注:对花括号({ 和})来说,它们既能用在重定向的正则表达式里,也能用在配置文件里分割代码块,为了避免冲突,正则表达式里如果带花括号,应该用双引号(或者单引号)包围。比如,要将类似以下的URL:
/photos/123456重定向到:/path/to/photos/12/1234/123456.png可以用以下方法 (注意双引号) :

rewrite "/photos/([0-9] {2}) ([0-9] {2})" /path/to/photos/$1/$1$2$3.png;

2.5 set指令

语法: set variable value
默认值: none
使用环境: server、location、if

  • 该指令用于定义一个变量,并给变量赋值。变量的值可以为文本、变量及文本变量的联合。示例如下:
    set $varname 'hello';

2.6 uninitialized_variable_warn 指令

语法:uninitialized_variable_warn on|off
默认值:uninitialized_variable_warn on
使用环境: http、server、location、if

  • 该指令用于开启或关闭记录关于未初始化变量的警告信息,默认值为开启。

2.7 rewrite全局变量

$args
$content_length
Scontent_type
$document_root
$document_uri
Shost
$http_user_agent
$http_cookie
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
Sremote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
Sserver_name
Sserver_port
Suri

3 正则表达式语法

字符 描述
\ 将下一个字符标记为一个特殊字符,或一个原义字符,或一个向后引用,或一个八进制转义符。例如,\n匹配一个换行符。序列\\匹配\\(则匹配(
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^也匹配\n\r之后的位置
$ 匹配输入字符串的结束位置。如果设置了 RegExp 对象的 Multiline 属性,$也匹配\n\r之前的位置
* 匹配前面的子表达式零次或多次。例如,zo*能匹配zZoo*等价于
+ 匹配前面的子表达式一次或多次。例如,zo+能匹配zozoo,但不能匹配z+等价于
? 匹配前面的子表达式零次或一次。例如,do(es)?可以匹配dodoes中的do。?等价于{0,1)
? 当该字符紧跟在任何一个其他限制符(*,+,?,{n),{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串ooooo+?将匹配单个o,而o+将匹配所有o
n是一个非负整数。匹配确定的n次。例如,o{2)不能匹配Bob中的o,但是能匹配food中的两个0
n是一个非负整数。至少匹配n次。例如,o{2,}”不能匹配Bo中的o,但能匹配fooood中的所有oo{1,}等价于o+o{0,)则等价于o*
m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,o{1,3}将匹配“fooooood”中的前三个 oo{0,1}等价于o?。请注意在逗号和两个数之间不能有空格
. 匹配除\n之外的任何单个字符。要匹配包括\n在内的任何字符,请使用像[.\n]的模式
(pattern) 匹配 patter 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在 VBScript中使用 SubMatches 集合,在JScript 中则使用S0...S9 属性。要匹配圆括号字符,请使用\(或者\)
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用字符`(
?=pattern) 正向预查,在任何匹配 patterm 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配无须获取供以后使用。例如`Windows(?=95
(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配无须获取供以后使用。例如`Windows(?!95
x|y 匹配xy。例如,`z
[xyz] 字符集合。匹配所包含的任意一个字符。例如,[abc]可以匹配plain中的a
[^xyz] 负值字符集合。匹配未包含的任意字符。例如,[^abc]可以匹配plain中的p
[a-z] 字符范围。匹配指定范围内的任意字符。例如,[a-z]可以匹配a2范围内的任意小写字母字符
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,[^a-z]可以匹配任何不在az范围内的任意字符
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如,er\b可以匹配never中的er,但不能匹配verb中的er
\B 匹配非单词边界。er\B能匹配yerb中的er,但不能匹配never中的er
\cx 匹配由x指明的控制字符。例如,\cM 匹配一个Control-M 或回车符。x的值必须为 A-Za-z之一。否则,将c视为一个原义的c字符
\d 匹配一-个数字字符。等价于[0-9]
\D 匹配一个非数字字符。等价于[^0-9]
\f 匹配一个换页符。等价于\xOc \cL
\n 匹配一个换行符。等价于\xOa\cJ
\r 匹配一个回车符。等价于\xOd\cM
\s 匹配任何空白字符,包括空格、制表符、换页符等。等价于[\f\n\r\t\v]
\S 匹配任何非空白字符。等价于[^\f\n\r\t\v]
\t 匹配一个制表符。等价于\x09\cI
\v 匹配一个垂直制表符。等价于\xOb\cK
\w 匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]
\W 匹配任何非单词字符。等价于[^A-Za-z0-9_]
\xn 匹配 n, 其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,x41匹配Ax041则等价于x04&1。正则表达式中可以使用 ASCI编码
\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,(.)1匹配两个连续的相同字符
\n 标识一个八进制转义值或一个向后引用。如果\n 之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0~7),则n为一个八进制转义值
\nm 标识一个八进制转义值或一个向后引用。如果\nm 之前至少有 nm 个获取的子表达式,则 nm为向后引用。如果\nm之前至少有 n个获取的子表达式,则n为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若n和m 均为八进制数字(0~7),则nm 将匹配八进制转义值 nm
\nml 如果n为八进制数字(0~3),且m 和1均为八进制数字(0~7),则匹配八进制转义值 nml
\un 匹配 n,其中n是一个用4个十六进制数字表示的 Unicode 字符。例如,\u00A9 匹配版权符号(©)

标签:字符,15,请求,匹配,URL,rewrite,nginx,服务器
From: https://www.cnblogs.com/ccblblog/p/17968265

相关文章

  • Nginx转发解析长域名多路径域名
    Nginx解析短域名,例如:访问http://192.168.1.23可直接跳转到http://192.168.1.23/webroot/decisionserver{listen90;server_namelocalhost;#匹配/转到/webroot/decision上;#^(.*)$表示/后任意部分,除非和其他location匹配否则一律转向/webroot/decisio......
  • argo-rollout使用--金丝雀结合ingress-nginx
    1.金丝雀发布流程,安装比例发布,又名灰度发布举例:共10pod第一批发布30%V1:10个PodV2:3个Pod第二批发布60%V1:10个PodV2:6个Pod第三批发布100%V1:10个PodV2:10个Pod第四批发布V2:10个Pod(active)V1:0个Pod 2.资源文件准备文......
  • nginx如何搭建集群
    搭建Nginx集群的主要目的是为了提高网站的可用性、负载均衡以及处理高并发请求。以下是一个简化的步骤,说明如何搭建一个基本的Nginx服务集群:基本Nginx集群搭建步骤:硬件与环境准备:准备多台服务器(例如,server1, server2,...),确保它们都安装了Linux或类Unix操作系统。保证所有服务器......
  • 14、nginx设置浏览器缓存
    1.设置expire头浏览器缓存可以通过expires指令输出Header头来实现,expires指令的语法如下:语法:expires[time|epoch|max|off]默认值:expiresoff作用域:http、server、location用途:使用本指令可以控制HTTP应答中的Expires和Cache-Control的Header头信息(起到......
  • Nginx开启IPv6端口监听
    一、场景:在IPv6的改造过程中,使用Nginx进行IPv6反向代理IPv4的业务系统。二、 NginX配置#定义一个服务器块,监听7777端口,并启用SSL(HTTPS)支持server{  #监听所有IPv4和IPv6的7777端口  listen   7777ssl;  listen[::]:7777;  #设置只能通过域......
  • 15指向成员变量和成员方法的指针
    指向成员变量和成员方法的指针指向成员变量的指针classTest{public: intma; staticintmb;};intTest::mb;intmain(){//类对象的成员变量指针不是普通的指针,需要加入类名限定符//类的静态成员变量指针不针对某一个特定对象,使用普通指针 int*p=&Tes......
  • 微软用Yarp取代了`Nginx`吞吐量提升了百分之八十!
    先来看一张图:Azure应用服务用YARP取代了Nginx,获得了80%以上的吞吐量。他们每天处理160B多个请求(1.9mRPS)。这是微软的一项了不起的技术创新。首先我们来介绍一下什么是YarpYarp是什么?YARP(YetAnotherReverseProxy)是一个开源的、高性能的反向代理库,由Microsoft开发,使用C......
  • 《c++dll篇》VS2015生成dll及调用
    VS2015生成dll及调用原文链接:https://blog.csdn.net/qq_20792765/article/details/109801411创建DLL文件创建的DLL文件包括三个文件(.h/.dll/.lib),1、打开VS新建一个项目。2、选择DLL,附加选项选择空项目3、在头文件和源文件下分别添加如下文件4、在头文件CaculatorDLL.h......
  • 每日总结2024/1/15(爬虫学习)
    原文链接python爬虫-Python3.x+Fiddler抓取APP数据-学习分享-SegmentFault思否我爬取的为浏览器数据  可以看到在这里我们成功爬取到了浏览器数据,但是在实现python中爬取数据遇到了很多版本以及配置缺少的问题,同时我的版本中http为2,不知道有没有其他影响,代码目前......
  • 1月15日总结
    好呀,我是歪歪。Spring的事件监听机制,不知道你有没有用过,实际开发过程中用来进行代码解耦简直不要太爽。但是我最近碰到了一个涉及到泛型的场景,常规套路下,在这个场景中使用该机制看起来会很傻,但是最终了解到Spring有一个优雅的解决方案,然后去了解了一下,感觉有点意思。和你一......