被nginx转发支配的恐惧

2022年 6月 7日 62点热度 0人点赞 0条评论

file

之前看过一点, 有 / 和没有还是有点区别的.

location 后面的 /

比如:

location /api/ {
    proxy_pass http://127.0.0.1:3000;
}

访问 http://127.0.0.1:80/api/cc, 后端的请求地址是 http://127.0.0.1:3000/api/cc

但是 http://127.0.0.1:80/api 这样的请求不会匹配到这个.

没有 / 的话:

location /api {
    proxy_pass http://127.0.0.1:3000;
}

这样的既能处理 http://127.0.0.1:80/api, 又能处理 http://127.0.0.1:80/api/cc

下面这部分的内容来自: nginx 之 proxy_pass 接口转发的规则

proxy_pass 后面的 /

proxy_pass 只是 HOST, 不包含任何路径, 比如

* http://host           -  √
* https://host          -  √
* http://host:port      -  √
* https://host:port     -  √
* http://host/          -  x
* http://host:port/     -  x

这种情况下, 会把匹配到的所有路径直接穿透转发.

proxy_pass 包含路径的:

http://host             - x
https//host/            - √
http://host:port        - x
https://host:port/      - √
http://host/api         - √
http://host/api/        - √

这种情况下,url 里面会去掉 location 匹配的字符串, 拼接到 proxy_pass 再进行转发.

重写代理链接 - url rewrite

使用 rewrite 指令并且生效后,proxy_pass url 链接中的路径会被忽略, 如:

server {
            listen       83;
            location / {
                rewrite ^/api/(.*) /fixpath=$1 break;
                proxy_pass http://127.0.0.1:3000/node/;
            }
            location ^/api/ {
                rewrite ^/api/(.*) /fixpath=$1 break;
                proxy_pass http://127.0.0.1:3000/node/;
            }
        }
  • 访问 http://127.0.0.1:83/bb/cc 后端的请求地址是 /node/bb/cc(匹配上 / 了, 没有匹配 rewrite)
  • 访问 http://127.0.0.1:83/api/cc 后端的请求地址是 /fixpath=cc (我们写的 proxy_pass http://127.0.0.1:3000/node/ 里面的 node 路径丢失了 )

配置示例

events {
}

http {
    # proxy_pass url 只是 host
    # 这时候 location 匹配的完整路径将直接透传给 url , 如:
    server {
        listen       80;

        location / {
            proxy_pass http://127.0.0.1:3000;
        }

        location /api/ {
            proxy_pass http://127.0.0.1:3000;
        }
    }
    # url 包含路径
    # 当 proxy_pass url 的 url 包含路径时, 匹配时会根据 location 的匹配后的链接透传给 url , 注意匹配后就是这样:

    server {
        listen       81;

        location / {
            proxy_pass http://127.0.0.1:3000/;
        }

        location /api/ {
            proxy_pass http://127.0.0.1:3000/;
        }

        location /bpi/ {
            proxy_pass http://127.0.0.1:3000/v1;
        }

        location /cpi {
            proxy_pass http://127.0.0.1:3000/v1;
        }
    }

    # 当 location 以正则形式匹配时,proxy_pass 就不能以 / 结束了,
    # 也就是不能包含路径了, 会提示配置错误, 比如错误的:

    server {
        listen       82;

        location / {
            proxy_pass http://127.0.0.1:3000/;
        }
        # nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, 
        # or inside named location, or inside "if" statement, or inside "limit_except" block in /test.conf:47
        #    location ~* ^/api/ {
        #         proxy_pass http://127.0.0.1:3000/;
        #     }

        # nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression,
        # or inside named location, or inside "if" statement, or inside "limit_except" block in /test.conf:52
        #    location ~* ^/api/ {
        #         proxy_pass http://127.0.0.1:3000/b1;
        #     }
    }

    # 使用 rewrite 指令并且生效后,proxy_pass url 链接中的路径会被忽略, 如:
    server {
        listen       83;
        location / {
            proxy_pass http://127.0.0.1:3000/node/;
        }

        location ^/api/ {
            rewrite ^/api/(.*) /fixpath=$1 break;
            proxy_pass http://127.0.0.1:3000/node/;
        }
    }
}

nginx 官方文档

Syntax: proxy_pass URL;
Default:    —
Context:    location, if in location, limit_except

Sets the protocol and address of a proxied server and an optional URI to which a location should be mapped. As a protocol, "http" or "https" can be specified. The address can be specified as a domain name or IP address, and an optional port:

proxy_pass http://localhost:8000/uri/;

or as a UNIX-domain socket path specified after the word "unix" and enclosed in colons:

proxy_pass http://unix:/tmp/backend.socket:/uri/;

If a domain name resolves to several addresses, all of them will be used in a round-robin fashion. In addition, an address can be specified as a server group.

Parameter value can contain variables. In this case, if an address is specified as a domain name, the name is searched among the described server groups, and, if not found, is determined using a resolver.

A request URI is passed to the server as follows:

  • If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:
    location /name/ {
    proxy_pass http://127.0.0.1/remote/;
    }
  • If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI:
    location /some/path/ {
    proxy_pass http://127.0.0.1;
    }

Before version 1.1.12, if proxy_pass is specified without a URI, the original request URI might be passed instead of the changed URI in some cases.

In some cases, the part of a request URI to be replaced cannot be determined:

  • When location is specified using a regular expression, and also inside named locations.
    In these cases, proxy_pass should be specified without a URI.
  • When the URI is changed inside a proxied location using the rewrite directive, and this same configuration will be used to process a request (break):
    location /name/ {
    rewrite    /name/([^/]+) /users?name=$1 break;
    proxy_pass http://127.0.0.1;
    }

    In this case, the URI specified in the directive is ignored and the full changed request URI is passed to the server.

  • When variables are used in proxy_pass:
    location /name/ {
    proxy_pass http://127.0.0.1$request_uri;
    }

    In this case, if URI is specified in the directive, it is passed to the server as is, replacing the original request URI.

WebSocket proxying requires special configuration and is supported since version 1.3.13.

什么是 normalized url?

file

本文来自:https://blog.duhbb.com

本文链接地址:被nginx转发支配的恐惧,英雄不问来路,转载请注明出处,谢谢。

有话想说:那就赶紧去给我留言吧。

rainbow

这个人很懒,什么都没留下

文章评论