做ajax long polling(POST请求)在firefox 下正常,在chrome下出现如下情况:
如果使用chrome浏览器通过get请求,返回结果也是正常的。
如果通过异步方式访问接口,则请求失败:
通过在服务器端设置response.setConentLength方式解决了问题。
通过比较发现,错误的响应和成功的响应区别在于:Transfer-Encoding: chunked vs Content-Length: 10
也就说如果使用chrunked方式编码,chrome浏览器无法获取chunked编码的消息体长度。在stackoverflow也找到了很多这个问题,都是在chrome浏览器下出现的。
注:response.setConentLength设置消息体的长度参数,是由 "消息体".getBytes(Response.Content-Encoding).length来决定的,如果直接获取 "消息体".length() 字符串的长度因为编码方式不同,导致浏览器获取的数据不完全。
参考:
HTTP Content-Coding Values
Registration Procedures
First Come First Served with specification recommended
Reference
[RFC2616]
Name | Description | Reference | Notes |
compress | UNIX "compress" program method | [RFC2616] | Section 3.5 |
deflate | "zlib" format [RFC1950] with "deflate" compression | [RFC2616] | Section 3.5 |
exi | W3C Efficient XML Interchange | ||
gzip | Same as GNU zip [RFC1952] | [RFC2616] | Section 3.5 |
identity | No transformation | [RFC2616] | Section 3.5 |
pack200-gzip | Network Transfer Format for Java Archives | [JSR 200: Network Transfer Format for Java][Kumar_Srinivasan][John_Rose] |
HTTP Transfer-Coding Values
Registration Procedures
First Come First Served with specification recommended
Reference
[RFC2616]
Name | Description | Reference | Notes |
chunked | Transfer in a series of chunks | [RFC2616] | Section 3.6.1 |
compress | UNIX "compress" program method | [RFC2616] | Section 3.6 |
deflate | "zlib" format [RFC1950] with "deflate" compression | [RFC2616] | Section 3.6 |
gzip | Same as GNU zip [RFC1952] | [RFC2616] | Section 3.6 |
identity | (withdrawn in errata to [RFC2616]) | [RFC2616] | Section 3.6 |
http://www.51testing.com/?uid-390472-action-viewspace-itemid-233985
HTTP 1.1中有两个实体头(Entity-Header)直接与编码相关,分别为Content-Encoding和Transfer-Encoding.
先说Content-Encoding, 该头表示实体已经采用了的编码方式.Content-Encoding是请求URL对应实体(Entity)本身的一部分.比如请求URL为http://host/image.png.gz时,可能会得到的Content-Encoding为gzip.Content-Encoding的值是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity等.
与Content-Encoding头对应,HTTP请求中包含了一个Accept-Encoding头,该头用来说明用户代理(User-Agent,一般也就是浏览器)能接受哪些类型的编码. 如果HTTP请求中不存在该头,服务器可以认为用户代理能接受任何编码类型.
接下来重点描述Transfer-Encoding, 该头表示为了达到安全传输或者数据压缩等目的而对实体进行的编码. Transfer-Encoding与Content-Encoding的不同之处在于:
1, Transfer-Encoding只是在传输过程中才有的,并非请求URL对应实体的本身特性.
2, Transfer-Encoding是一个"跳到跳"头,而Content-Encoding是"端到端"头.
该头的用途举例如,请求URL为http://host/abc.txt,服务器发送数据时认为该文件可用gzip方式压缩以节省带宽,接收端看到Transfer-Encoding为gzip首先进行解码然后才能得到请求实体.
此外多个编码可能同时对同一实体使用,所以Transfer-Encoding头中编码顺序相当重要,它代表了解码的顺序过程.同样,Transfer-Encoding的值也是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity/chunked等.
Transfer-Encoding中有一类特定编码:chunked编码.该编码将实体分块传送并逐块标明长度,直到长度为0块表示传输结束, 这在实体长度未知时特别有用(比如由数据库动态产生的数据). HTTP1.1标准规定,只要使用了Transfer-Encoding的地方就必须使用chunked编码,并且chunked必须为最后一层编码.任何HTTP 1.1应用都必须能处理chunked编码.
与Transfer-Encoding对应的请求头为TE,它主要表示请求发起者愿意接收的Transfer-Encoding类型. 如果TE为空或者不存在,则表示唯一能接受的类型为chunked.
其他与Transfer-Encoding相关的头还包括Trailer,它与chunked编码相关,就不细述了.
顾名思义,Content-Length表示传输的实体长度,以字节为单位(在请求方法为HEAD时表示会要发送的长度,但并不实际发送.).Content-Length受Transfer-Encoding影响很大,只要Transfer-Encoding不为identity,则实际传输长度由编码中的chunked决定,Content-Length即使存在也被忽略.
关于HTTP Message Body的长度
在HTTP中有消息体(Message body)和实体(Entity body)之分,简单说来在没有Transfer-Encoding作用时,消息体就是实体,而应用了Transfer-Encoding后,消息体就是编码后的实体,如下:
Message body = Transfer-Encoding encode(Entity body)
如何确定消息体的长度? HTTP 1.1标准给出了如下方法(按照优先级依次排列):
1, 响应状态(Response Status)为1xx/204/304或者请求方法为HEAD时,消息体长度为0.
2, 如果使用了非"identity"的Transfer-Encoding编码方式,则消息体长度由"chunked"编码决定,除非该消息以连接关闭为结束.
3, 如果存在"Content-Length"实体头,则消息长度为该数值.
3, 如果消息使用关闭连接方式代表消息体结束,则长度由关闭前收到的长度决定. 该条对HTTP Request包含的消息体不适用.