SHIHUC

好记性不如烂笔头,还可以分享给别人看看! 专注基础算法,互联网架构,人工智能领域的技术实现和应用。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

nginx路径匹配中斜线的研究

Posted on 2021-04-04 15:05  shihuc  阅读(791)  评论(0编辑  收藏  举报

互联网应用中,nginx的作用算是一个非常典型且牛逼的存在,它让分布式应用部署变得简洁高效,尤其是在反向代理的配置部署中,nginx的简单易用,功能强大,性能优越。。。

但是,因为nginx的功能强大,很大一部分来源于url的规则匹配的配置相对容易让人摸不着头脑,尤其是斜线的使用,什么时候有,什么时候不需要,今天,我就将location和proxy_pass后面的配置是否带斜线,有无斜线的作用差异,通过案例分析,然后给出一个简单的总结,方便自己也方便读者掌握,当然,自己看nginx的技术文档,也可以找到自己所需要的技巧。

 

1. 环境配置信息

系统的基础配置信息,所有的请求默认都到这个路径。在/home/tkiot/www路径下,创建三个基本页面,分别是a.html,b.html,ab.html。

[tkiot@tkiot-nginx1 www]$ pwd
/home/tkiot/www
[tkiot@tkiot-nginx1 www]$ ll
total 4304
drwxrwxr-x 5 tkiot tkiot      95 Aug 28  2019 -
-rw-rw-r-- 1 tkiot tkiot       3 Mar 23 17:53 ab.html
-rw-rw-r-- 1 tkiot tkiot       2 Mar 23 17:53 a.html
-rw-rw-r-- 1 tkiot tkiot       2 Mar 23 17:53 b.html
drwxrwxr-x 3 tkiot tkiot      95 Dec 26  2019 bk
drwxrwxr-x 3 tkiot tkiot      63 Jan  7  2020 cc
-rw-r--r-- 1 tkiot tkiot 1203399 Jul  1  2020 dist7.zip
drwxrwxr-x 3 tkiot tkiot      57 Nov 28  2019 document
drwxrwxr-x 3 tkiot tkiot      62 Aug  6  2020 download
drwxrwxr-x 3 tkiot tkiot      52 Sep 12  2019 error
-rw-rw-r-- 1 tkiot tkiot  293864 Jun  5  2020 f1a80a6a56341b8b1e27.worker.js
-rw-rw-r-- 1 tkiot tkiot    4286 Jun  5  2020 favicon.ico
-rw-rw-r-- 1 tkiot tkiot    5521 Jun  5  2020 index.html
drwxrwxr-x 3 tkiot tkiot      57 Jul  1  2020 isc
-rw-rw-r-- 1 tkiot tkiot 2877440 Jun 23  2020 isc.tar
drwxrwxr-x 6 tkiot tkiot      51 Jan  7  2020 static

静态路由配置信息如下:

location / {
    root   /home/tkiot/www;
    index  index.html index.htm;
}

在server层面之外,配置upstream,就是代理本地的静态文件

upstream slashcs {
    server 127.0.0.1:80;
}

 

2. 案例演示与分析

浏览器输入:http://10.95.198.18/hx/a.html
case1:location后面不带斜线,proxy_pass后面不带路径,末尾不带斜线

location /hx {
   proxy_pass http://slashcs;
}

nginx日志信息错误:

127.0.0.1 - - [04/Apr/2021:14:52:48 +0800] "GET /hx/a.html HTTP/1.0" 404 577 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
10.94.100.131 - - [04/Apr/2021:14:52:48 +0800] "GET /hx/a.html HTTP/1.1" 404 577 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"

因为/home/tkiot/www目录下没有hx子目录,nginx在/home/tkiot/www下寻找hx/a.html文件,找不到,所以报404

 

浏览器输入:http://10.95.198.18/hx/a.html
case2:location后面不带斜线,proxy_pass后面不带路径,末尾带斜线

location /hx {
   proxy_pass http://slashcs/;
}

nginx日志返回正常:

127.0.0.1 - - [04/Apr/2021:13:02:26 +0800] "GET //a.html HTTP/1.0" 200 2 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
10.94.100.131 - - [04/Apr/2021:13:02:26 +0800] "GET /hx/a.html HTTP/1.1" 200 2 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"

nginx将请求http://10.95.198.18/hx/a.html路径中/hx部分去掉了,相当于请求被转为为http://127.0.0.1:80//a.html.在/home/tkiot/www目录下是可以找到a.html的。这种配置的核心点在于proxy_pass路径后带有/反斜线,这个斜线相当于将location后面写的路径部分,从匹配到的请求url路径中完全去掉,然后将请求url路径中剩余部分追加到proxy_pass所配置的新的请求地址上。这里请求url路径为/hx/a.html,location后面写的路径部分为/hx,去掉/hx后,请求url路径剩余部分为/a.html,追加到http://slashcs/后面,则为http://slashcs//a.html. 注意,这里url路径配置成任意前缀,例如/hhh/xxx/,只要location后面路径部分,将想要去掉的部分写上,就可以是先路径删除。

 

浏览器输入:http://10.95.198.18/hx/b.html
case3:location后面不带斜线,proxy_pass后面带路径,末尾不带斜线

location /hx {
   proxy_pass http://slashcs/a;
}

nginx日志信息错误:

127.0.0.1 - - [04/Apr/2021:13:19:15 +0800] "GET /a/b.html HTTP/1.0" 404 501 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
10.94.100.131 - - [04/Apr/2021:13:19:15 +0800] "GET /hx/b.html HTTP/1.1" 404 501 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"

因为proxy_pass后面带了路径,这个路径将会实现对location部分匹配到的部分路径的删除,然后将请求url的路径剩余部分追加到proxy_pass指向的新的地址后面,所以新的完全地址为http://slashcs/a/b.html,因为整个nginx对应80的server下面,没有/a开头的location配置,所以最终落到 location / 对应的配置中,/home/tkiot/www下面没有a这个目录,所以最终爆出404

 

浏览器输入:http://10.95.198.18/hx/b.html
case4:location后面不带斜线,proxy_pass后面带路径,末尾带斜线

location /hx {
   proxy_pass http://slashcs/a/;
}

nginx日志信息错误:

127.0.0.1 - - [04/Apr/2021:13:25:58 +0800] "GET /a//b.html HTTP/1.0" 404 501 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
10.94.100.131 - - [04/Apr/2021:13:25:58 +0800] "GET /hx/b.html HTTP/1.1" 404 501 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"

分析逻辑和case3是一致的。

 

浏览器输入:http://10.95.198.18/hx/a.html
case5:location后面带斜线,proxy_pass后面不带路径,末尾不带斜线

location /hx/ {
   proxy_pass http://slashcs;
}

nginx日志信息错误:

127.0.0.1 - - [04/Apr/2021:13:29:17 +0800] "GET /hx/a.html HTTP/1.0" 404 577 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
10.94.100.131 - - [04/Apr/2021:13:29:17 +0800] "GET /hx/a.html HTTP/1.1" 404 577 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"

proxy_pass指向的路径后面不带路径也不带斜线的情况,只要location后面的路径部分,和请求的url中的路径部分匹配上,就实现url路径部分前面的信息的替换,实现新的请求。此处,将url路径前面部分http://10.95.198.18替换为http://slashcs,然后将请求的路径/hx/a.html追加到后面,变成新的请求http://slashcs/hx/a.html。因为静态资源路径/home/tkiot/www/hx不存在,所以报404

 

浏览器输入:http://10.95.198.18/hx/a.html
case6:location后面带斜线,proxy_pass后面不带路径,末尾带斜线

location /hx/ {
   proxy_pass http://slashcs/;
}

nginx日志返回正常:

127.0.0.1 - - [04/Apr/2021:13:49:37 +0800] "GET /a.html HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
10.94.100.131 - - [04/Apr/2021:13:49:37 +0800] "GET /hx/a.html HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"

这个路径替换规则很简单,proxy_pass指向的请求拼接上原始url请求路径中去除location部分地址信息后剩余的部分a.html,得到新的请求url:http://slashcs/a.html

 

浏览器输入:http://10.95.198.18/hx/b.html
case7:location后面带斜线,proxy_pass后面带路径,末尾不带斜线

location /hx/ {
   proxy_pass http://slashcs/a;
}

nginx日志返回正常:

127.0.0.1 - - [04/Apr/2021:13:38:01 +0800] "GET /ab.html HTTP/1.0" 200 3 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
10.94.100.131 - - [04/Apr/2021:13:38:01 +0800] "GET /hx/b.html HTTP/1.1" 200 3 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"

这个路径替换规则很简单,proxy_pass指向的请求拼接上原始url请求路径中去除location部分地址信息后剩余的部分b.html,得到新的请求url:http://slashcs/ab.html

 

浏览器输入:http://10.95.198.18/hx/b.html
case7:location后面带斜线,proxy_pass后面带路径,末尾带斜线

location /hx/ {
   proxy_pass http://slashcs/a/;
}

nginx日志返回异常:

127.0.0.1 - - [04/Apr/2021:13:58:47 +0800] "GET /a/b.html HTTP/1.0" 404 501 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
10.94.100.131 - - [04/Apr/2021:13:58:47 +0800] "GET /hx/b.html HTTP/1.1" 404 501 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"

这个路径替换规则很简单,proxy_pass指向的请求拼接上原始url请求路径中去除location部分地址信息后剩余的部分b.html,得到新的请求url:http://slashcs/a/b.html, 因为静态资源路径/home/tkiot/www/a不存在,所以报404

 

3. 归纳总结

通过上面的测试案例,得到一个结论,便于指导配置location的思路。核心就是一句话,看proxy_pass后面指向的新地址是否带有路径信息(这个路径信息很广泛,upstream名称或者IP后面仅仅只有一个斜线/,也算是一个路径,/后面有更为明确的路径,算是具体路径),只要proxy_pass后面新制定的路由地址带有/开头的字符串(/后面可以有0个或者多余0个字符),那么location后面的地址信息将会从客户请求的url部分被去除掉,将剩余的地址信息部分追加到proxy_pass指向的地址后面,构建成一个全新的请求url。

下面结合这个location的配置描述,概要总结如下图: