NGINX处理//(双斜杠)问题_nginx //-程序员宅基地

技术标签: nginx  负载均衡  NGINX  http  linux运维  

问题引入

最近开发同事反馈在服务器内读取到的url在一个特定的地方多了一个/,本来应该是http://example.domain.url/servername/appname/dosomething这样的地址,在服务器上收到的地址为http://example.domain.url/servername//appname/dosomething,影响了后续的应用处理。
在应用服务器的前一层恰好是NGINX反向代理。网络硬件截取域名,将http://servername/appname/dosomething丢给NGINX进行分发,NGINX通过配置upstream负载均衡,再通过proxy_pass拼接新的url,通过proxy_set_header重定义请求头。而在做转发的时候正是将servername替换为实际的服务器IP:PORT,这个操作看起来是影响服务的关键节点。

原先配置

# upstream part
upstream servername {
    
     server 192.168.100.1:8888;
     server 192.168.100.2:8888;
     check interval=5000 rise=1 fall=3 timeout=4000;
}
..........
# proxy_pass part
location /servername/   {
    
      proxy_pass http://servername/appname/;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Request-Context http://$host:$server_port/servername/;
      proxy_set_header X-Real-IP $remote_addr;
}

怀疑是proxy

location后带/不带/,proxy_pass后带/不带/,查资料发现不同位置会影响url转义结果,那么会不会遵循完整替换原则呢?

1
location /pass/ {
    
      proxy_pass http://localhost:8080;
}
# http://localhost:8080/pass/xxx
}
2
location /pass/ {
    
      proxy_pass http://localhost:8080/;
}
# http://localhost:8080/xxx
}
3
location /pass {
    
      proxy_pass http://localhost:8080;
}
# http://localhost:8080/xxx
}
4
location /pass {
    
      proxy_pass http://localhost:8080/;
}
# http://localhost:8080//xxx
}

这四种情况看起来是有三种结果,不过为了验证可以再进阶一下:

5
location /pass/ {
    
      proxy_pass http://localhost:8080/app;
}
# http://localhost:8080/appxxx
}
6
location /pass/ {
    
      proxy_pass http://localhost:8080/app/;
}
# http://localhost:8080/app/xxx
}
7
location /pass {
    
      proxy_pass http://localhost:8080/app;
}
# http://localhost:8080/app/xxx
}
8
location /pass {
    
      proxy_pass http://localhost:8080/app/;
}
# http://localhost:8080/app//xxx
}

可以看到2 3 6 7的方式是正确的,location部分结尾带/则proxy_pass部分结尾带/,location部分结尾不带/则proxy_pass部分结尾不带/,完整的遵从同义替换。因此本身我们的配置文件在这边书写是没错的。

怀疑是应用

那么是不是应用本身的问题导致的呢?
假想会不会是应用bug或者配置的问题导致应用接收的url错误,其实nginx转发并没有问题。
为了判断该问题,只能抓包。
在服务器安装了wireshark,过滤掉非http包,发现携带的url确实是http://example.domain.url/servername//appname/dosomething这样的,问题还是在nginx上面。

是proxy_set_header吗?

删除proxy_set_header里的/变成了

# upstream part
upstream servername {
    
     server 192.168.100.1:8888;
     server 192.168.100.1:8888;
     check interval=5000 rise=1 fall=3 timeout=4000;
}
..........
# proxy_pass part
location /servername/   {
    
      proxy_pass http://servername/appname/;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Request-Context http://$host:$server_port/servername;
      # 注意servername后面的/去掉了
      proxy_set_header X-Real-IP $remote_addr;
}

再进行抓包,url变成http://example.domain.url/servername/appname/dosomething正常了,看来罪魁祸首找到了。

为什么是proxy_set_header

