写在前面的话
在 nginx 中,我们很多时候都有一个疑问,在 proxy_pass 或者 root 或者 location 后面需不需要加上 /,加和不加有啥区别。
root / alias 后面的 /
root 和 alias 都是指向目录,所以后面是否存在 / 没有影响:
server { listen 8082; server_name localhost; location ^~ /root/ { root /data/www/root/; index index.html index.htm; } location ^~ /alias/ { alias /data/www/alias/; index index.html index.htm; } }
我们这里加不加红色的 / 都一样的结果。
location 后面的 /
在 location 中也存在是否添加 / 的情况:
server { listen 8082; server_name localhost; location ^~ /alias/ { echo "WITH: /"; } location ^~ /alias { echo "WITHOUT: /"; } }
此时两种匹配就有了两个含义,前者只能匹配 /alis/123 这样的,而后者可以匹配 /alias123,也可 /alias/123 这样的。
但是当两者同时在一个 server 中由于匹配精确度越高优先级越高的原因,后者匹配不到 /alias/123
proxy_pass 后面的 /
这个才是我们这次说明的重点,也是最为复杂的:
我们新建这样的目录结构,然后配置 nginx:
server { listen 7000; server_name localhost; location / { root /data/www/proxy_pass; } }
此时我们可以访问这 4 个 html 文件测试:
这个时候我们做反向代理:
# 代理不带项目名称,没有 / server { listen 7001; server_name locahost; location /proxy/ { proxy_pass http://127.0.0.1:7000; } } # 代理不带项目名称,但是有 / server { listen 7002; server_name locahost; location /proxy/ { proxy_pass http://127.0.0.1:7000/; } } # 代理带项目名称,没有 / server { listen 7003; server_name locahost; location /proxy/ { proxy_pass http://127.0.0.1:7000/other; } } # 代理带项目名称,但是有 / server { listen 7004; server_name locahost; location /proxy/ { proxy_pass http://127.0.0.1:7000/other/; } }
此时我们访问测试同一 URI 不同端口:
结论:
在 proxy_pass 中,当我们不是 / 匹配而是带有自定义项目名匹配的时候:
1. proxy_pass 后面带 /,我们的自定义的项目名就不会被视作路径的一部分去查找后端。
2. proxy_pass 后面不带 /,我们自定义的项目名会当成路径的一部分添加到代理后端的查找中。
当我们在 proxy_pass 代理的导致中还包含项目名称的时候:
1. 当后面还跟了项目名,我们自定义的匹配项目名就都不会再作为请求的一部分去查找后端。
2. 当后面的项目名不带 / 的时候,除去我们自定义部分,后面的 URI 会直接拼接到我们 proxy_pass 上面,由于他们之间没有 / 分隔,所以会组成一个新的路径去查后端。
3. 当后面的项目带 / 的时候,则会在拼接的时候相当于多了个 / 的分隔。
小结
这个 / 就很小的一个符号,但是可能造成我们配置的东西完全不符合我们的需求,特别是第三个 proxy_pass 的。