Nginx Rewrite 重写规则相关指令
2019-04-14 22:28:04 阿炯

重写(Rewrite)是通过Nginx的配置文件,以让网站的url中达到某种状态时则定向或跳转到某个规则,比如常见的伪静态、301重定向、浏览器定向等。

相关指令有if,rewrite,set,return,break等,其中最关键的就是rewrite。一个简单的Nginx Rewrite规则语法如下:
rewrite ^/f/(.*)\.html /show.php?video=$1 break;

指令执行顺序

首先顺序执行server块中的rewrite模块指令,得到rewrite后的请求URI。然后循环执行如下指令,如果没有遇到中断循环标志,此循环最多执行10次,但是我们可以使用break指令来中断rewrite后的新一轮的循环。

(1). 依据rewrite后的请求URI,匹配定义的 location 块。

(2). 顺序执行匹配到的 location 中的rewrite模块指令。

rewrite

ngx_http_rewrite_module 模块用来使用正则表达式(PCRE)改变请求的URI,返回重定向,并有条件地选择配置。

语法

在配置文件的server块中写,如:
server {
   rewrite 规则 定向路径 重写类型;
}

规则:可以是字符串或者正则来表示想匹配的目标url。
定向路径:表示匹配到规则后要定向的路径,如果规则里有正则,则可以使用$index来表示正则里的捕获分组。
重写类型:
    last :相当于Apache里德(L)标记,表示完成rewrite,浏览器地址栏URL地址不变
    break;本条规则匹配完成后,终止匹配,不再匹配后面的规则,浏览器地址栏URL地址不变
    redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址
    permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址


1.break指令

默认值:none ;使用环境:server,location,if ;

该指令的作用是完成当前的规则集,不再处理rewrite指令,但是其他模块指令是不受影响的。

示例
server {
    listen 8080;
    # 此处 break 会停止执行 server 块的 return 指令(return 指令属于rewrite模块)
    # 如果把它注释掉 则所有请求进来都返回 ok
    break;
    return 200 "ok";
    location = /testbreak {
        break;
        return 200 $request_uri;
        proxy_pass http://127.0.0.1:8080/other;
    }
    location / {
        return 200 $request_uri;
    }
}

# 发送请求如下
# curl 127.0.0.1:8080/testbreak
# /other

# 可以看到 返回 `/other` 而不是 `/testbreak`,说明 `proxy_pass` 指令还是被执行了
# 也就是说 其他模块的指令是不会被 break 中断执行的
# (proxy_pass是ngx_http_proxy_module的指令)

2.if指令

默认值:none ;使用环境:server,location

该指令用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句。If指令不支持嵌套,不支持多个条件&&和||处理。

if (表达式) {
}

if判断和内置全局环境变量


#当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false直接比较变量和内容时,使用=或!=~正则表达式匹配,~*不区分大小写的匹配,!~区分大小写的不匹配。if 中的几种判断条件:
1,一个变量名,如果变量 $variable 的值为空字符串或者字符串"0",则为false
2,变量与一个字符串的比较 相等为(=) 不相等为(!=) 注意此处不要把相等当做赋值语句,直接比较变量和内容。
3,变量与一个正则表达式的模式匹配 操作符可以是(~ 区分大小写的正则匹配, ~*不区分大小写的正则匹配, !~ !~*,前面两者的非)
4,检测文件是否存在 使用 -f(存在) 和 !-f(不存在)
5,检测路径是否存在 使用 -d(存在) 和 !-d(不存在) 后面判断可以是字符串也可是变量
6,检测文件、路径、或者链接文件是否存在 使用 -e(存在) 和 !-e(不存在) 后面判断可以是字符串也可是变量
7,检测文件是否为可执行文件 使用 -x(可执行) 和 !-x(不可执行) 后面判断可以是字符串也可是变量

注意:上面第1,2,3条被判断的必须是变量,4, 5, 6, 7则可以是变量也可是字符串。

set $variable "0";
if ($variable) {
    # 不会执行,因为 "0" 为 false
    break;            
}

# 使用变量与正则表达式匹配没有问题
if ( $http_host ~ "^star\.igrow\.cn$" ) {
    break;            
}

# 字符串与正则表达式匹配报错
if ( "star" ~ "^star\.igrow\.cn$" ) {
    break;            
}
# 检查文件类的字符串与变量均可
if ( !-f "/data.log" ) {
    break;            
}

if ( !-f $filename ) {
    break;            
}

