本文仅代表个人观点。

一、rewrite

1、rewrite 特点

(1)重写url,可以重写path,也可以重写整个url(存在协议,默认返回302,代表临时跳转,此时 last 和 break 无效)。

(2)4 个 flag:last、break、redirect(302)、permanent(301)。存在 flag 时,在当前 location 中,不再执行之后的 rewrite 指令集(包括 rewrite、return)中的指令;break 和 last 正好相反,break 中止对其它 location 的规则匹配,last 继续向其它 location 进行规则匹配;

(3)存在 rewrite 时,proxy_pass 需要和 break 一起使用,否则将被跳过。

(4)rewrite 重写整个 url (302)时,会暴露链接(浏览器执行重定向链接);重写 path 时,break 和 last 可以隐藏链接(代理执行),redirect、permanent 会暴露链接(浏览器执行);

(5)rewrite 和 proxy_pass 都可以重写整个url,区别是:(1)rewrite 重写整个 url 后,重定向的请求由浏览器发送,不常用,一般适用于访问公网其他服务器,如用于解决跨域问题;proxy_pass 重写整个 url 后,由代理服务器发起重定向请求,浏览器是无感知的,以便于访问内网和隐藏调用链;(2)rewrite 常用于重写 path,此时使用 break 和 last 也可以隐藏重定向的调用链,使用 redirect 和 permanent 则会暴露调用链;

总结:

(1)仅重写 path,使用 rewrite;

(2)仅重写主机,最好使用 proxy_pass;

(3)重写整个 url,结合使用 proxy_pass 和 rewrite。

2、使用举例

(1)break

server {
        listen 9000;
        server_name localhost;

        location /info {
                rewrite ^/.* https://www.baidu.com permanent;
        }

        location /break {
                rewrite /.* /info break;
                proxy_pass http://127.0.0.1:9000;

                # 该 return 不执行
                return 200 "ok";
        }
}

输入:http://localhost:9000

执行过程:首先,匹配到 /break 的 location 块,执行了 rewrite 和 proxy_pass,跳过 return(因为有 break),重定向到 http://127.0.0.1:9000/info;然后,再次进行 server 块,匹配到 /info 的 location 块,最后重定向到了baidu。

总结:两次进入 server

(2)break

输入:http://localhost:9000

执行过程:首先,匹配到 /break 的 location 块,执行了 rewrite 和 proxy_pass,跳过 return(因为有 break),重定向到 http://127.0.0.1:9000/info;然后,再次进行 server 块,匹配到 /info 的 location 块,最后重定向到了baidu。

总结:两次进入 server

注意:proxy_pass 最后不要写成 
http://127.0.0.1:9000/,应去掉最后的斜杠,而(1)的写法可加斜杠,也可不加斜杠。

server {
        listen 9000;
        server_name localhost;

        location /info {
                rewrite ^/.* https://www.baidu.com permanent;
        }

        location /break {
                rewrite /.* /info;
                break;
                proxy_pass http://127.0.0.1:9000;

                # 该 return 不执行
                return 200 "ok";
        }
}

(3)last

输入:http://localhost:9000

执行过程:首先,匹配到 /break 的 location 块,执行了 rewrite,跳过 return 和 proxy_pass(因为有 last,proxy_pass 需要和 break 一起用);然后继续匹配,匹配到 /info 的 location 块,最后重定向到了baidu。

总结:一次进入 server,两次 location 匹配

server {
        listen 9000;
        server_name localhost;

        location /info {
                rewrite ^/.* https://www.baidu.com permanent;
        }

        location /break {
                rewrite /.* /info last;

                # 该 proxy_pass 不执行
                proxy_pass http://127.0.0.1:9000;

                # 该 return 不执行
                return 200 "ok";
        }
}

二、proxy_pass

1、proxy_pass 的特点

(1)代理作用,由代理服务器发起重定向请求;

(2)proxy_pass 重写的 url 中包含 path 时,会替换 location 块的匹配规则。

  • http://example.com/api/data 会被代理到 http://127.0.0.1/proxy/data
location /api/ {
    proxy_pass http://127.0.0.1/proxy/;
}
  • http://example.com/api/data 会被代理到 http://127.0.0.1/proxydata 
location /api/ {
    proxy_pass http://127.0.0.1/proxy;
}
  • http://example.com/api/data 会被代理到 http://127.0.0.1/data
location /api/ {
    proxy_pass http://127.0.0.1/;
}

(3)proxy_pass 中不含path时,则不会发生替换

  • http://example.com/api/data 会被代理到 http://127.0.0.1/api/data
location /api/ {
    proxy_pass http://127.0.0.1;
}

(4)与 rewrite 同时存在时,proxy_pass 中的 path 不会替换,相当于不起作用

  • http://example.com/api/data 会被代理到 http://127.0.0.1/info/data
location /api/ {
    rewrite /api/(.*) /info/$1 break;
    proxy_pass http://127.0.0.1/proxy/;
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