nginx服务器的rewrite功能

时间:2020-12-12 05:25:02

nginx编译的时候默认是把rewrite功能编辑进去的,但是因为rewrite需要使用正则表达式,因此需要安装pcre依赖包。

yum install -y pcre pcre-install

rewrite是nginx服务器提供的一个重要基本功能,其再web服务器产品中几乎是必备的,用于实现URL的重写。URL重写是非常有用的功能,比如它可以让我们在改变网站结构后,不需要要求客户端用户修改原来的书签,业无需其他网站修改对我们网站的友情链接;它还可以在一定程度上提高网站的安全性。

地址重定向与地址转发

地址重定向:是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL。比如在浏览器输入baidu.com时,浏览器会自动跳到https://www.baidu.com这个过程,就是一个地址重定向。我们输入的是baidu.com,但是浏览器显示的URL是服务器返回的一个新的URL地址。

地址转发:是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,因为这个跳转过程实在服务器实现的,并不是在客户端实现的所以客户端并不知道这个跳转动作,所以它的地址栏还是原来的地址。

转发是服务器行为,重定向是客户端行为。

地址重定向与地址转发的异同:

  • 地址转发后,客户端浏览器中地址栏显示是不改变的;而地址重写后客户端地址浏览器地址栏中地址改变为服务器选择确定的地址。
  • 在一次地址转发过程中,客户端只产生一次网络请求;而一次地址重写一般会产生两次网络请求。
  • 地址转发一般发生在同一站点内;地址重定向没有限制。
  • 地址转发到的页面可以不用全路径名表示,而地址重写到的页面必须使用完整的路径名表示。
  • 地址转发过程中,可以将客户端请求request范围内属性传递给新的页面,但地址重定向不可以。
  • 地址转发要比地址重定向快。

https://www.cnblogs.com/he-px/p/7448603.html 这片博文说明了地址转发与地址重定向的一些解释!

rewrite规则

rewrite规则是学习和使用nginx服务器rewrite功能的基础,可以借助于pcre实现uri的重定向,并且它还支持nginx预设变量。

废话不说,来介绍有关rewrite的指令:

if指令

该指令用来支持条件判断,并根据条件判断的结果选择不同的nginx配置,可以在server块或者location块中配置该指令。

if (condition) {....}
#花括号代表一个作用域,形成一个if块,是条件为真时的nginx配置。condition为判断条件,有以下几种写法。
  • 变量名。如果变量的值为空字符串或者以“0”开头的任意字符串,if指令认为条件为false,其他条件为true:
            if ($document_uri) {
return http://10.0.102.204$document_uri;
}
#如果请求中有uri,则返回一个指定的url;事实上所有发往本机的请求都会返回这个url,因为http://localhost也是含有一个URI的,可省略的“/”;测试的时候是这样
  • 使用“=”和“!=”比较变量和字符串是否相等,相等时if指令认为条件为true,反之为false。
           if ($remote_addr = 172.16.100.19)
{
return ;
}
#若是客户端ip为172.16.100.19,则禁止访问,返回403代码。
#需要注意的是这里的字符串不需要加引号!
  • 使用正则表达式对变量进行匹配,成功为true,否则为false。变量与正则表达式之间用"~","~*","!~"或"!~*"连接。
    • ~:表示匹配过程中对大小写敏感。
    • ~*:匹配过程中对大小写不敏感。
    • !~和!~*: 前面的感叹号表示匹配失败时结果为true,否则为false。