# 如果文件不存在则返回400
if (!-f $request_filename) {
    return 400;
}

# 如果host不是xuexb.com,则301到xuexb.com中
if ( $host != 'xuexb.com' ){
    rewrite ^/(.*)$ https://xuexb.com/$1 permanent;
}

# 如果请求类型不是POST则返回405
if ($request_method = POST) {
    return 405;
}

# 如果参数中有 a=1 则301到指定域名
if ($args ~ a=1) {
    rewrite ^ http://example.com/ permanent;
}

在某种场景下可结合location规则来使用,如:
# 访问 /test.html 时
location = /test.html {
    # 默认值为freeoa
    set $name freeoa;
    # 如果参数中有 name=xx 则使用该值
    if ($args ~* name=(\w+?)(&|$)) {
        set $name $1;
    }
    # 301
    rewrite ^ /$name.html permanent;
}


/test.html => /freeoa.html
/test.html?name=ok => /ok.html?name=ok


一些高级的判断条件

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

B.变量比较可以使用"="(表示等于)和"!="(表示不等于)

C.正则表达式模式匹配可以使用"~*"和"~"符号

D."~"符号表示区分大小写字母的匹配

E."~*"符号表示不区分大小写字母的匹配

F."!~"和"!~*"符号的作用刚好和"~"、"~*"相反,表示不匹配

G."-f"和"!-f"用来判断文件是否存在

H."-d"和"!-d"用来判断目录是否存在

I."-e"和"!-e"用来判断文件或目录是否存在

J."-x"和"!-x"用来判断文件是否为可执行

K.部分正则表达式可以在()内,用$1~$9来访问

访问链接是:http://localhost:8080/test1/test2/test.psp
网站路径是:/var/www/html
$host:localhost
$server_port:8080
$request_uri:http://localhost:8080/test1/test2/test.psp
$document_uri:/test1/test2/test.psp
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.psp

3.return指令

语法:return code ;使用环境:server,location,if ;

该指令用于结束规则的执行并返回状态码给客户端。

return code [text];
return code URL;
return URL;

停止处理并将指定的code码返回给客户端,非标准code码 444 关闭连接而不发送响应报头。

从0.8.42版本开始,return 语句可以指定重定向 url (状态码可以为如下几种 301,302,303,307),也可以为其他状态码指定响应的文本内容,并且重定向的url和响应的文本可以包含变量。

有一种特殊情况,就是重定向的url可以指定为此服务器本地的urI,这样的话,nginx会依据请求的协议$scheme,server_name_in_redirect 和 port_in_redirect自动生成完整的 url (此处要说明的是 server_name_in_redirect 和 port_in_redirect 指令是表示是否将server块中的 server_name 和 listen 的端口作为redirect用 )。

# return code [text]; 返回 ok 给客户端
location = /ok {
    return 200 "ok";
}

# return code URL; 临时重定向到 百度
location = /redirect {
    return 302 http://www.baidu.com;
}

# return URL; 和上面一样默认也是临时重定向
location = /redirect {
    return http://www.baidu.com;
}

# 如果访问的URL以".sh"或".bash"结尾,则返回403状态码

location ~ .*\.(sh|bash)?$ {
return 403;
}

4.rewrite 指令

语法:rewrite regex replacement flag

默认值:none ; 使用环境:server,location,if

rewrite根据nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写和者重定向。rewrite和location类似,都可以实现跳转,区别是rewrite是在同一域名内更改url,而location是对同类型匹配路径做控制访问,或者proxy_pass代理到其他服务器。

rewrite和location执行顺序:
执行server下的rewrite
执行location匹配
执行location下的rewrite

语法和参数说明

rewrite语法格式
rewrite        <regex>        <replacement>        <flag>;
关键字        正则表达式         代替的内容         重写类型

Rewrite:一般都是rewrite
Regex:可以是字符串或者正则来表示想要匹配的目标URL
Replacement:将正则匹配的内容替换成replacement
Flag:flag标示,重写类型:
  - last:本条规则匹配完成后,继续向下匹配新的location URI规则;相当于Apache里德(L)标记,表示完成rewrite,浏览器地址栏URL地址不变;一般写在server和if中;
  - break:本条规则匹配完成后,终止匹配,不再匹配后面的规则,浏览器地址栏URL地址不变;一般使用在location中;
  - redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址;
  - permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址;


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

if( $host ~* www\.(.*) ){
set $host_without_www $1;
rewrite  ^(.*)$  http://$host_without_www$1 permanent;
}

rewrite 指令是使用指定的正则表达式regex来匹配请求的urI,如果匹配成功,则使用replacement更改URI。rewrite指令按照它们在配置文件中出现的顺序执行。可以使用flag标志来终止指令的进一步处理。如果替换字符串replacement以http://,https://或$scheme开头,则停止处理后续内容,并直接重定向返回给客户端。

第一种情况 重写的字符串带http://

location / {
    # 当匹配 正则表达式 /test1/(.*)时 请求将被临时重定向到 http://www.$1.com
    # 相当于 flag 写为 redirect
    rewrite /test1/(.*) http://www.$1.com;
    return 200 "ok";
}
# 在浏览器中输入 127.0.0.1:8080/test1/baidu
# 则临时重定向到 www.baidu.com
# 后面的 return 指令将没有机会执行了

第二种情况 重写的字符串不带http://

location / {
    rewrite /test1/(.*) www.$1.com;
    return 200 "ok";
}
# 发送请求如下
# curl 127.0.0.1:8080/test1/baidu
# ok

# 此处没有带http:// 所以只是简单的重写,请求的 uri 由 /test1/baidu 重写为 www.baidu.com
# 因为会顺序执行 rewrite 指令,所以下一步执行 return 指令响应了 ok

rewrite指令的最后一项参数为flag标记,支持flag标记有:

1.last 相当于apache里面的[L]标记,表示rewrite。停止处理当前的ngx_http_rewrite_module的指令集,并开始搜索与更改后的URI相匹配的location。

2.break本条规则匹配完成后,终止匹配,不再匹配后面的规则。停止处理当前的ngx_http_rewrite_module指令集,就像上面说的break指令一样。

3.redirect  返回302临时重定向,浏览器地址会显示跳转后的URL地址。

4.permanent  返回301永久重定向, 浏览器地址会显示跳转后的URL地址。

使用last和break实现URI重写,浏览器地址栏不变。而且两者有细微差别,使用alias指令必须用last标记;使用proxy_pass指令时,需要使用break标记。last标记在本条rewrite规则执行完毕后,会对其所在server{......}标签重新发起请求,而break标记则在本条规则匹配完成后,终止匹配。

一般在跟location中(location /{...})或直接在server标签中编写rewrite规则,推荐使用last标记;在非根location中(location /cms/{...}),则使用break。

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

示例:
rewrite ^/test(.*)$ http://www.freeoa.net/home  permanent;

访问 http://www.freeoa.net/test?id=5 会跳转到 http://www.freeoa.net/home?id=5

示例:如果我们将类似URL /photo/123456 重定向到 /path/to/photo/12/1234/123456.png

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

注:如果正则表达式里面有花括号"{"或"}" ,应该使用双引号或单引号。

# 没有rewrite 后面没有任何 flag 时就顺序执行
# 当 location 中没有 rewrite 模块指令可被执行时 就重写发起新一轮location匹配
location / {
    # 顺序执行如下两条rewrite指令
    rewrite ^/test1 /test2;
    rewrite ^/test2 /test3;  # 此处发起新一轮location匹配 uri为/test3
}

location = /test2 {
    return 200 "/test2";
}  

location = /test3 {
    return 200 "/test3";
}

# 发送如下请求
# curl 127.0.0.1:8080/test1
# /test3

server {
    # 访问 /last.html 的时候,页面内容重写到 /index.html 中
    rewrite /last.html /index.html last;
    # 访问 /break.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配
    rewrite /break.html /index.html break;
    # 访问 /redirect.html 的时候,页面直接302定向到 /index.html中
    rewrite /redirect.html /index.html redirect;
    # 访问 /permanent.html 的时候,页面直接301定向到 /index.html中
    rewrite /permanent.html /index.html permanent;
    # 把 /html/*.html => /post/*.html ,301定向
    rewrite ^/html/(.+?).html$ /post/$1.html permanent;
    # 把 /search/key => /search.html?keyword=key
    rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
}

last 与 break 的区别

last 和 break一样,它们都会终止此 location 中其他它rewrite模块指令的执行,但是 last 立即发起新一轮的 location 匹配而 break 则不会。因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。这里 last 和 break 区别有点难以理解:
    last一般写在server和if中,而break一般使用在location中
    last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
    break和last都能组织继续执行后面的rewrite指令

在location里一旦返回break则直接生效并停止后续的匹配location。

