Content-Length标头已存在

我正在使用Android中包含的Apache HttpClient(4.1)来执行HttpPut。 我已经确认我只有1个内容长度标题。 但是,每次发送请求时,都会收到有关已指定的Content-Length标头的协议exception。

HttpClient client = new DefaultHttpClient(); putMethod = new HttpPut(url + encodedFileName); putMethod.addHeader(..) //<-once for each header putMethod.setEntity(new ByteArrayEntity(data)); client.execute(putMethod); //throws Exception 

引起:org.apache.http.ProtocolException:org.apache.http.protocol.RequestContent.process(RequestContent.java:70)中已经出现的Content-Length头文件位于org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor的.java:290)

有任何想法吗?

我自己没有使用HttpClient,但我怀疑问题是putMethod.setEntity(...)隐式提供内容长度,你也可以通过putMethod.addHeader(...)调用之一显式设置它。

正如igor.zh所指出的,如果使用Spring的HttpComponentsMessageSender类,就会出现这个问题。 更确切地说,如果您将自己的HttpClient实例传递给HttpComponentsMessageSender构造函数,这只是一个问题 – 否则会自动处理该问题。

从spring-ws 2.1.4开始,默认构造函数中使用的HttpComponentsMessageSender.RemoveSoapHeadersInterceptor子类被公开以解决此问题(请参阅https://jira.spring.io/browse/SWS-835 ),因此可以在您自己的HttpClient实例中使​​用,而不是编写自己的类来执行它。 它还会清除HTTP.TRANSFER_ENCODING标头。

使用HttpClientBuilder.addInterceptorFirst方法将此拦截器注入您自己的HttpClient实例。 下面的例子使用XML bean连线。 如果有人知道构造HttpClient实例的更简洁的方法(除了编写工厂bean类),我全都耳朵!

                     

或者,如果可以的话,只需允许HttpComponentsMessageSender构建自己的HttpClient实例,而不是将其传递给它。 关于这一点的注意事项:从spring-ws 2.2.0-RELEASE开始,HttpComponentsMessageSender的默认构造函数继续使用DefaultHttpClient类,现在不推荐使用它。 希望这将在未来的版本中得到解决。

当我使用http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/transport/http/HttpComponentsMessageSender.html作为Spring WebService Message Sender时,这种情况发生在我身上。 在这种情况下,像HttpPut或HttpRequest这样的东西不容易访问,因此,使用HttpClientBuilder构建HttpClient,我最终在罪魁祸首RequestContent之前插入了一个HttpRequestInterceptor:

 private static class ContentLengthHeaderRemover implements HttpRequestInterceptor{ @Override public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { request.removeHeaders(HTTP.CONTENT_LEN);// fighting org.apache.http.protocol.RequestContent's ProtocolException("Content-Length header already present"); } } ... HttpClientBuilder httpClientBuilder = HttpClients.custom(); httpClientBuilder.addInterceptorFirst(new CcontentLengthHeaderRemover()); 

John Rix的回答是正确的。 以下是使用普通java的方法:

 HttpClient client = HttpClients.custom() .addInterceptorFirst(new RemoveSoapHeadersInterceptor()) .build(); 

如果您查看http://docjar.org/docs/api/org/apache/http/protocol/RequestContent.html,您会注意到如果您自己设置它会抛出该exception。 因此,内部工作自动设置内容长度。 这也意味着,要将其设置为“0”,您需要将实体设置为null。