nginx rewrite中的last & break机制

The last & break mechanism in nginx rewrite

我现在正在为我的项目处理 nginx 重写,但得到了一些超出我预期的东西,只是与您分享,看看是否有任何合理的建议。

nginx 服务器设置列表如下:

location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ /mp3/.mp3;
    rewrite ^(/download/.*)/movie/(.*)\..*$ /avi/.mp3 break;
    rewrite ^(/download/.*)/avvvv/(.*)\..*$ /rmvb/.mp3;
}

从上一节可以看出,我只添加了一个下载位置,重写了三个rules.I在nginx中打开调试日志并启动它以加载此设置。

现在我们在浏览器中输入url: localhost/download/123/movie/UBW.avi。从日志中可以看出命中了规则,日志如下:

2017/05/22 15:27:27 [notice] 1904#12520: *85 "^(/download/.*)/media/(.*)\..*$" does not match "/download/123/movie/UBW.avi", client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"
2017/05/22 15:27:27 [notice] 1904#12520: *85 "^(/download/.*)/movie/(.*)\..*$" matches "/download/123/movie/UBW.avi", client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"
2017/05/22 15:27:27 [notice] 1904#12520: *85 rewritten data: "/download/123/avi/UBW.mp3", args: "", client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"
2017/05/22 15:27:27 [error] 1904#12520: *85 CreateFile() "D:\Soft\nginx-1.13.0/html/download/123/avi/UBW.mp3" failed (3: The system cannot find the path specified), client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"

从上面的信息中,我们可以看到第二条规则被命中并且分节符是由于 "break" 关键字造成的。这种行为在我们的预料之中。

但是我改变了下面的部分并表现出与上面相同的行为:

location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ /mp3/.mp3;
    rewrite ^(/download/.*)/movie/(.*)\..*$ /avi/.mp3 last;
    rewrite ^(/download/.*)/avvvv/(.*)\..*$ /rmvb/.mp3;
}

日志如下:

2017/05/22 15:33:45 [notice] 11244#11544: *92 "^(/download/.*)/media/(.*)\..*$" does not match "/download/123/movie/UBW.avi", client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"
2017/05/22 15:33:45 [notice] 11244#11544: *92 "^(/download/.*)/movie/(.*)\..*$" matches "/download/123/movie/UBW.avi", client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"
2017/05/22 15:33:45 [notice] 11244#11544: *92 rewritten data: "/download/123/avi/UBW.mp3", args: "", client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"
2017/05/22 15:33:45 [notice] 11244#11544: *92 "^(/download/.*)/media/(.*)\..*$" does not match "/download/123/avi/UBW.mp3", client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"
2017/05/22 15:33:45 [notice] 11244#11544: *92 "^(/download/.*)/movie/(.*)\..*$" does not match "/download/123/avi/UBW.mp3", client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"
2017/05/22 15:33:45 [notice] 11244#11544: *92 "^(/download/.*)/avvvv/(.*)\..*$" does not match "/download/123/avi/UBW.mp3", client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"
2017/05/22 15:33:45 [error] 11244#11544: *92 CreateFile() "D:\Soft\nginx-1.13.0/html/download/123/avi/UBW.mp3" failed (3: The system cannot find the path specified), client: 127.0.0.1, server: localhost, request: "GET /download/123/movie/UBW.avi HTTP/1.1", host: "localhost"

从日志的第二行可以看出命中了规则,但是nginx在下载部分开始了一个新的循环,奇怪的是,它并没有命中规则,为什么?

此外,如果我们使用 last 关键字,那么 nginx 将尝试循环该部分多少次,默认情况下是两次,对吗?

The ngx_http_rewrite_module module is used to change request URI using PCRE regular expressions

记住当你重写uri时,uri会改变。

对于last

When rewrite module meets last, it stops processing the current set and the rewritten request is passed once again to find the appropriate location (and the new set of rewriting rules).

在你的配置中

location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ /mp3/.mp3;  //a
    rewrite ^(/download/.*)/movie/(.*)\..*$ /avi/.mp3 last; //b
    rewrite ^(/download/.*)/avvvv/(.*)\..*$ /rmvb/.mp3;    //c
}

你的urllocalhost/download/123/movie/UBW.avi

你的请求 uri 是 /download/123/movie/UBW.avi


第一关

/download/123/movie/UBW.avi匹配b,所以uri重写为/download/123/avi/UBW.mp3,第一遍完成。


二传

然后,在第二遍中,uri 是

/download/123/avi/UBW.mp3

所以它不匹配 a b c,最后,它在日志中抛出错误。