server {
    location / {
        rewrite /last/ /q.html last;
        rewrite /break/ /q.html break;
    }
    location = /q.html {
        return 400;
    }
}

访问/last/时重写到/q.html,然后使用新的uri再匹配,正好匹配到locatoin = /q.html然后返回了400
访问/break时重写到/q.html,由于返回了break,则直接停止了

location = /test3 {
    return 200 "/test3";
}
location = /test4 {
    return 200 "/test4";
}
# 发送如下请求
# curl 127.0.0.1:8080/test1
# /test3

当如果将上面的 location / 改成如下
location / {
    rewrite ^/test1 /test2;
    # 此处不会发起新一轮location匹配;当是会终止执行后续rewrite模块指令重写后的uri为 /more/index.html
    rewrite ^/test2 /more/index.html break;  
    rewrite /more/index\.html /test4; # 这条指令会被忽略

    # 因为 proxy_pass 不是rewrite模块的指令所以它不会被 break终止
    proxy_pass https://www.baidu.com;
}
# 发送如下请求
# 浏览器输入 127.0.0.1:8080/test1
# 代理到 百度产品大全页面 https://www.baidu.com/more/index.html;

上面的代码中即使将 proxy_pass 放在 带有 break 的 rewrite上面它也是会执行的,这里涉及到nginx的执行流程了,大家有兴趣可以了解下。

rewrite 后的请求参数

如果替换字符串replacement包含新的请求参数,则在它们之后附加先前的请求参数。如果你不想要之前的参数,则在替换字符串 replacement 的末尾放置一个问号,避免附加它们。

# 由于最后加了个 ?,原来的请求参数将不会被追加到rewrite之后的url后面
rewrite ^/users/(.*)$ /show?user=$1? last;

rewrite_log

Context: http, server, location, if

开启或者关闭 rewrite模块指令执行的日志,如果开启,则重写将记录下notice 等级的日志到nginx 的 error_log 中,默认为关闭 off。

Syntax: rewrite_log on | off;

再说完了rewrite里面的情况,现在来说一说与之相匹配关系最为密切的location。

在server块中使用,如:
server {
    location 表达式 {
    }
}

location表达式类型
如果直接写一个路径,则匹配该路径下的
    ~ 表示执行一个正则匹配,区分大小写
    ~* 表示执行一个正则匹配,不区分大小写
    ^~ 表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他location。
    = 进行普通字符精确匹配。也就是完全匹配。

优先级
    等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项。
    ^~类型表达式。一旦匹配成功,则不再查找其他匹配项。
    正则表达式类型(~ ~*)的优先级次之。如果有多个location的正则能匹配的话,则使用正则表达式最长的那个。
    常规字符串匹配类型。按前缀匹配。

示例:地址的伪装
server {
# 用 xx_admin 来掩饰 admin
location / {
    # 使用break拿一旦匹配成功则忽略后续location
    rewrite /xx_admin /admin break;
}
# 访问真实地址直接报没有权限
location /admin {
    return 403;
}
}

5.Set指令

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

该指令用于定义一个变量,并给变量赋值。变量的值可以为文本、变量以及文本变量的联合。

示例:set $varname "hello world";

location / {
    set $var1 "host is ";
    set $var2 $host;
    set $var3 " uri is $request_uri";
    return 200 "response ok $var1$var2$var3";
}
# 发送如下请求
# curl 127.0.0.1:8080/test
# response ok host is 127.0.0.1 uri is /test

6.Uninitialized_variable_warn指令

语法:uninitialized_variable_warn on|off

使用环境:http,server,location,if

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

至此 Nginx Rewrite 重写规则指令就介绍完毕了。

7.Nginx Rewrite可以用到的全局变量

$args ,$content_length ,$content_type ,$document_root ,$document_uri ,$host ,$http_user_agent ,$http_cookie ,$limit_rate ,$request_body_file ,$request_method ,$remote_addr ,$remote_port ,$remote_user ,$request_filename ,$request_uri ,$query_string ,$scheme ,$server_protocol ,$server_addr ,$server_name ,$server_port ,$uri

详情见 Nginx 内置全局变量

Nginx的Rewrite规则编写实例

1.当访问的文件和目录不存在时,重定向到某个php文件

if( !-e $request_filename ){
rewrite ^/(.*)$ index.php last;
}

2.目录对换 /123456/xxxx  ====>   /xxxx?id=123456

rewrite ^/(\d+)/(.+)/  /$2?id=$1 last;

