Nginx服务器的Rewrite功能(一)

2017-12-07 01:28:54

Rewrite功能的配置
  • Rewrite是Nginx服务器提供的一个重要的基本功能,其在Web服务器产品中几乎是必备的功能。用于实现URL的重写。URL重写是非常有用的功能,比如它可以让我们在改变网站结构后,无需要求客户端用户修改原来的书签,也无需其他网站修改对我们网站的友情链接;它可以在一定程度上提高网站的安全性;能够让我们的网站显得更加专业。适当的利用Rewrite功能,可以给我们带来很多好处。

地址重写与地址转发

  • 地址重写与转发在计算机网络领域是两个重要概念,经常被大家提起。但许多人对这两个概念的区别并不清楚,甚至混为一谈。在学习Nginx服务器的Rewrite功能之前,我们有必要先将这对概念进行一下分析和对比,让大家能够有一个清晰的认识。
  • 地址重写,实际上是为了实现地址标准化。那么,什么是地址标准化呢?我们来举一个例子。比如在访问Google首页的时候,我们在地址栏输入 www.google.com , 也可以输入google.cn,它们都能准确的指向Google首页,从客户端来看,Google头面同时对应了两个地址,实际上,Google服务器是在不同的地址中选择了确定的一个,即www.google.com ,进而返回服务器响应的。这个过程就是地址标准化的过程。google.cn这个地址在服务器中被 改变为www.google.com 的过程就是地址重定向的过程。
  • 转发的概念最初和网页的访问并没有太大的关系,它是指在网络数据传输过程中数据分组到达路由器或者桥接器后该设备通过检查分组地址并将数据转到相邻局域网上的过程。后来该概念被 用在网页访问中,出现了地址转发的说法。地址转发,是指将一个域名指到另一个已有站点的过程。
  • 从上面的解释,我们可以看到地址重写和地址转发代表的两个过程是不同的。我们可以总结这两个过程的几点区别:
  1. 地址转发后客户端浏览器地址栏中的地址显示是不改变的;而地址重写后客户端浏览器地址栏中的地址改变为服务 器选择确定的地址。
  2. 在一次地址转发整个过程中只产生一次网络请求;而一次地址重写一般会产生两次请求。
  3. 地址转发一般发生在同一站点项目内;而地址重写没有该 限制。
  4. 地址转发到的页面可以不用全路径名表示,而地址重写到的页面必须使用完整的路径名表示。
  5. 地址转发过程中,可以将客户端请求的request范围内属性传递给新的页面,但地址重写不可以。
  6. 地址转发的速度较地址重定向快。

Rewrite规则*

  • Rewrite规则是学习和Nginx服务器Rewrite功能的基础,可以借助Pcre实现URL重写,并且它还Nginx预设变量。Rewrite的核心 就是Pcre.
  • 正则表达式是用于描述或者匹配一系列符合句法和字符串的一个字符串。大家应该都使用过windows/dos平台下用于文件查找的通配符'*'和'?',如果要查找某个目录下所有的Word文档,就使用*.doc进行搜索,*会被解释成任意的字符串。和符类似,在很多文本编辑器或其它工具中,正则表达式通常可以被用来检索和替换符合某个句法模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。PCRE就是在PERL中内置的功能强大的正则表达式引擎,可以被许多工具使用的库。正则表达式有多种不同的风格,并且不同版本的对句法的匹配处理上也有一定的差异。
  • 在Nginx服务器中,使用ngx_http_rewrite_module模块支持URL重写功能。该模块是Nginx服务器的标准Http模块。

if指令*

  • 该指令用来支持条件判断,并根据条件判断结果选择不同的Nginx配置,可以在server块或location块中配置该指令,其语法结构为:
if(condition){....}
  • 其中,花括号代表一个作用域,形成一个if配置块,是条件为真时的Nginx配置。condition为判断条件(true/false),它可以支持以来几种设置方法。

变量名。如果变量的值 为空字符串或者以“0”开头的任意字符串,if指令认为条件为flase,其他情况认为条件为true,比如:

if($slow)
{
... #Nginx配置
}

使用"="(等于)和"!="(不等于)比较变量和字符串是否相等,相等时if指令认为条件为true.比如:

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

注意
这里的字符串不需要加引号

