问题
最近项目中遇到了一个nginx方面的问题,大概是这样的:
- 目前项目上使用了强缓存策略,该策略的配置规则如下:
1 | location ~* \.(zip|apk)$ { |
即强制html文件不做缓存,然后所有的资源文件全部设置成最大缓存,这样只需要打包构建时,构建的文件是根据hash规则生成的,那么就能保证,浏览器请求资源文件,只会请求一次,没有额外的网络开销(资源变更,hash值变化,对浏览器来说是新的资源文件)。
- 由于需求原因,需要引入一个网盘管理系统,结果导致location规则冲突:
因为网盘系统是一个独立系统,我们只是在登录页面做了一个简单的自动登录逻辑,然后就可以使用iframe嵌套到我们系统,最终效果如下:
但是,因为该系统使用的是cookie验证的方式,单纯的iframe嵌套会导致,cookie无法传递,进而系统登录失败,因此将嵌套地址改成了/resource-service/home.html
,然后使用nginx反向代理到真正的服务器地址,这样就能做到同源了,具体配置如下:
1 | location /resource-service { |
- 使用该策略之后,访问该路径,浏览器一直返回404,删掉其它匹配规则,则可以正常访问,所以肯定是location匹配规则冲突了,那么问题就来了,location的匹配规则是怎样的?
详解
上面的问题,我们先放下,了解了locatin的匹配规则之后,其实答案不言而喻
location语法
引用自:https://blog.csdn.net/luoyang_java/article/details/83507193
=
:精确匹配^~
:表示已某个uri路径开头,即匹配url,这里需要注意的是,nginx不对url做编码,所以匹配/static/20%/images,会被^~ /static/images匹配到(空格被忽略了)~
:表示区分大小写的正则匹配~*
:开头表示不区分大小写的正则匹配!~
:区分大小写不匹配!~*
:不区分大小写不匹配/
:通用匹配,任何请求都会匹配到
精准匹配和一般匹配
location = /resouce-service/
和location /resource-service/
:请求
http://127.0.0.1/resource-service/
的时候,会匹配到前者,后者不会被命中location = /resouce-service
和location /resource-service
:请求
http://127.0.0.1/resource-service/
的时候,会匹配到后者,前者不会被命中location = resouce-service
和location resource-service
:请求
http://127.0.0.1/resource-service/
的时候,会匹配到前者,后者不会被命中location = resouce-service
和location /resource-service/
:请求
http://127.0.0.1/resource-service/
的时候,会匹配到后者,前者不会被命中
所以:路径相同时的精准匹配优先, 必须满足/uri/或者uri,要么两边都加/,要么两边都不加/
一般匹配
location /resouce-service/
和 location /resource-service/images
:
请求http://127.0.0.1/resource-service/images/test.png
时,即匹配到/resouce-service/也能匹配到/resouce-service/images时,按照最长uri匹配优先,所以匹配的是后者
^~开头的规则
location ^~ /resouce-service/
和 location /resource-service/images
和 和 location ~ /resource-service/.*\.(S:png|jpg|gif)
:
加上^~
前缀后,会停止正则匹配,但是会继续匹配一般匹配
所以上面匹配到location ^~ /resouce-service/
后会继续匹配location /resource-service/images
,但是location ~ /resource-service/*\.(S:png|jpg|gif)
不会匹配
精准匹配和正则匹配
location /resouce-service/
和 location /resource-service/.*\.html$
:
如果http://127.0.0.1/resource-service/
精准匹配到前者,所有不会继续匹配后者
如果http://127.0.0.1/resource-service/home.html
会匹配前者,但不是精准匹配,所以会继续匹配后者
正则匹配
location \.html$
和 location ~ ^/resouce-service/.*\.html$
:
会按照编辑顺序,顺序匹配,如上面,会优先匹配前者
@开头的uri
1 | location @resouce-service { |
@开头的uri,如果nginx存在对应页面,则不做反应,如果nginx不存在对应页面,则执行代理,代理到yangxl.cn上
总结
先精准命中,如果命中,立刻返回结果并结束
普通命中,如果命中多个,则按照最长命中解析
如果
^~
开头命中,则不会继续搜索正则命中,但会继续搜索普通命中上面都没有命中,则按照正则规则的顺序查找,找到后返回结果并结束解析
解决
通过上面的解析,我们来分析遇到的问题,很明显请求http://127.0.0.1/resource-service/home.html
时location /resource-service
属于普通命中,会继续执行正则匹配,结果又命中了location ~ .*\.(?:htm|html)$
,导致nginx解析错误
那么,解决方案就可以使用总结中的第三条了,即使用^~
规避正则命中:
1 | location / { |