0%

nginx rewrite

nginx rewrite

跟随本篇做实验,请务必在每一次访问前清理浏览器缓存。

Syntax: rewrite regex replacement [flag];
Default: —
Context: server, location, if

一旦一个URI匹配到指定的正则表达式,URI就会立即被修改为replacement,默认情况下(无flag)修改后的URI会继续向下执行指令。
配置flag可以终止继续向下执行指令。如果配置replacement以“http://”, “https://”, or “$scheme”开头,新URL将直接返回给客户端(默认为302状态码)。
replacement中可以使用变量

flag不同值的含义:

  • 无flag 匹配到之后会继续向下执行指令
  • last 停止当前指令,修改后的URI开始匹配
  • break 停止当前指令,立即返回结果
  • redirect 返回临时重定向302
  • permanent 返回永久重定向301

redirectpermanent是返回重定向状态码给客户端,地址栏url会变;
lastbreak的区别在于,break是按照修改后的url直接返回结果,last是按照修改后的url开启新一轮匹配。

无flag

nginx server配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
location = /f5.html {
return 403;
}

location = /favicon.ico {
empty_gif;
}

location / {
rewrite ^.*$ /f5.html;
rewrite ^.*$ /index.html;
}

rewrite_log on;

a_html.png

查看错误日志,发现死循环了

1
2
3
4
5
6
7
2019/07/26 16:57:50 [notice] 24875#0: *23 "^.*$" matches "/a.html", client: 127.0.0.1, server: localhost, request: "GET /a.html HTTP/1.1", host: "127.0.0.1"
2019/07/26 16:57:50 [notice] 24875#0: *23 rewritten data: "/f5.html", args: "", client: 127.0.0.1, server: localhost, request: "GET /a.html HTTP/1.1", host: "127.0.0.1"
2019/07/26 16:57:50 [notice] 24875#0: *23 "^.*$" matches "/f5.html", client: 127.0.0.1, server: localhost, request: "GET /a.html HTTP/1.1", host: "127.0.0.1"
2019/07/26 16:57:50 [notice] 24875#0: *23 rewritten data: "/index.html", args: "", client: 127.0.0.1, server: localhost, request: "GET /a.html HTTP/1.1", host: "127.0.0.1"
2019/07/26 16:57:50 [notice] 24875#0: *23 "^.*$" matches "/index.html", client: 127.0.0.1, server: localhost, request: "GET /a.html HTTP/1.1", host: "127.0.0.1"
2019/07/26 16:57:50 [notice] 24875#0: *23 rewritten data: "/f5.html", args: "", client: 127.0.0.1, server: localhost, request: "GET /a.html HTTP/1.1", host: "59.151.22.61"
2019/07/26 16:57:50 [notice] 24875#0: *23 "^.*$" matches "/f5.html", client: 1127.0.0.1, server: localhost, request: "GET /a.html HTTP/1.1", host: "127.0.0.1"

上面配置,用户请求流程:

1
/a.html --第一条rewrite规则匹配--> /f5.html --第二条rewrite匹配--> /index.html --匹配当前server(Host没变),匹配location /,再次循环

如果添加以下location,则可以正常访问到index.html

1
2
location = /index.html {
}

无flag rewrite写入server与location区别

  • 写入serverrewrite规则,仅会执行一次;
  • 写入locationrewrite规则,若rewrite后的地址仍然匹配location,则会再次rewrite

如以下两个规则:

1
2
3
4
5
6
server {
listen 80;
server_name localhost;
root /html;
rewrite ^(.*)userid(.*)$ $1uid$2;
}
1
2
3
4
5
6
7
8
9
server {
listen 80;
server_name localhost;
root /html;

location / {
rewrite ^(.*)userid(.*)$ $1uid$2;
}
}

假设client访问127.0.0.1/userid1/userid2,则第一条规则实际访问的是/html/uid1/userid2;第二条规则实际访问的是/html/uid1/uid2;

last

添加last

1
2
rewrite ^.*$ /f5.html last;
rewrite ^.*$ /index.html last;

403.png

break

修改为break

1
2
3
4
location / {
rewrite ^.*$ /f5.html break;
rewrite ^.*$ /index.html break;
}

f5.png

rewrite与index

当有以下rewrite语句的时候,会抢占index语句,导致无法自动访问目录下的默认index文件

1
rewrite ^/(.*) /m/$1;

参考:
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite