互联网应用中,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的配置描述,概要总结如下图: