httpclient-4.5.9.jar

org.apache.http:

auth     身份

client    端

conn     连接

cookie  本地

impl:    实现

execchain   异常

httpcore-4.4.11.jar

org.apache.http.entity;

  1. AbstractHttpEntity

http请求体包报文格式:

Content-Type:                  报文类型:application/json;charset=utf-8

Content-Encoding:            编码方式:gzip或deflate

Content-Length:               报文长度:

Chunked:                         是否分块传输

Content-Length, HTTP消息长度, 用十进制数字表示的八位字节的数目. 一般情况下, 很多工作都被框架完成, 我们很少去关注这部分内容, 但少数情况下发生了Content-Length与实际消息长度不一致, 程序可能会发生比较奇怪的异常, 如:

  • 无响应直到超时.
  • 请求被截断, 而且下一个请求解析出现错乱.

Content-Length是HTTP消息长度, 用十进制数字表示的八位字节的数目, 是Headers中常见的一个字段. Content-Length应该是精确的, 否则就会导致异常 (特别地, HTTP1.0中这个字段可有可无).

Content-Length首部指示出报文中实体主体的字节大小. 这个大小是包含了所有内容编码的, 比如, 对文本文件进行了gzip压缩的话, Content-Length首部指的就是压缩后的大小而不是原始大小.

Content-Length是如何工作的

Content-Length使用十进制的数字表示了消息的长度, 服务端/客户端通过它来得知后续要读取消息的长度.

 
image
 
image

如果这个长度不正确, 会发生如下情况:

Content-Length > 实际长度

如果Content-Length比实际的长度大, 服务端/客户端读取到消息结尾后, 会等待下一个字节, 自然会无响应直到超时.

 
image

同样地, 在响应消息中Content-Length超过实际长度也是一样的效果:

 
image
 
image

Content-Length < 实际长度

如果这个长度小于实际长度, 首次请求的消息会被截取, 比如参数为param=piaoruiqingContent-Length为10, 那么这次请求的消息会被截取为: param=piao, 如图所示:

 
image
 
image

但, 仅仅是如此吗, 当然不, 我们再来看看第二次请求会发生什么让人意外的事情, 如图:

 
image

连续的两次请求, 第一次消息被截断, 而第二次没有发生预期的截断, 而是服务端抛出了异常: Request method 'ruiqingPOST' not supported.刺不刺激 (ノ)゚Д゚( )

那 ruiqingPOST是个什么神仙方法??? 此时, 凭着多年开发(DEBUG)经验练就的敏感度, 我们大致可以猜出, 上一次请求被截取剩下的消息, 在这次请求出现了. 掏出wireshark来验证一下, 如图:

 
image

导致这种情况的原因就是开启了Connection:keep-alive, 如果使用Connection:close, 所产生的现象就是每一次的请求都被截断, 但不会产生解析混乱(如将上一次剩下的消息拼接到后续的请求消息中).

不确定Content-Length的值怎么办

Content-Length首部指示出报文中实体主体的字节大小. 但如在请求处理完成前无法获取消息长度, 我们就无法明确指定Content-Length, 此时应该使用Transfer-Encoding: chunked

什么是Transfer-Encoding: chunked

数据以一系列分块的形式进行发送. Content-Length 首部在这种情况下不被发送. 在每一个分块的开头需要添加当前分块的长度, 以十六进制的形式表示,后面紧跟着 \r\n , 之后是分块本身, 后面也是\r\n. 终止块是一个常规的分块, 不同之处在于其长度为0.

Transfer-Encoding: chunked是如何工作的

接下来我们用一个下载文件的例子, 来探讨Transfer-Encoding: chunked是如何工作的. 服务端代码如下:

 
image

使用postman发起请求, wireshark抓包查看, 如图:

 
image

在wireshark中可以很清晰地看到chunked的数据, 其结构大致是: 返回的消息被分为多个数据块, 每个数据块有两部分, 长度 + 数据, 这两部分都以CRLF(即\r\n)结尾. 而终止块是一个特殊的数据块, 其长度为0, 如图:

 
image

如此, 即完成了分块编码. 其主要应用于如下场景, 即要传输大量的数据, 但是在请求在没有被处理完之前响应的长度是无法获得的. 例如, 当需要用从数据库中查询获得的数据生成一个大的HTML表格、需要传输大量的图片等.

  • Content-Length如果存在且生效, 必须是正确的, 否则会发生异常.(大于实际值会超时, 小于实际值会截断并可能导致后续的数据解析混乱)
  • 如果报文中包含Transfer-Encoding: chunked首部, 那么Content-Length将被忽略.
  • @转自:https://blog.piaoruiqing.com.

