Java 内容长度标头已存在
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3332370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Content-Length header already present
提问by AdamC
I am using the Apache HttpClient (4.1) included in Android to execute a HttpPut. I have verified that I only have 1 content-length header. However, every time I send the request, I get a protocol exception about the Content-Length header already specified.
我正在使用 Android 中包含的 Apache HttpClient (4.1) 来执行 HttpPut。我已经验证我只有 1 个内容长度标头。但是,每次发送请求时,都会收到有关已指定的 Content-Length 标头的协议异常。
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
Caused by: org.apache.http.ProtocolException: Content-Length header already present at org.apache.http.protocol.RequestContent.process(RequestContent.java:70) at org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor.java:290)
引起:org.apache.http.ProtocolException: Content-Length 标头已经存在于 org.apache.http.protocol.RequestContent.process(RequestContent.java:70) at org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor) .java:290)
Any ideas?
有任何想法吗?
采纳答案by Stephen C
I've not used HttpClient myself, but I suspect that the problem is that putMethod.setEntity(...)
is implicitly supplying a content length and you are also setting it explicitly via one of the putMethod.addHeader(...)
calls.
我自己没有使用过 HttpClient,但我怀疑问题在于putMethod.setEntity(...)
隐式提供了内容长度,并且您还通过其中一个putMethod.addHeader(...)
调用显式设置了它。
回答by Prannay
If you checkout http://docjar.org/docs/api/org/apache/http/protocol/RequestContent.htmlyou'll notice that it throws that exception if you've set it yourself. Therefore, the internal working set the content length automatically. This also means, to set it to "0", you need to set the entity to null.
如果您查看http://docjar.org/docs/api/org/apache/http/protocol/RequestContent.html,您会注意到如果您自己设置它会抛出该异常。因此,内部工作自动设置内容长度。这也意味着,要将其设置为“0”,您需要将实体设置为 null。
回答by igor.zh
That happens to me when I used http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/transport/http/HttpComponentsMessageSender.htmlas a Spring WebService Message Sender. In that case the stuff like HttpPut or HttpRequest are not easily accessible, so, building HttpClient with HttpClientBuilder, I ended up inserting a HttpRequestInterceptor in front of the culprit RequestContent :
当我使用http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/transport/http/HttpComponentsMessageSender.html作为 Spring WebService 消息发送器时,这发生在我身上。在这种情况下,像 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());
回答by John Rix
As pointed out by igor.zh, this problem can occur if using Spring's HttpComponentsMessageSender class. To be more precise though, this is only a problem if you are passing your own instance of HttpClient into the HttpComponentsMessageSender constructor - the issue is handled automatically otherwise.
正如 igor.zh 所指出的,如果使用 Spring 的 HttpComponentsMessageSender 类,就会出现这个问题。不过,更准确地说,这仅在您将自己的 HttpClient 实例传递到 HttpComponentsMessageSender 构造函数时才会出现问题 - 否则会自动处理该问题。
As of spring-ws 2.1.4, the HttpComponentsMessageSender.RemoveSoapHeadersInterceptor subclass that is used in the default constructor was made public to address this issue (see https://jira.spring.io/browse/SWS-835) and so can be used in your own HttpClient instances instead of writing your own class to do it. It also clears the HTTP.TRANSFER_ENCODING header.
从 spring-ws 2.1.4 开始,默认构造函数中使用的 HttpComponentsMessageSender.RemoveSoapHeadersInterceptor 子类已公开以解决此问题(请参阅https://jira.spring.io/browse/SWS-835),因此可以在您自己的 HttpClient 实例中使用,而不是编写您自己的类来执行此操作。它还清除 HTTP.TRANSFER_ENCODING 标头。
Use the HttpClientBuilder.addInterceptorFirst method to inject this interceptor into your own HttpClient instance. Example below using XML bean wiring. If anybody knows a more concise way of constructing the HttpClient instance (aside from writing a factory bean class), I'm all ears!
使用 HttpClientBuilder.addInterceptorFirst 方法将此拦截器注入您自己的 HttpClient 实例。下面的示例使用 XML bean 接线。如果有人知道构造 HttpClient 实例的更简洁的方法(除了编写工厂 bean 类),我全神贯注!
<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create"/>
<bean id="interceptedHttpClientBuilder" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="httpClientBuilder" />
<property name="targetMethod" value="addInterceptorFirst"> </property>
<property name="arguments">
<list>
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender.RemoveSoapHeadersInterceptor"/>
</list>
</property>
</bean>
<bean id="httpClient" factory-bean="interceptedHttpClientBuilder" factory-method="build" />
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<property name="httpClient" ref="httpClient"/>
</bean>
</property>
</bean>
Alternatively, if you can, just allow HttpComponentsMessageSender to construct its own HttpClient instance rather than passing one to it. Minor note on this: as of spring-ws 2.2.0-RELEASE, the default constructor for HttpComponentsMessageSender continues to use the DefaultHttpClient class, which is now deprecated. Hopefully this will be addressed in a future release.
或者,如果可以,只允许 HttpComponentsMessageSender 构建自己的 HttpClient 实例,而不是将其传递给它。关于此的小注意事项:从 spring-ws 2.2.0-RELEASE 开始, HttpComponentsMessageSender 的默认构造函数继续使用 DefaultHttpClient 类,该类现已弃用。希望这将在未来的版本中得到解决。
回答by Muhd
John Rix's answerhas the right idea. Here's how you do it with plain java:
John Rix 的回答是正确的。以下是使用普通 Java 的方法:
HttpClient client = HttpClients.custom()
.addInterceptorFirst(new RemoveSoapHeadersInterceptor())
.build();
回答by Alok
@John Rix's answer This code helped solved the problem
@John Rix 的回答这段代码帮助解决了这个问题
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");
}
}
HttpClient client = HttpClients.custom()
.addInterceptorFirst(new ContentLengthHeaderRemover())
.build();