2018年4月

关于 http 1.1 header Transfer-Encoding 的用法

关于 Transfer-Encoding 在官方文档中有以下几个点要注意:

  1. 它是 Hop to Hop 的 header, 也就是中间代理可以改的, 并不是 end to end 的 header;
  2. 它是传输编码, 并不是 content-encoding, content-encoding 是 end to end;
  3. 可能的值有: chunked, compress, deflate, gzip, identity. 可以是多个, 用逗号隔开;
  4. 如果是 chunked, 因为预先不知道内容长度, 所以 Content-Length 是不需要的;
  5. 如果有 chunked, chunked 必须在逗号隔开的最后一个;
  6. HTTP/1.1 应用程序必须能够编码/解码 chunked;
  7. identity 代表原样传输, 没有编码, 必须永远被接受;
  8. 在 request 的 header 中的 TE, 其实是 Accepted-Transfer-Encoding 的缩写;

比较容易混淆, 官方文档有没有说明的是:
尽管 Transfer-Encoding 是一个 response header, 可是在 request 的 header 中也可以使用这个 header, 并且服务端都能处理. 参考下面这 2 处文章:

If a Transfer-Encoding field with a value of "chunked" is specified in
an HTTP message (either a request sent by a client or the response
from the server)
Chunking is most often used by the server for responses, but clients
can also chunk large requests

另外在 Tomcat8 的实现中, org.apache.coyote.http11.Http11Processor 的类的 prepareRequest() 方法中, 我们可以看到具体的对于 Transfer-Encoding 的处理方法. 其中包含对于 request 使用 chunked 处理.

使用 Curl 测试 content-length 和 payload 的数据量不一致的问题:

curl -X POST http://localhost:8080/post --header "Content-Type:application/json" --header "content-length: 2" --header "transfer-encoding:abc" --data "{"

更多内容, 参考: rfc7230, RFC2616
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding

关于 Java Socket 和 TCP 连接的相关问题

这个问答解释了 Socket 和 TCP 的 level 问题.
https://stackoverflow.com/questions/10240694/java-socket-api-how-to-tell-if-a-connection-has-been-closed

这篇文章介绍了 Socket close() 和 TCP 的 FIN, RST 的相关问题.
https://docs.oracle.com/javase/8/docs/technotes/guides/net/articles/connection_release.html

查看 JDK 源代码: SocketInputStream 和 SocketOutputStream 的 read 和 write 方法, 可以看到只有在 read 和 write 的时候才能知道这个 tcp 连接的状态.

对于 NIO 可以更快的知道这个消息.

HttpClient 库的介绍中, 有关于如何关掉 idle 和 expired 的连接问题:
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e373