nginx中斜杠
nginx中的"\"
Location
nginx每个location都是一个匹配目录,nginx的策略是:访问请求来时,会对访问地址进行解析,从上到下逐个匹配,匹配上就执行对应location大括号中的策略,并根据策略对请求作出相应。
location中没有"/"
- 请求可以模糊匹配以字符串开头的所有字符串
location中有"/"
- 只能精确匹配字符本身
举例
location /test {
root /usr/local/app/ ;
index index.html index.htm;
}
location没有斜杠结尾,则可以匹配到
/testxxxxx
也可以匹配到/testxxxx/xxxx
只要以test开头的都能匹配到
location /test/ {
root /usr/local/app ;
index index.html index.htm;
}
- 必须精确匹配到
/test/
整个URI的请求(包好/test/xxx
)
URL自动加"/"
有时候访问的地址要求后面以 / 结尾,如果用户忘记输入 /,Nginx 就会自动加上 /。
有时候访问的地址要求后面以 / 结尾,如果用户忘记输入 /,Nginx 就会自动加上 /。
通过一个例子来演示问题:server { listen 80; server_name localhost; location / { root html; index index.html; } }
要想访问上述资源,很简单,只需要通过 http://192.168.200.133 直接就能访问,地址后面不需要加 /,但是如果将上述的配置修改为如下内容:
server { listen 80; server_name localhost; location /frx { root html; index index.html; } }
这个时候,要想访问上述资源,按照上述的访问方式,我们可以通过 http://192.168.200.133/frx/ 来访问,但是如果地址后面不加斜杠,如 http://192.168.200.133/frx,页面就会出问题。如果不加斜杠,Nginx 服务器内部会自动做一个 301 的重定向,重定向的地址会有一个指令叫 server_name_in_redirect 来决定重定向的地址:
如果该指令为 on重定向的地址为:http://server_name/目录名/
如果该指令为 off重定向的地址为:http://原URL中的域名/目录名/
所以就拿刚才的地址来说,访问 http://192.168.200.133/frx 如果不加斜杠,那么按照上述规则:如果指令 server_name_in_redirect 为 on,则 301 重定向地址变为 http://localhost/frx/,IP 发生改变,地址出现了问题
如果指令 server_name_in_redirect 为 off,则 301 重定向地址变为 http://192.168.200.133/frx/。这个符合我们的期望
注意 server_name_in_redirect 指令在 Nginx 的 0.8.48 版本之前默认都是 on,之后改成了 off,所以现在我们这个版本不需要考虑这个问题,但是如果是 0.8.48 以前的版本并且 server_name_in_redirect 设置为 on,我们如何通过 Rewrite 来解决这个问题?
解决方案
我们可以使用 Rewrite 功能为末尾没有斜杠的 URL 自动添加一个斜杠
server {
listen 80;
server_name localhost;
server_name_in_redirect on;
location /frx {
if (-d $request_filename){ # 如果请求的资源目录存在
rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; # $2 获取第二个括号的值:/
}
}
}
# $1 是第一个括号的值,$2 是第二个括号的值。
proxy_pass
不增加目录
- 这里将发送 http://192.168.199.27/frx/xu 请求。
案例 | location | proxy_pass | 匹配 |
---|---|---|---|
1 | /frx | http://192.168.199.27 | /frx/xu |
2 | /frx/ | http://192.168.199.27 | /frx/xu |
3 | /frx | http://192.168.199.27/ | //xu |
4 | /frx/ | http://192.168.199.27/ | /xu |
总结
- 如果proxy_pass后面不加/,则会追加全部请求到地址后面
- 如果proxy_pass后面加/,则会去除请求和location的匹配字符串
增加目录
- 这里将发送 http://192.168.199.27/frx/xu 请求。
案例 | location | proxy_pass | 匹配 |
---|---|---|---|
1 | /frx | http://192.168.199.27/bing | /bing/xu |
2 | /frx/ | http://192.168.199.27/bing | /bingxu |
3 | /frx | http://192.168.199.27/bing/ | /bing//xu |
4 | /frx/ | http://192.168.199.27/bing/ | /bing/xu |
总结
- 如果proxy_pass后面有目录,有没有’/',Nginx都会将匹配 location 的内容从请求路径中剔除,然后将请求路径剩余的字符串拼接到 proxy_pass 后生成新的请求路径
举例:proxy_pass 的 ip:port 后接了字符串,因此将 location 的 /frx/ 从原请求路径 /frx/xu 中剔除,变为 xu,然后将 xu 拼接到 http://192.168.1.48/bing 后生成了新请求,因此其他地址收到的请求就是 /bingxu。
root和alias
总结
- root 的处理结果是: root 路径 + location 路径
- alias 的处理结果是:使用 alias 路径替换 location 路径
- alias 是一个目录别名的定义,root 则是最上层目录的含义
- 如果 location 路径是以 / 结尾,则 alias 也必须是以 / 结尾,root 没有要求
- alias 不支持 location 的 =