IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> HTTP请求头大小写问题踩坑记录 -> 正文阅读

[网络协议]HTTP请求头大小写问题踩坑记录

场景

类似网关的需求做请求转发,大概是接收到客户端http请求后做简单处理,之后通过httpclient转发出去,其中请求头需要全部透传过去。但是直接全部无脑传过去会出现问题,比如因为处理过请求,所以长度已经变了,客户端的请求头content-length已经不再适用了,再比如如果客户端设置了accept-encoding请求头,因为压缩过所以要处理结果比较麻烦。所以这两个请求头不直接传过去。所以就出现一下代码,遍历请求头的key之后设置httpclient请求参数中,排除这两个请求头。

//请求头透传
Enumeration<String> keys = request.getHeaderNames();
while(keys.hasMoreElements()) {
	String key = keys.nextElement();
	//将请求头accept-encoding去掉防止用户携带后服务器返回压缩的内容处理比较麻烦
	if ("accept-encoding".equals(key)) {
		continue;
	}
	//将请求头content-length,长度需要重新计算
	if ("content-length".equals(key)) {
		continue;
	}
	String value = req.getHeader(key);
	httpRequest.setHeader(key, value);
}

直接写常量很不优雅,万一常量有变化岂不是很难找修改的地方,所以就使用spring提供的请求头常量做修改如下

//请求头透传
Enumeration<String> keys = request.getHeaderNames();
while(keys.hasMoreElements()) {
	String key = keys.nextElement();
	//将请求头accept-encoding去掉防止用户携带后服务器返回压缩的内容处理比较麻烦
	if (HttpHeaders.ACCEPT_ENCODING.equals(key)) {
		continue;
	}
	//将请求头content-length,长度需要重新计算
	if (HttpHeaders.CONTENT_LENGTH.equals(key)) {
		continue;
	}
	String value = req.getHeader(key);
	httpRequest.setHeader(key, value);
}

结果发现没能过滤掉这两个请求头,断点一看原来HttpServlet传过来的请求头是全部小写的比如content-length,但是spring定义的常量是首字母大写的比如Content-Length。这不都是http协议竟然还有这种不同,两个都遵守协议应该一样的,而且前端传参是首字母大写的,到HttpServlet就变成小写了,HttpServlet是tomcat传过来的,是不是tomcat做了什么特殊处理?

分析

经过查阅资料和网上找答案,原来http协议header字段名大小写不敏感。https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html
所以spring的首字母大写常量或者tomcat全部转成小写也是合规的
在这里插入图片描述
知道了这个前提就问题就好解决,既然大小不敏感那么判断相等的时候都转成小写再判断即可。
但是好奇一个问题,既然大小不敏感那么tomcat全部处理成小写字母,万一用户通过getHeader获取请求头使用大写呢?猜想肯定时getHeader()方法做过处理,跟进代码就能找到答案了,跟进tomcat的HttpServletRequest 最后找到如下代码,方法equalsIgnoreCase()看名字就看出来,当用户通过getHeader()时是做了忽略大小写判断的。很容易相通,既然http协议要求大小写不敏感,那么保存的时候怎么存都得,但是取出来的时候需要做忽略大小写判断才符合http协议的要求。

    public MessageBytes getValue(String name) {
        for (int i = 0; i < count; i++) {
            if (headers[i].getName().equalsIgnoreCase(name)) {
                return headers[i].getValue();
            }
        }
        return null;
    }

解决

http协议header字段名大小写不敏感的,所以每个框架的写法可能都不一样,如果需要判断请求头相等需要都考虑,即全部转成大写或者小写再判断即可。如下

//请求头透传
Enumeration<String> keys = request.getHeaderNames();
while(keys.hasMoreElements()) {
	String key = keys.nextElement();
	//将请求头accept-encoding去掉防止用户携带后服务器返回压缩的内容处理比较麻烦
	if (HttpHeaders.ACCEPT_ENCODING.toLowerCase().equals(key.toLowerCase())) {
		continue;
	}
	//将请求头content-length,长度需要重新计算
	if (HttpHeaders.CONTENT_LENGTH.toLowerCase().equals(key.toLowerCase())) {
		continue;
	}
	String value = req.getHeader(key);
	httpRequest.setHeader(key, value);
}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 23:05:00  更:2022-04-07 23:06:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:23:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码