分布式 - 服务器Nginx:一小时入门系列之 rewrite 指令

1. rewrite 指令语法

nginx的rewrite指令用于重写URL,可以将一个URL重写为另一个URL。它的语法如下:

rewrite regex replacement [flag];

其中,regex是一个正则表达式,用于匹配需要重写的URL;replacement是重写后的URL;flag是可选的标志,用于控制重写的行为。flag 的常见取值为 last 和 break,都是用于控制重写规则执行的指令:

① break指令会立即停止当前的rewrite规则,并将处理流程交给下一个指令。也就是说,如果当前规则匹配成功,那么后面的规则将不会再被执行。如果没有匹配成功,则会继续执行后面的规则。

② last指令会停止当前的rewrite规则,并将处理流程交给nginx的下一个阶段。也就是说,如果当前规则匹配成功,那么后面的规则也会被执行。如果没有匹配成功,则会继续执行后面的规则。

需要注意的是,break和last指令的区别在于是否继续执行后面的规则。如果需要停止后面的规则,使用break指令;如果需要继续执行后面的规则,使用last指令。

rewrite 指令会导致请求的重新处理,因此可能会影响性能,因此,应该尽量避免在高并发场景下使用rewrite指令。

2. rewrite 指令示例

① Nginx 配置文件 8002.conf:

server{
    listen 8002;
    server_name rioyi.tomcat;

    # 请求转达到 http://localhost:8080
    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass http://localhost:8080;
    }

    # 请求ie页面
    location = /html/ie.html {
        root  /some/path/static;
    }

    # 请求字体文件
    location ^~ /fonts/ {
        root  /some/path/static;
    }

    # css|js|png|jpg|gif|ico 页面
    location ~ \.(css|js|png|jpg|gif|ico) {
        root /some/path/static;
    }
}

② 访问 http://192.168.1.9:8002 并登录若依管理系统上传一个图片,在响应中获取上传图片的访问路径:http://192.168.1.9:8002/profile/upload/2023/08/26/Spring3_20230826191911A002.jpg,直接在浏览器访问该图片会报错404,因为请求会去访问 /some/path/static 目录下的文件。

{
    
    
    "msg": "操作成功",
    "fileName": "/profile/upload/2023/08/26/Spring3_20230826191911A002.jpg",
    "code": 0,
    "newFileName": "Spring3_20230826191911A002.jpg",
    "url": "http://192.168.1.9:8002/profile/upload/2023/08/26/Spring3_20230826191911A002.jpg",
    "originalFilename": "Spring3.jpg"
}

在浏览器当访问图片 http://192.168.1.9:8002/profile/upload/2023/08/26/Spring3_20230826191911A002.jpg 时报错 404 Not Found,因为访问该jpg文件时会去访问 /some/path/static 目录下的文件,因此报错 404 Not Found。

③ 利用 rewrite 指令将请求URL重写为另一个URL,直接访问服务器图片地址:

server{
    listen 8002;
    server_name rioyi.tomcat;
    
    # 将所有以“/profile/upload”开头的请求重写为“http://192.168.1.9:8080”加上原始请求的URI
    rewrite_log on;
    rewrite ^/profile/upload http://192.168.1.9:8080$request_uri;

    # 请求转达到 http://localhost:8080
    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass http://localhost:8080;
    }

    # 请求ie页面
    location = /html/ie.html {
        root  /some/path/static;
    }

    # 请求字体文件
    location ^~ /fonts/ {
        root  /some/path/static;
    }

    # css|js|png|jpg|gif|ico 页面
    location ~ \.(css|js|png|jpg|gif|ico) {
        root /some/path/static;
    }
}

④ 访问 http://192.168.1.9:8002/profile/upload/2023/08/26/Spring3_20230826191911A002.jpg 会重定向到 http://192.168.1.9:8080/profile/upload/2023/08/26/Spring3_20230826191911A002.jpg

3. 不使用 last 和 break 重写规则

① 在 /home/AdminLTE-3.2.0/pages下创建一个1.txt,里面内容是this is a file

server{
    listen 8000;
    server_name localhost;

    rewrite_log on;

    location / {
        rewrite ^/old/(.*) /new/$1;
        rewrite ^/new/(.*) /pages/$1;

        root /home/AdminLTE-3.2.0;
        index index.html index2.html index3.html;
    }
    
    location /pages/1.txt {
        return 200 "this is rewrite test!";
    }
}

Nginx 服务器配置文件监听本地 8000 端口,配置了 rewrite_log 开启重写日志记录。当请求的URL为 /old/1.txt 时,第一条 rewrite 规则将以 /old/ 开头的请求重写为以 /new/ 开头的请求,第二条 rewrite 规则将以 /new/ 开头的请求重写为以 /pages/ 开头的请求,最后接着匹配以 /pages/1.txt 结尾的请求,使用 return 指令返回状态码 200 和消息体 “this is rewrite test!”

