例题 1
配置:
error_log logs/error.log info;
server {
listen 9090;
server_name localhost;
root html;
rewrite_log on;
rewrite "^/aaa\.html$" /bbb.html;
location /ccc.html {
rewrite "^/ccc\.html$" /eee.html;
}
location /bbb.html {
rewrite "^/bbb\.html$" /ccc.html;
rewrite "^/ccc\.html$" /ddd.html;
}
}
结果:
[root@web108 ~]# curl http://localhost:9090/aaa.html
ddd html file
[root@web108 ~]#
日志:
2011/08/08 10:05:41 [notice] 31592#0: *90 "^/aaa\.html$" matches "/aaa.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:05:41 [notice] 31592#0: *90 rewritten data: "/bbb.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:05:41 [notice] 31592#0: *90 "^/bbb\.html$" matches "/bbb.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:05:41 [notice] 31592#0: *90 rewritten data: "/ccc.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:05:41 [notice] 31592#0: *90 "^/ccc\.html$" matches "/ccc.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:05:41 [notice] 31592#0: *90 rewritten data: "/ddd.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:05:41 [notice] 31592#0: *90 "^/aaa\.html$" does not match "/ddd.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:05:41 [info] 31592#0: *90 client 127.0.0.1 closed keepalive connection
解释:
GET /aaa.html 请求,首先执行 server 级的 rewrite 指令,被重写为 /bbb.html ,然后匹配到 location /bbb.html {} ,接着执行 location 级的 rewrite 指令,先重写为 /ccc.html ,再重写为 /ddd.html ;由于 URI 被 location 级的 rewrite 指令重写了,因此需要重新进行 location 的匹配,相当于重写后的 URI 被当做一个新的请求,会重新执行 server 级的 rewrite ,然后重新匹配 location ,日志“ 2011/08/08 10:05:41 [notice] 31592#0: *90 "^/aaa\.html$" does not match "/ddd.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090" ”体现了重新匹配 location 的流程。
例题 2
配置:
error_log logs/error.log info;
server {
listen 9090;
server_name localhost;
root html;
rewrite_log on;
rewrite "^/aaa\.html$" /bbb.html;
rewrite "^/ccc\.html$" /ddd.html;
location /bbb.html {
rewrite "^/bbb\.html$" /ccc.html;
}
location /ddd.html {
rewrite "^/ddd\.html$" /eee.html;
}
}
结果:
[root@web108 ~]# curl http://localhost:9090/aaa.html
eee html file
[root@web108 ~]#
日志:
2011/08/08 10:21:00 [notice] 2218#0: *91 "^/aaa\.html$" matches "/aaa.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 rewritten data: "/bbb.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 "^/ccc\.html$" does not match "/bbb.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 "^/bbb\.html$" matches "/bbb.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 rewritten data: "/ccc.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 "^/aaa\.html$" does not match "/ccc.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 "^/ccc\.html$" matches "/ccc.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 rewritten data: "/ddd.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 "^/ddd\.html$" matches "/ddd.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 rewritten data: "/eee.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 "^/aaa\.html$" does not match "/eee.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [notice] 2218#0: *91 "^/ccc\.html$" does not match "/eee.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"
2011/08/08 10:21:00 [info] 2218#0: *91 client 127.0.0.1 closed keepalive connection
解释:
第一次迭代 location 匹配
GET /aaa.html ,首先执行 server 级的重写,“ rewrite "^/aaa\.html$" /bbb.html ”把 /aaa.html 重写为 /bbb.html ,但 /bbb.html 没匹配上“ rewrite "^/ccc\.html$" /ddd.html ”,最终保留 /bbb.html ;接着,匹配 location /bbb.html {} ,执行 location 级的 rewrite 指令,把 /bbb.html 重写为 /ccc.html ,由于 URI 被 location 级 rewrite 重写,因此需要重新迭代 location 匹配。
第二次迭代 location 匹配
对于第一次迭代结果 /ccc.html ,首先依然是执行 server 级的 rewrite 指令,“ rewrite "^/aaa\.html$" /bbb.html; ”跟 /ccc.html 不匹配,但“ rewrite "^/ccc\.html$" /ddd.html; ”把 /ccc.html 重写为 /ddd.html ; server 级 rewrite 执行完后,接着 location 匹配, /ddd.html 匹配到 location /ddd.html {} ,执行 location 级的 rewrite 指令,把 /ddd.html 重写为 /eee.html 。同样由于 URI 被 location 级的 rewrite 指令重写,于是需要重新迭代 location 匹配。
第三次迭代 location 匹配
对于第二次迭代结果 /eee.html ,首先依然执行 server 级的 rewrite 指令,“ rewrite "^/aaa\.html$" /bbb.html; ”和“ rewrite "^/ccc\.html$" /ddd.html; ”,只不过它们都没匹配上 /eee.html ,接着 /eee.html 进行 location 匹配,也没有,最终结果是 /eee.html ,返回“ eee html file ”页面。
最后说明下,如果把上述配置修改成server级rewrite和location的编辑顺序调整:
server {
listen 9090;
server_name localhost;
root html;
rewrite_log on;
location /bbb.html {
rewrite "^/bbb\.html$" /ccc.html;
}
location /ddd.html {
rewrite "^/ddd\.html$" /eee.html;
}
rewrite "^/aaa\.html$" /bbb.html;
rewrite "^/ccc\.html$" /ddd.html;
}
结果是不会受影响的,也就是说location匹配迭代总是先执行server级rewrite,再进行location匹配,再执行location级的rewrite,如果URI因location级rewrite指令重写,则需要进行下一次迭代。但总的迭代次数不超过10次,否则nginx报500错误。
简单伪代码描述下rewrite执行过程:
boolean match_finish = false;
int match_count = 0;
while(!match_finish && match_count < 10) {
match_count ++;
(1)按编辑顺序执行server级的rewrite指令;
(2)按重写后的URI匹配location;
(3)
String uri_before_location = uri;
按编辑顺序执行location级的rewrite指令;
String uri_after_location = rewrite(uri);
if(uri_before_location != uri_after_location) {
match_finish = false;
} else {
match_finish = true;
}
if(location rewrite has last flag) {
continue;//表示不执行后面的rewrite,直接进入下一次迭代
}
if(location rewrite has break flag) {
break;//表示不执行后面的rewrite,并退出循环迭代
}
}
if(match_count <= 10) {
return HTTP_200;
} else {
return HTTP_500;
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于