HttpClient:禁用分块编码
我正在使用 Apache Commons HttpClient 和 Restlet 来调用 Restful Web 服务。不幸的是,我的服务器(基于 Ruby on Rails)不喜欢 HttpClient 默认使用的 Transfer-Encoding: chunked
。
有什么方法可以禁用客户端 POST 的分块编码吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
作为一般规则,为了不分块请求,您需要指定帖子正文的确切大小,这对于动态生成的数据意味着您需要在内存中缓冲整个响应,查看其大小然后才发送它。
Apache客户端文档似乎证实了这一点:
AbstractHttpEntity.setChunked()
状态As a general rule, for request not to be chunked, you need to specify exact size of post body, which for dynamically generated data means you need to buffer entire response in memory, see its size and only then send it.
Apache client documentation seems to confirm this:
AbstractHttpEntity.setChunked()
states正如 Restlet 邮件列表中所述,在 Restlet 2.1 版本中,您可以将 ClientResource#entityBuffering 属性设置为 true 以将内容缓存在内存中并防止分块编码。
As said in Restlet mailing list, in Restlet version 2.1, you can set ClientResource#entityBuffering property to true to cache content in memory and prevent chunked encoding.
正如 @Slartibartfast 在他的回答中暗示的那样,最可靠的方法是显式将 HttpPost 切换到 HTTP 1.0 协议。
将 apache HttpPost 请求设置为 HTTP 1.0 协议(与 HttpGet 相同,如果您需要这个...):
HttpPost httpPost = new HttpPost(someUrl);
httpPost.setProtocolVersion(HttpVersion.HTTP_1_0); // 自 Apache HttpClient v.4.3 起
创建 Multipart post 请求时,提供附件作为输入,而不是输入流(对于 HTTP 1.1,这会导致分块编码),而是一个字节数组,您必须创建该数组事先来自同一个流。这就是内容长度已知的原因。请参阅 org.apache.http.entity.mime.MultipartEntityBuilder.addBinaryBody(String, byte[], ContentType, String)
我对此进行了 Android 开发测试,需要稍微不同的类名...(请参阅 https://github.com/andstatus/andstatus/issues/249 )
The most reliable way, as @Slartibartfast hinted in his answer, is to explicitly switch HttpPost to HTTP 1.0 protocol.
Set apache HttpPost request to HTTP 1.0 protocol (the same for HttpGet, if you need this...):
HttpPost httpPost = new HttpPost(someUrl);
httpPost.setProtocolVersion(HttpVersion.HTTP_1_0); // Since v.4.3 of Apache HttpClient
When creating Multipart post request provide as an input for an attachment not an InputStream (as for HTTP 1.1, which causes chunked encoding), but an array of bytes, which you have to create from the same stream beforehand. This is why content length is known. See org.apache.http.entity.mime.MultipartEntityBuilder.addBinaryBody(String, byte[], ContentType, String)
I tested this for Android development, that required slightly different class names... (see https://github.com/andstatus/andstatus/issues/249 )