proxy_set_header用来重新定义或添加字段传递给代理服务器的请求头。在没有定义proxy_set_header时会继承之前定义的值。也就是如果前道网络设备修改了请求头以后,nginx不作修改的话会原样转发请求头;但是也可以修改里面的文本和变量或者是它们的组合。
那么X-Forwarded-Request-Context修改的是请求头的哪一部分就是现在要了解的重点了,这个参数确实过于冷门,翻遍全网只有在esri的问答网站有这样一个回答(回答地址

X-Forwarded-Url-Base: web adaptor context
X-Forwarded-Request-Context: this appears to be the same as the web context url setting
webAdaptorID: web adaptor id
X-Forwarded-For: an external ip

这里就是设置web url的,并且目前看到只有arcgis的应用读取这个设置,看来确实会影响web url,但是为什么不遵循跟proxy_pass一样的替换原则,这个只有该模块的开发者才能知道了。注意proxy_set_header 来自内置模块ngx_http_proxy_module,不属于第三方模块。
那么不如来引申一下,深入了解一下proxy_set_header模块。这个后续会单独写一篇博客。

另一种处理//问题

在查找这个问题的时候,我看到了另一个NGINX处理//的方式。地址

前端引用css,js时如果写的…/…/之类的引用方式,那么在访问链接中加入多个斜杠会导致引用失败.
可以通过nginx对多个斜杠进行处理
如访问 public//view//a//test.html 重定向到 public/view/a/test.html

merge_slashes off;
rewrite (.*)//(.*) $1/$2 permanent;

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/algebra007/article/details/119429795

智能推荐

unique_lock_unique_lock unique_lock-程序员宅基地

文章浏览阅读122次。//一.unique_lock取代lock_guard//unique_lock 是个类模板,工作中,一般lock_guard(推荐使用);lock_guard 取代了lock()和unlock()//unique_lock 比lock_guard 灵活很多;效率上差一点,内存占用多一点。//二.unique_lock的第二个参数://2.1:std::adopt_lock:起标记作用,表示这个互斥量已经被lock了(所以必去把互斥量提前lock了,否则会报异常)//2.2:std::try_to_unique_lock unique_lock

2D-Position _position_ids 2d-程序员宅基地

文章浏览阅读678次。2D-Position 允许通过拖曳移动绝对定位的对象。 AbsolutePosition 设定元素的 position 属性为“absolute”(绝对)。 BackColor 设置或获取当前选中区的背景颜色。 BlockDirLTR 目前尚未支持。 BlockDirRTL 目前尚未支持。 Bold 切换当前选中区的粗体显示与否。 BrowseMode 目前尚未支持。 Copy 将当前选中区复制_position_ids 2d

ASP.NET 4.0 专题实务(II) – 范例应用与4.0新功能(VB / C#双语法)的「勘误表」-程序员宅基地

文章浏览阅读106次。虽然这几本是在台湾出版、发行的,但仍有少数的朋友在内地买到。为了提供售后服务,我也公布书本的「勘误表」。谢谢各位的支持。ASP.NET 4.0 專題實務(II) – 範例應用與4.0新功能(VB / C#雙語法)(松崗出版)ASP.NET 4.0 专题实务(II) – 范例应用与4.0新功能(VB/ C#双语法)(松岗出版)================..._asp.net专题实务

css选择器nth-child(n)、first-child、last-child_css nth-child(n)匹配元素为-程序员宅基地

文章浏览阅读797次。> 1:nth-child(n)选择器匹配父元素中的第n个子元素。1: nth-child(3)选择列表的第三个元素p:nth-child(3){background:#ccc;}2: nth-child(2n) 选择列表中的偶数标签 2 4 6 8 nth-child(2n-1) 选择列表中的偶数标签 1 3 5 7p:nth-child(2n/2n-1){..._css nth-child(n)匹配元素为

wolfSSL_connect失败错误码-188_ssl error 188-程序员宅基地

文章浏览阅读1.3k次。记录:wolfssl使用过程中遇到,调用wolfSSL_connect返回值小于0,wolfSSL_get_error得到错误码为-188;wolfcrypt/error_crypt.h中对错误码定义为: ASN_NO_SIGNER_E = -188, /* ASN no signer to confirm failure */查找网上资料比较少,官方论坛解答..._ssl error 188

品牌如何在抖音提高产品转化?_品牌抖音内容号如何转化销售-程序员宅基地

文章浏览阅读269次。如何提高品牌产品转化_品牌抖音内容号如何转化销售

随便推点

linux 进程间使用unix socket通信_linux unix socket-程序员宅基地

文章浏览阅读1.2w次,点赞6次,收藏41次。前言:前些天实现了unix socket的通信,本想完完全全自己写一篇博客记录下来,但写的时候发现对于socket知识的理解还有所欠缺,故引用其他博客写的比较好的部分综合一下,这样让大家更容易理解。一、Unix socket概述(参考于博客http://blog.csdn.net/bingqingsuimeng/article/details/8470029):socket API_linux unix socket

ignite客户端调用报错 Ignite instance with provided name doesn't exist_org.apache.ignite.igniteillegalstateexception: gri-程序员宅基地

文章浏览阅读1.2k次。Disconnected from the target VM, address: '127.0.0.1:58990', transport: 'socket'Exception in thread "main" class org.apache.ignite.IgniteException: Remote job threw user exception (override or implem..._org.apache.ignite.igniteillegalstateexception: grid is in invalid state to p

YOLOv8项目实践——目标检测、实例分割、姿态估计、目标追踪算法原理及模型部署(Python实现带界面)-程序员宅基地

文章浏览阅读1.9k次,点赞39次,收藏16次。这是一个集成了YoloV8目标检测、实例分割、姿态估计与目标追踪的项目,界面是用PyQt5写的,可以读入图像,视频与摄像头。

英文文本处理与NLTK库_英文分词的步骤包括( )。根据空格拆分单词 去停用词 提取词干 规则映射 我的答案:-程序员宅基地

文章浏览阅读2.2k次,点赞2次,收藏26次。英文文本处理:有分词,去停用词,提取词干,词性分析,依赖分析,命名实体识别等步骤。目的是为了文本分类建模和文本相似度建模做到更高的准确率。后面会用到深度学习提高准确率。1.英文文本处理与NLTK库文本处理解决分类,解决情感分析,解决翻译等等一系列问题。接下来我们来看一下,在英文文本当中,基本的处理文本的一些操作。1.1 英文Tokenization(标记化/分词)不能直接送到模型当中进..._英文分词的步骤包括( )。根据空格拆分单词 去停用词 提取词干 规则映射 我的答案:

如何在react的Hook中异步请求数据_react hook 异步请求-程序员宅基地

文章浏览阅读3.9k次。如何在react的Hook中请求数据原文:How to fetch data with React Hooks?In this tutorial, I want to show you how to fetch data in React with Hooks by using the state and effect hooks. We will use the widely known Hacker News API to fetch popular articles from the tech_react hook 异步请求

mysql 日期类型比价_MySQL 日期时间类型怎么选?-程序员宅基地

文章浏览阅读116次。构建数据库写程序避免不了使用日期和时间,对于数据库来说,有多种日期时间字段可供选择,如 timestamp 和 datetime 以及使用 int 来存储 unix timestamp。不仅新手,包括一些有经验的程序员还是比较迷茫,究竟我该用哪种类型来存储日期时间呢?那我们就一步一步来分析他们的特点,这样我们根据自己的需求选择合适的字段类型来存储 (优点和缺点是比较出来的 , 跟父母从小喜欢拿邻..._mysql timestamp比价

推荐文章

热门文章

相关标签