在正则表达式中,可以使用小括号对变量进行截取,在花括号中引用$1....$9引用截取的值。

           if ($remote_addr ~ 10.0..*)
{
return ;
}
#以上102网段的所有机器均不能访问。
#使用小括号对正则表达式的截取,遇见的话补上,可以类比Python中正则截取,规则都一样!
  • 判断文件是否存在用-f,判断目录是否存在用-d,判断请求的目录或者文件是否存在用-e,判断请求的文件是否有可执行权限用-x;以上的判断存在则条件为真,若是在前面加上"!"则表示非的意思!
        location  /one.html {
if (-f $request_filename)
{
return http://10.0.102.204$document_uri;
}
#若是请求的文件存在,则转向另一个网址发起请求。这里request_filename变量是文件在服务器上的绝对路径。
#譬如这里,因为root路径默认是/usr/local/nginx/html,因此request_filename的路径为/usr/local/nginx/html/one.html.

break指令与return指令

  • break指令用于中断当前同一作用域中的nginx配置。与该指令处于同一作用域的nginx配置中,位于它前面的指令配置生效,位于后面的指令配置无效。nginx服务器在根据配置处理请求的过程中遇到该指令时,回到上一层作用域继续向下读取配置。可以用作server块和location块。
location  /  {
if ($slow) {
set $id $1 #处于break之前,配置有效
break;
limit_rete 100k; #处于break指令之后,配置无效
}
..... #其他nginx配置指令,处于break作用域的上一层,配置有效
}
  • return指令,该指令用于完成对请求的处理,直接向客户端返回响应的状态码。处于该指令后所有的nginx配置指令无效。可以在server块和if块中使用。
return  [text];
return code URL;
return URL; #code,返回给客户端的状态码。可以返回的状态码为0~999的任意http状态码。非标准的444状态码可以强制关闭服务端与客户端的连接而不返回任何响应信息。
#text,为返回给客户端的响应具体内容,支持变量的使用。
#URL,返回给客户端URL地址。 code的几种状态说明:
301: 表示被请求资源永久移动到新的位置。
302:表示临时重定向,要求使用GET请求。
303:表对当前请求的响应可以在另一个URL上找到,并且客户端当采用GET方式访问那个资源。
307:请求的资源临时从不同的URL响应。

return指令的用法,在上面if语句中已经使用,不再说明。

rewrite指令

该指令通过正则表达式的使用来改变URI。可以同时存在一个或者多个,安装顺序依次对URI进行匹配和处理。

该指令可以在server块或者Location块中配置,其语法结构为:

rewrite  regex replacement  [flag];

#regx,用于匹配URI的正则表达式。使用括号标记要截取的内容。
#replacement,匹配成功后用于替换uri中被截取内容的字符串。默认情况下,如果该字符串是由"http://"或者"hppts://"开头的,则不会继续向下对uri进行处理,而直接将重写后的URI返回给客户端。
#flag,用来设置rewrite对URI的处理行为,可以为以下标记中的一个。
  • last,终止继续在本Location块中处理接收到的URI,并将重写的URI作为一个新的URI,使用各Location块进行处理。该标志将重写后的URI重新在server块中执行,为重写后的URI提供了转入到其他Location块的机会。
  • break,将此处重写的URI作为一个新的URI,在本块中继续执行。但是不会将新的URI转向到其他Location块。
  • redirect,将重写后的URI返回给客户端,状态码为302,指明是临时重定向URI,主要用在replacement变量不是以"http://"和"hpps://"开头的情况下。
  • permanent,将重写后的URI返回给客户端,状态码为301,指明是永久重定向。

需要特别注意rewrite接收到的uri不包含host地址。因此regex不可能匹配到uri的host地址。

另外客户端使用get发起请求时,请求后面的参数指令也不包含在rewrite指令接受到的内容中。但是若想在replacement中引用参数,可以使用nginx全局变量$requext_uri,但是在使用的时候需要加上一个"?".

rewrite     regex       http://wwww.xxx.com$requext_uri? permanect;

rewrite_log指令

该指令配置是否开启URL重写日志输出功能,其语法结构为:

rewirte_log  on | off;

默认设置为off。如果配置开启,url重写日志将以notice级别输出到error_log指令配置的日志文件中。

set指令

该指令用于设置一个新的变量。

set  variable value;

#variable,为变量名称。注意要用符号$作为变量的第一个字符,变量不能与nginx服务器预设的全局变量同名。
#value,为变量的值,可以使字符串,其他变量或变量的组合等

uninitialized_variable_warn指令

该指令用于配置使用未初始化的变量时,是否记录警告日志。

uninitialized_variable_warn  on | off;
默认设置开启状态。

nginx服务器预设的全局变量如下,可能不太全。

变量     说明
$args     存放了请求url中的请求指令。比如http://www.myweb.name/server/source?arg1=value1&arg2=value2中的arg1=value1&arg2=value2
$content_length     存放请求头中的Content-length字段
$content_type     存放了请求头中的Content-type字段
$document_root     存放了针对当前请求的根路径
$document_uri     请求中的uri,不包含请求指令 ,比如比如http://www.myweb.name/server/source?arg1=value1&arg2=value2中的/server/source
$host     存放了请求url中的主机字段,比如比如http://www.myweb.name/server/source?arg1=value1&arg2=value2中的www.myweb.name。如果请求中的主机部分字段不可用或者为空,则存放nginx配置中该server块中server_name指令的配置值
$http_user_agent     存放客户端的代理
$http_cookie     cookie
$limit_rate     nginx配置中limit_rate指令的配置值
$remote_addr     客户端的地址
$remote_port     客户端与服务器端建立连接的端口号
$remote_user     变量中存放了客户端的用户名
$request_body_file     存放了发给后端服务器的本地文件资源的名称
$request_method     存放了客户端的请求方式,如get,post等
$request_filename     存放当前请求的资源文件的路径名
$requset_uri     当前请求的uri,并且带有指令
$query_string     $args含义相同
$scheme     客户端请求使用的协议,如http,https,ftp等
$server_protocol     客户端请求协议的版本,如”HTTP/1.0”,”HTTP/1.1”
$server_addr     服务器的地址
$server_name     客户端请求到达的服务器的名称
$server_port     客户端请求到达的服务器的端口号
$uri     同 $document_uri