http请求中的Content-Length作用机制与分块chunked的更多相关文章

  1. SSM项目中用ajax尝试实现controller请求中重定向不起作用的问题

    首先我在controller中有一个添加数据的方法: @RequestMapping(value="/emp",method=RequestMethod.POST) public ...

  2. HTTP请求中浏览器的缓存机制

    摘要:在Web开发过程中,我们可能会经常遇到浏览器缓存的问题.本文作者详细解释了浏览器缓存的机制,帮助读者更深层次的认识浏览器的缓存. 流程 当资源第一次被访问的时候,HTTP头部如下 (Reques ...

  3. HTTP请求中的缓存(cache)机制

    http://www.chaorenmao.com/blog/?p=79 流程 当资源第一次被访问的时候,HTTP头部如下 (Request-Line)  GET /a.html HTTP/1.1Ho ...

  4. Ajax请求中的async:false/true的作用【转载】

    [Ajax请求中的async:false/true的作用] 作者:https://www.cnblogs.com/mmzuo-798/p/7098979.html 前言: 昨天在做倒计时修改的时候,发 ...

  5. [翻译] Python 3.5中async/await的工作机制

    Python 3.5中async/await的工作机制 多处翻译出于自己理解,如有疑惑请参考原文 原文链接 身为Python核心开发组的成员,我对于这门语言的各种细节充满好奇.尽管我很清楚自己不可能对 ...

  6. Http请求中Content-Type讲解以及在Spring MVC中的应用

    引言: 在Http请求中,我们每天都在使用Content-type来指定不同格式的请求信息,但是却很少有人去全面了解content-type中允许的值有多少,这里将讲解Content-Type的可用值 ...

  7. URL中“#” “?” &“”号的作用

    URL中"#" "?" &""号的作用   阅读目录 1. # 2. ? 3. & 回到顶部 1. # 10年9月,twit ...

  8. RL中“#” “?” &“”号的作用

    阅读目录 1. # 2. ? 3. & 回到顶部 1. # 10年9月,twitter改版.一个显著变化,就是URL加入了"#!"符号.比如,改版前的用户主页网址为http ...

  9. HTTP请求中的Body构建——.NET客户端调用JAVA服务进行文件上传

    PS:今日的第二篇,当日事还要当日毕:)   http的POST请求发送的内容在Body中,因此有时候会有我们自己构建body的情况. JAVA使用http—post上传file时,spring框架中 ...

随机推荐

  1. Angular前端开源框架

    1.  项目框架介绍 本项目采用了开源项目ngx-admin作为脚手架.基于Angular 8 +,Bootstrap 4+和Nebular,ngx-admin是最受欢迎的后台管理模板,是用于个人和商 ...

  2. zrender笔记----(数字Number组件)出现的问题和解决办法

    1.期望的效果是这样子的(这也是最终结果): 2.开始是用json假数据,开始没考虑null的问题,导致在判断传值处,判断有误. 导致在对接接口时,凌乱了,后来修改了下变成后面图C的逻辑,json数据 ...

  3. 转:HTML5 History API 详解

    从Ajax翻页的问题说起 请想象你正在看一个视频下面的评论,在翻到十几页的时候,你发现一个写得稍长,但非常有趣的评论.正当你想要停下滚轮细看的时候,手残按到了F5.然后,页面刷新了,评论又回到了第一页 ...

  4. luogu 4381 [IOI2008]Island 单调队列 + 基环树直径 + tarjan

    Description 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样 ...

  5. C++ 对象间通信框架 V2.0 ××××××× 之(二)

    公共头文件:ss_type_def.h ================================================================================ ...

  6. (23)C++/Python项目练习一

    逆转字符串——输入一个字符串,将其逆转并输出. Python: def rev(s): return (s[::-1]) s =input("请输入一个字符串:") a = rev ...

  7. spring util包 StringUtils工具类中的isEmpty() 方法解析

    今天在公司看到同事写的代码,无意发现在判断字符串类型时,使用的是StringUtils工具类中的isEmpty()去判断如下所示 @RequestMapping(value = "/pub/ ...

  8. MySQL主从复制 报错处理

    基于GTID的主从复制: 跳过一个事务: SET @@session.gtid_next = '冲突的GTID号';BEGIN;COMMIT; SET gtid_next = 'AUTOMATIC';

  9. 《图解 TCP-IP(第 5 版)》

    第一章 网络基础知识 计算机网络根据规模可以分为:广域网(WAN: Wide Area Network)和局域网(LAN: Local Area Network) 协议的标准化: 国际标准化组织(IS ...

  10. 小程序框架MpVue踩坑日记(二)

    数据嵌套超过三层或者等于三层的时候 父组件传值给子组件后,如果子组件内的值需要改变 通过this.emit()传值后,父组件的值虽然会改变,但是视图并不会重新渲染 原因就是数据嵌套太多,没有触发ren ...