对给定的条件(condition)进行判断,如果条件为真,大括号内的rewrite指令将被执行。

条件(conditon)可以是如下任何操作:

1. 当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false;

2. 使用“=”和“!=”比较一个变量和字符串;

3. 使用“~”做正则表达式匹配,“~*”做不区分大小写的正则匹配,“!~”做区分大小写的正则不匹配;

4. 使用“-f”和“!-f” 检查一个文件是否存在;

5. 使用“-d”和“!-d”检查一个目录是否存在;

6. 使用“-e”和“!-e”检查一个文件、目录、符号链接是否存在;

7. 使用“-x”和“ !-x”检查一个文件是否可执行;

如下示例:

/ /如果 UA包含 "MSIE", rewrite请求到 / msid /目录下
if ( $http_user_agent ~ MSIE ) {
rewrite ^ ( . * ) $ / msie / $ 1 break ;
/ /如果 cookie匹配正则,设置变量 $id等于正则引用部分
if ( $http_cookie ~ * "id=([^;]+)(?:;|$)" ) {
set $id $ 1 ;
/ /给某个访问 IP返回 403
if ( $remote_addr = "202\.38\.78\.85" ) {
return 403 ;
/ /如果提交方法为 POST,则返回状态 405( Method not allowed)。 return不能返回 301 , 302
if ( $request_method = POST ) {
return 405 ;
/ /如果 $slow可以通过 set指令设置,则进行限速处理
if ( $slow ) {
limit _rate 10k ;
/ /如果请求的文件名不存在,则反向代理到 localhost 。这里的 break也是停止 rewrite检查
if ( ! - f $request_filename ) {
break ;
proxy_pass http : / / 127.0.0.1 ;
/ /如果 query string中包含 "post=140",则永久重定向到 example .com
if ( $args ~ post = 140 ) {
rewrite ^ http : / / example .com / permanent ;
/ /防盗链
location ~ * \ . ( gif | jpg | png | swf | flv ) $ {
valid_referers none blocked www .baidu .com www .ywnds .com ;
if ( $invalid_referer ) {
return 404 ;

停止处理并为客户端返回状态码,非标准的444状态码将关闭连接,不发送任何响应头。可以使用的状态码有:204,400,402-406,408,410, 411, 413, 416与500-504。如果状态码附带文字段落,该文本将被放置在响应主体。相反,如果状态码后面是一个URL,该URL将成为location头部值。没有状态码的URL将被视为一个302状态码。

4)rewrite

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

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

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

1)处理在server级别中定义的模块指令;

2)为请求查找location;

3)处理在选中的location中定义的模块指令,如果指令改变了URI,按新的URI查找location。这个循环至多重复10次,之后nginx返回错误500 (Internal Server Error);

如果一个URI匹配了rewrite指令指定的正则表达式(regex),则URI就按照replacement进行重写,而rewrite按配置文件中出现的顺序执行。其中flag标志可以停止继续处理。如果replacement以”http://”或”https://”开始,将不再继续处理,那么这个重定向将直接返回给客户端。

flag可以是如下参数:

  • last,完成该rewrite规则的执行后,停止处理后续rewrite指令集;然后查找匹配改变后URI的新location;
  • break,完成该rewrite规则的执行后,停止处理后续rewrite指令集,并不再重新查找;但是当前location内剩余非rewrite语句和location外的的非rewrite语句可以执行;
  • redirect,返回302临时重定向,地址栏会显示跳转后的地址;
  • permanent,返回301永久重定向,地址栏会显示跳转后的地址;即表示如果客户端不清理浏览器缓存,那么返回的结果将永久保存在客户端浏览器中了。
  • 因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。这里last和break区别有点难以理解:

    1)last一般写在server和if中,而break一般使用在location中;

    2)last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配;

    3)break和last都能组织继续执行后面的rewrite指令。

    server {
    . . .
    rewrite ^ ( / download / . * ) / media / ( . * ) . . * $ $ 1 / mp3 / $ 2.mp3 last ;
    rewrite ^ ( / download / . * ) / audio / ( . * ) . . * $ $ 1 / mp3 / $ 2.ra last ;
    return 403 ;
    . . .
    location / download / {
    rewrite ^ ( / download / . * ) / media / ( . * ) . . * $ $ 1 / mp3 / $ 2.mp3 break ;
    rewrite ^ ( / download / . * ) / audio / ( . * ) . . * $ $ 1 / mp3 / $ 2.ra break ;
    return 403 ;
    Syntax : uninitialized_variable_warn on | off ;
    Default : uninitialized_variable_warn on ;
    Context : http , server , location , if

    $1是两个小写字母组成的字符串,$2是由小写字母和0到9的数字组成的5个字符的字符串,$3将是个文件名,$4是png、jpg、gif中的其中一个。

    第二部分:重写规则的第二部分是URI

    当重写规则第一部分被匹配到了之后,则请求被改写,那么该URI可能包含正则表达式中的捕获的位置参数或这个级别下的nginx任何配置变量。如:

    如果这个URI不匹配nginx配置的任何location,那么将给客户端返回301(永久重定向)或302(临时重定向)的状态码来表示重定向类型。该状态码可以通过第三个参数来明确指定。

    第三部分:重写规则的第三部分就是标记(flag)

    第三部分也就是尾部的标记(flag), last标记将导致重写后的URI搜索匹配nginx的其他location,最多可循环10次。如:

    $args #这个变量等于请求行中的参数,同$query_string;
    $content_length #请求头中的Content-length字段;
    $content_type #请求头中的Content-Type字段;
    $document_root #当前请求在root指令中指定的值,如:root /var/www/html;
    $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相同,例:http://localhost:88/test1/test2/test.php;
    $host: localhost
    $server_port: 88
    $request_uri: http : / / localhost : 88 / test1 / test2 / test .php
    $document_uri: / test1 / test2 / test .php
    $document_root: / var / www / html
    $request_filename: / var / www / html / test1 / test2 / test .php

    3)使用rewrite模块禁止用户代理

    Nginx可以通过各种方式来限制访问,例如NGINX基本Http认证、allow/deny等等,这些都是前文提过的,下面来看看nginx如何通过用户代理来禁止访问。

    user agent是什么?

    简单来说告诉服务器你当前使用的是什么浏览器、工具等来访问我的。例如火狐、chrome、wget、curl等浏览器或工具。使用$http_user_agent变量就可以获取到用户代理,一般在定义日志格式时都会使用这个变量,把用户代理记录到日志中去。

    如何禁止特定UA?

    我们不希望被使用wget或者curl来下载我的文件,怎么做呢?这里就可以使用rewrite模块了,编辑nginx配置文件,以下内容放在http配置段,那么整个nginx都生效。如果放到server里,那么一个域名生效,你放哪,哪就有效!