② 访问 http://192.168.1.9:8000/old/1.txt,默认以顺序执行:

[root@nginx-dev conf.d]# curl -i http://192.168.1.9:8000/old/1.txt
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Sat, 26 Aug 2023 12:55:50 GMT
Content-Type: text/plain
Content-Length: 21
Connection: keep-alive

this is rewrite test!

③ 查看 rewrite 日志:

==> /var/log/nginx/error.log <==
2023/08/26 20:55:50 [notice] 6214#6214: *209 "^/old/(.*)" matches "/old/1.txt", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

2023/08/26 20:55:50 [notice] 6214#6214: *209 rewritten data: "/new/1.txt", args: "", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

2023/08/26 20:55:50 [notice] 6214#6214: *209 "^/new/(.*)" matches "/new/1.txt", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

2023/08/26 20:55:50 [notice] 6214#6214: *209 rewritten data: "/pages/1.txt", args: "", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"
==> /var/log/nginx/access.log <==

4. 使用 break 重写规则

break指令会立即停止当前的rewrite规则,并将处理流程交给下一个指令。也就是说,如果当前规则匹配成功,那么后面的规则将不会再被执行。如果没有匹配成功,则会继续执行后面的规则。

① Nginx 配置文件 8000.conf:

break 指令不执行后续的rewrite规则,以新的/new/1.txt路径去执行块内的其他指令。

server{
    listen 8000;
    server_name localhost;

    rewrite_log on;

    location / {
        rewrite ^/old/(.*) /new/$1 break;
        rewrite ^/new/(.*) /pages/$1;

        root /home/AdminLTE-3.2.0;
        index index.html index2.html index3.html;
    }
    
    location /pages/1.txt {
        return 200 "this is rewrite test!";
    }
}

当请求的URL为 /old/1.txt 时,第一条规则将会匹配并将其重写为/new/1.txt,然后使用break关键字终止 rewrite 规则的匹配。 nginx将不再继续匹配后续的rewrite规则,而是直接使用当前规则的重写结果进行请求处理。

② 访问 http://192.168.1.9:8000/old/1.txt :报错 404 Not Found

[root@nginx-dev conf.d]# curl -i http://192.168.1.9:8000/old/1.txt
HTTP/1.1 404 Not Found
Server: nginx/1.24.0
Date: Sat, 26 Aug 2023 13:08:49 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.24.0</center>
</body>
</html>

③ 查看 rewrite 日志:

2023/08/26 21:08:49 [notice] 6283#6283: *210 "^/old/(.*)" matches "/old/1.txt", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

2023/08/26 21:08:49 [notice] 6283#6283: *210 rewritten data: "/new/1.txt", args: "", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

2023/08/26 21:08:49 [error] 6283#6283: *210 open() "/home/AdminLTE-3.2.0/new/1.txt" failed (2: No such file or directory), client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

==> /var/log/nginx/access.log <==

5. 使用 last 重写规则

last指令会停止当前的rewrite规则,并将处理流程交给nginx的下一个阶段。也就是说,如果当前规则匹配成功,那么后面的规则也会被执行。如果没有匹配成功,则会继续执行后面的规则。

① Ngiinx 配置文件8000.conf:

server{
    listen 8000;
    server_name localhost;

    rewrite_log on;

    location / {
        rewrite ^/old/(.*) /new/$1 last;
        rewrite ^/new/(.*) /pages/$1;

        root /home/AdminLTE-3.2.0;
        index index.html index2.html index3.html;
    }
    
    location /pages/1.txt {
        return 200 "this is rewrite test!";
    }
}

② 测试:

[root@nginx-dev conf.d]# curl -i http://192.168.1.9:8000/old/1.txt
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Sat, 26 Aug 2023 13:42:02 GMT
Content-Type: text/plain
Content-Length: 21
Connection: keep-alive

this is rewrite test! 

③ 查看 rewrite 重写日志:

2023/08/26 21:42:02 [notice] 6346#6346: *211 "^/old/(.*)" matches "/old/1.txt", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

2023/08/26 21:42:02 [notice] 6346#6346: *211 rewritten data: "/new/1.txt", args: "", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

2023/08/26 21:42:02 [notice] 6346#6346: *211 "^/old/(.*)" does not match "/new/1.txt", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

2023/08/26 21:42:02 [notice] 6346#6346: *211 "^/new/(.*)" matches "/new/1.txt", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

2023/08/26 21:42:02 [notice] 6346#6346: *211 rewritten data: "/pages/1.txt", args: "", client: 192.168.1.9, server: localhost, request: "GET /old/1.txt HTTP/1.1", host: "192.168.1.9:8000"

==> /var/log/nginx/access.log <==

猜你喜欢

转载自blog.csdn.net/qq_42764468/article/details/132516590