3.如果客户端使用的是IE浏览器,则重定向到/ie目录下

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

4.禁止访问多个目录

location ~ ^/(cron|templates)/ {
deny all;
break;
}

5.禁止访问以/data开头的文件

location ~ ^/data {
deny all;
}

6.禁止访问以.sh,.flv,.mp3为文件后缀名的文件

location ~ .*\.(sh|flv|mp3)$ {
return 403;
}

7.设置某些类型文件的浏览器缓存时间

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
}
location ~ .*\.(js|css)$ {
expires 1h;
}

8.给favicon.ico和robots.txt设置过期时间

这里为favicon.ico为99天,robots.txt为7天并不记录404错误日志。

location ~(favicon.ico) {
log_not_found off;
expires 99d;
break;
}

location ~(robots.txt) {
log_not_found off;
expires 7d;
break;
}

9.设定某个文件的过期时间;这里为600秒,并不记录访问日志

location ^~ /html/scripts/loadhead_1.js {
access_log   off;
root /opt/lampp/htdocs/web;
expires 600;
break;
}

10.文件反盗链并设置过期时间
这里的return 412 为自定义的http状态码,默认为403,方便找出正确的盗链的请求
“rewrite ^/ http://img.freeoa.net/getout.gif;”显示一张防盗链图片
“access_log off;”不记录访问日志,减轻压力
“expires 3d”所有文件3天的浏览器缓存

location ~* ^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ {
valid_referers none blocked *.forbd.com *.forbd.net localhost 208.10.167.100;
if ($invalid_referer) {
rewrite ^/ http://img.freeoa.net/getout.gif;
return 412;
break;
}
access_log   off;
root /opt/lampp/htdocs/web;
expires 3d;
break;
}

11.只充许固定ip访问网站,并加上密码

root  /opt/htdocs/www;
allow   208.100.167.100;
allow   222.3.1.2;
denyall;
auth_basic “FreeOA_Admin”;
auth_basic_user_file htpasswd;

12.将多级目录下的文件转成一个文件,增强seo效果

/job-123-456-789.html 指向/job/123/456/789.html
rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last;

13.将根目录下某个文件夹指向2级目录

如/shanghaijob/ 指向 /area/shanghai/
如果你将last改成permanent,那么浏览器地址栏显是/location/shanghai/

rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;

上面例子有个问题是访问/shanghai 时将不会匹配

rewrite ^/([0-9a-z]+)job$ /area/$1/ last;
rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;

这样/shanghai 也可以访问了,但页面中的相对链接无法使用,如./list_1.html真实地址是/area/shanghia/list_1.html会变成/list_1.html,导至无法访问。

那我加上自动跳转也是不行了
(-d $request_filename)它有个条件是必需为真实目录,而我的rewrite不是的,所以没有效果。

if (-d $request_filename){
rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}

知道原因后可手动跳转
rewrite ^/([0-9a-z]+)job$ /$1job/ permanent;
rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;

14.文件和目录不存在的时候重定向

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

15.rewrite和if、set的示例
server {
  # 访问 /last.html 的时候,页面内容重写到 /index.html 中,并继续后面的匹配,浏览器地址栏URL地址不变
  rewrite /last.html /index.html last;

  # 访问 /break.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配,浏览器地址栏URL地址不变;
  rewrite /break.html /index.html break;

  # 访问 /redirect.html 的时候,页面直接302定向到 /index.html中,浏览器地址URL跳为index.html
  rewrite /redirect.html /index.html redirect;

  # 访问 /permanent.html 的时候,页面直接301定向到 /index.html中,浏览器地址URL跳为index.html
  rewrite /permanent.html /index.html permanent;

  # 把 /html/*.html => /post/*.html ,301定向
  rewrite ^/html/(.+?).html$ /post/$1.html permanent;

  # 把 /search/key => /search.html?keyword=key
  rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
 
  # 把当前域名的请求,跳转到新域名上,域名变化但路径不变
  rewrite ^/(.*) http://www.jd.com/$1 permanent;
}

# 如果文件不存在则返回400
if (!-f $request_filename) {
    return 400;
}

# 如果host是www.360buy.com,则301到www.jd.com中
if ( $host != "www.jd.com" ){
    rewrite ^/(.*)$ https://www.jd.com/$1 permanent;
}

# 如果请求类型是POST则返回405,return不能返回301,302
if ($request_method = POST) {
    return 405;
}

# 如果参数中有 a=1 则301到指定域名
if ($args ~ a=1) {
    rewrite ^ http://example.com/ permanent;
}

- 文件名及参数重写
location = /index.html {
# 修改默认值为
 set $name test;

# 如果参数中有 name=xx 则使用该值
 if ($args ~* name=(\w+?)(&|$)) {
     set $name $1;
 }

# permanent 301重定向
 rewrite ^ /$name.html permanent;
}

- 隐藏真实目录
server {
  root /var/www/html;
  # 用 /html_test 来掩饰 html
  location / {
    # 使用break拿一旦匹配成功则忽略后续location
    rewrite /html_test /html break;
  }

  # 访问真实地址直接报没权限
  location /html {
      return 403;
  }
}

- 禁止指定IP访问
location / {
    if ($remote_addr = 192.168.1.253) {
        return 403;
    }
}

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

- 对/images/bla_500x400.jpg文件请求,重写到/resizer/bla.jpg?width=500&height=400地址,并会继续尝试匹配location。
rewrite ^/images/(.*)_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=$3? last;



以下是摘自外文网站的一些重写规则示例

server {
    listen       80;
    server_name  example.org;
    return       301 http://www.example.org$request_uri;
}

server {
    listen       80;
    server_name  www.example.org;
    ...
}

server {
    listen 80;
    server_name www.domain.com;
    // $scheme will get the http protocol
    // and 301 is best practice for tablet, phone, desktop and seo
    return 301 $scheme://domain.com$request_uri;
}

server {
    listen 80;
    server_name domain.com;
    // here goes the rest of your config file
    location / {
        rewrite ^/cp/login?$ /cp/login.php last;
    }
}

server {
    server_name  domain.com;
    rewrite ^(.*) http://www.domain.com$1 permanent;
}

server {
    #listen 80 is default
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

server {
    listen 80;
    server_name domain1.com;
    return 301 $scheme://domain2.com$request_uri;
}

Redirect from non-www to www

server {
    server_name example.com;
    # Option 1
    return 301 $scheme://$host$request_uri;
    # Option 2
    rewrite ^ http://$host$request_uri? permanent;
}

Redirect from http to https

server {
    server_name example.com;
    # Option 1
    return 301 https://$server_name$request_uri;
    # Option 2
    rewrite ^ https://$server_name$request_uri? permanent;
}

Redirect URI Matching

Within the server block of our application server, location blocks are used to match against a request URI that needs to be redirected.

server {
     listen 80;
     server_name example.com
     #Exact URI
     location = /post/learning-nginx-redirects {
          return 301 http://example.com/articles/nginx/how-to-do-redirects/
     }
     #Matching URI Path
     location = /post/learning-nginx-redirects {
        return 301 http://example.com/articles/nginx/how-to-do-redirects/
    }
    #Matching URI Patterns
    location /post {
        return 301 http://example.com/articles
    }
    #Temporary Redirect
    location /post {
        return 302 http://example.com/articles
    }
    #Creating a Permanent Redirect
    location /post {
        return 301 http://example.com/articles
    }
}

Redirect both, non-SSL and SSL to their non-www counterpart:
server {
    listen 80;
    listen 443 ssl;
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

The $scheme variable will only contain http if your server is only listening on port 80 (default) and the listen option does not contain the ssl keyword. Not using the variable will not gain you any performance.

**Redirect everything to SSL (personal config on UNIX with IPv4, IPv6, SPDY, ...):**

#
# Redirect all www to non-www
#
server {
    server_name          www.example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:80;
    listen               *:443 ssl spdy;
    listen               [::]:80 ipv6only=on;
    listen               [::]:443 ssl spdy ipv6only=on;
    return 301 https://example.com$request_uri;
}

#
# Redirect all non-encrypted to encrypted
#
server {
    server_name          example.com;
    listen               *:80;
    listen               [::]:80;
    return 301 https://example.com$request_uri;
}

#
# There we go!
#
server {
    server_name          example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:443 ssl spdy;
    listen               [::]:443 ssl spdy;
    # rest goes here...
}

REWRITE

Only the part of the original url that matches the regex is rewritten.
Slower than a Return.
Returns HTTP 302 (Moved Temporarily) in all cases, irrespective of permanent.
Suitable for temporary url changes.

RETURN

The entire url is rewritten to the url specified.
Faster response than rewrite.
Returns HTTP 301 (Moved Permanently).
Suitable for permanent changes to the url.
No need to set permanent.