使用与正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则为false.变量与正则表达式之间用"~","~","!~"或"!~"连接,"~"表示匹配过程中对大小写敏感,"~"表示匹配过程中对大小写不敏感;使用"!~"和"!~",匹配失败时if指令认为条件为true,否则为false.在正则表达式中,可以使用小括号对变量进行截取,在花括号中作用$1...$9引用截取的值.比如:

if($http_user_agent ~ MSIE)
{
    #$http_user_agent 的值中是否含有MSIE字符串,如果包含,为true
}
if($http_cookie ~* "id=([^;]+)(?:;|$)")
{
    #Nginx配置,可以使用$1和$2获取截取到的值.如
    # set $id $1;将截取的id赋值给$id变量以备后用.
    ...
}

注意
整个正则表达式字符串一般不需要加引号,但如果含有右花括号"}"或者分号";"字符时,必须要给整个正则表达式添加引号

判断请求的文件是否存在使用"-f"和"!-f".当使用"-f"时,如果请求的文件存在,if指令认为条件为true,如果请求的文件不存在为false;使用"!-f"时,如果请求的文件不存在,则为false,如果请求的文件存在,也为false.使用方法如下:

if(-f $request_filename){
    #判断请求的文件是否存在
}
if(!-f $request_filename)
{
    #判断请求的文件是否不存在
}

判断请求的目录是否存在使用"-d"和"!-d".当使用"-d"时,如果请求的目录存在,if指令认为条件为true,如果请求的目录不存在,则为false;当使用"!-d"时,如果请求的目录不存在但该目录的上级目录存在,则为true,如果该目录和它的上级目录都不存在,则为false,如果请求的目录存在,也为false.使用方法见"-f"和"!-f"的使用.

判断请求的目录或者文件是否存在使用"-e"和"!-e".当使用"-e"时,如果请求的目录或者文件存在时,if指令认为条件为true,否则为false.当使用"!-e"时,如果请求的文件和该文件所在路径上的目录都不存在,为true,否则为false.使用方法见"-f"和"!-f"的使用

判断请求的文件是否可执行使用"-x"和"!-x".当使用"-x"时,如果请求的文件可执行,if指令认为条件为true,否则为false;当使用"!-x"时,如果请求的文件不可执行,为true否则为false.使用方法见"-f"和"!-f"的使用.

break指令

  • 该指令用于中断当前相当作用域中的其他Nginx配置.与该指令处于同一作用域的Nginx配置中位于它前面的指令配置生效,位于后面的指令配置无效.Nginx服务器在根据配置处理请求的过程中遇到该指令时,回到上一层作用域继续向下读取配置.该指令可以在server块和locatiuon块以及if块中使用,其语法结构为:
break;
  • 我们通过一个例子加深理解
location / {
    if($slow) {
        set $id $1    #处于break指令之前,配置有效
        break;
        limit_rate 10k; #处于break指令之后,配置无效
    }
    ...     #其他Nginx配置,处于break指令所在作用域的上一层作用域,配置有效
}

1. return 指定

  • 该指令用于完成请求的处理,直接向客户端返回响应状态代码.处于该指令后的所有Nginx配置都是无效的.该指令可以在server块和location块以及if块中使用,其语法结构有以下几种:
return [ text ]
return code URL;
return URL;

code,为返回给客户端的HTTP状态代码.可以返回的状态代码为0~999的任意HTTP状态代码.非标准的444代码可以强制关闭服务器与客户端的连接而不返回任何响应信息给客户端
text,为返回给客户端的响应体内容,支持变量的使用
URL,为返回给客户端的URL地址.

  • 从Nginx 0.8.42开始,当code使用301(表示被请求资源永久移动到新的位置),302(表示请求的资源现在临时从不同的URL响应,要求使用GET方式请求),303(表示对应当前请求的响应可以在另一个URL上找到,并且客户端应当采用GET方式文章那个资源)和307(请求的资源临时从不同的URL响应)代码时,可以使用结构2将新的URL返回给客户端;当code使用除上面提到 的其他代码时,可以使用结构1指定text向客户端发送指定的响应体内容.
  • 当返回状态代码为302或307时,可以使用结构3对url进行配置.返回的url中应该包含"http://","https://" 或者直接使用"$scheme"变量(Request Scheme,代表传输协议,Nginx内置变量)指定

注意

  • 在NGINX 0.7.51之前的版本中,只支持返回204,400,402~406,408,410,411,413,416和500~504等状态代码.