如何在 apache http 客户端中忽略零 content-length header
How to ignore zero content-length header in apache http client
服务器响应 body 是“[]”并且 Content-Length = 0。当客户端尝试读取提到的响应 body 时,它总是一次得到“-1”。此外,如果我拦截服务器响应并将 Content-Length 更改为“2” - 一切正常。我可以得出结论,当 Content-Length = 0 时 apache http client returns -1,但响应 body 实际上不是空的。我正在寻找即使 Content-length 不正确也能够读取响应 body 的解决方法,即我可以设置 http 客户端以忽略 Content-length header 值吗?我没有机会修改服务器,并且由于某些原因我不能使用 HttpUrlConnection 而不是 apache 客户端。拜托,任何建议。
故障Content-length
的问题是HttpClient不知道响应何时结束,在Keep-Alive连接的情况下,这也会中断此连接上的下一个请求。
最简单的选择是扩展 org.apache.http.impl.entity.LaxContentLengthStrategy 并使其 return 内容长度为“2”,而在 header 中为“0”,但如果长度真的为 0,线程将挂起等待从套接字中读取更多内容:
class MyLaxContentLengthStrategy extends LaxContentLengthStrategy{
public long determineLength(final HttpMessage message) throws HttpException {
final Header contentLengthHeader = message.getFirstHeader(HTTP.CONTENT_LEN);
if (contentLengthHeader != null) {
long contentlen = -1;
final Header[] headers = message.getHeaders(HTTP.CONTENT_LEN);
for (int i = headers.length - 1; i >= 0; i--) {
final Header header = headers[i];
try {
contentlen = Long.parseLong(header.getValue());
break;
} catch (final NumberFormatException ignore) {
}
// See if we can have better luck with another header, if present
}
if (contentlen == 0) {
return 2;
}
}
return super.determineLength(message);
}
}
在 HttpClient 中设置 which 可能有点棘手:
http://mail-archives.apache.org/mod_mbox/hc-httpclient-users/201301.mbox/%3C1359388867.10617.16.camel@ubuntu%3E
从 4.4 开始就更容易了:
ManagedHttpClientConnectionFactory cliConnFactory = new ManagedHttpClientConnectionFactory(
null, null, null,
new MyLaxContentLengthStrategy());
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(cliConnFactory);
HttpClients.custom
.....
.setConnectionManager(cm)
.build();
所以如果你真的不需要带“[]”的body,你可以指示HttpClient关闭这个连接并放弃错误的响应。这可以通过用这样的东西覆盖 org.apache.http.impl.client.DefaultClientConnectionReuseStrategy 来完成:
class MyConnectionReuseStrategy extends DefaultClientConnectionReuseStrategy{
@Override
public boolean keepAlive(final HttpResponse response, final HttpContext context) {
final HttpRequest request = (HttpRequest) context.getAttribute(HttpCoreContext.HTTP_REQUEST);
if (request != null) {
final Header[] contLenHeaders = request.getHeaders(HttpHeaders.CONTENT_LENGTH);
for(Header h : contLenHeaders){
if("0".equalsIgnoreCase(h.getValue())){
return false;
}
}
}
return super.keepAlive(response, context);
}
}
你可以这样设置:
HttpClients.custom
.....
.setConnectionReuseStrategy(new MyConnectionReuseStrategy())
.build();
服务器响应 body 是“[]”并且 Content-Length = 0。当客户端尝试读取提到的响应 body 时,它总是一次得到“-1”。此外,如果我拦截服务器响应并将 Content-Length 更改为“2” - 一切正常。我可以得出结论,当 Content-Length = 0 时 apache http client returns -1,但响应 body 实际上不是空的。我正在寻找即使 Content-length 不正确也能够读取响应 body 的解决方法,即我可以设置 http 客户端以忽略 Content-length header 值吗?我没有机会修改服务器,并且由于某些原因我不能使用 HttpUrlConnection 而不是 apache 客户端。拜托,任何建议。
故障Content-length
的问题是HttpClient不知道响应何时结束,在Keep-Alive连接的情况下,这也会中断此连接上的下一个请求。
最简单的选择是扩展 org.apache.http.impl.entity.LaxContentLengthStrategy 并使其 return 内容长度为“2”,而在 header 中为“0”,但如果长度真的为 0,线程将挂起等待从套接字中读取更多内容:
class MyLaxContentLengthStrategy extends LaxContentLengthStrategy{
public long determineLength(final HttpMessage message) throws HttpException {
final Header contentLengthHeader = message.getFirstHeader(HTTP.CONTENT_LEN);
if (contentLengthHeader != null) {
long contentlen = -1;
final Header[] headers = message.getHeaders(HTTP.CONTENT_LEN);
for (int i = headers.length - 1; i >= 0; i--) {
final Header header = headers[i];
try {
contentlen = Long.parseLong(header.getValue());
break;
} catch (final NumberFormatException ignore) {
}
// See if we can have better luck with another header, if present
}
if (contentlen == 0) {
return 2;
}
}
return super.determineLength(message);
}
}
在 HttpClient 中设置 which 可能有点棘手: http://mail-archives.apache.org/mod_mbox/hc-httpclient-users/201301.mbox/%3C1359388867.10617.16.camel@ubuntu%3E 从 4.4 开始就更容易了:
ManagedHttpClientConnectionFactory cliConnFactory = new ManagedHttpClientConnectionFactory(
null, null, null,
new MyLaxContentLengthStrategy());
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(cliConnFactory);
HttpClients.custom
.....
.setConnectionManager(cm)
.build();
所以如果你真的不需要带“[]”的body,你可以指示HttpClient关闭这个连接并放弃错误的响应。这可以通过用这样的东西覆盖 org.apache.http.impl.client.DefaultClientConnectionReuseStrategy 来完成:
class MyConnectionReuseStrategy extends DefaultClientConnectionReuseStrategy{
@Override
public boolean keepAlive(final HttpResponse response, final HttpContext context) {
final HttpRequest request = (HttpRequest) context.getAttribute(HttpCoreContext.HTTP_REQUEST);
if (request != null) {
final Header[] contLenHeaders = request.getHeaders(HttpHeaders.CONTENT_LENGTH);
for(Header h : contLenHeaders){
if("0".equalsIgnoreCase(h.getValue())){
return false;
}
}
}
return super.keepAlive(response, context);
}
}
你可以这样设置:
HttpClients.custom
.....
.setConnectionReuseStrategy(new MyConnectionReuseStrategy())
.build();