Content-Length标头已存在

Ada*_*amC 30 java android httpclient

我正在使用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
Run Code Online (Sandbox Code Playgroud)

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

有任何想法吗?

Joh*_*Rix 33

正如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类),我全都耳朵!

<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>
Run Code Online (Sandbox Code Playgroud)

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


Ste*_*n C 30

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

  • 究竟.除非使用普通的Socket,否则你永远不必在Java中设置Content-Length. (2认同)
  • 足够公平,但是Javadoc并没有说不能建立自己的Content-Length标头,并且还说:“在通常情况下,可以忽略所有预连接参数和常规请求属性:连接参数和请求属性默认为明智的值。对于此接口的大多数客户端,只有两种有趣的方法...' (2认同)
  • 顺便说一句 - 我能够通过设置请求拦截器(在最后)并查看修改后的请求来验证这一点.它显示已设置的Content-Length. (2认同)

igo*_*.zh 13

当我使用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());
Run Code Online (Sandbox Code Playgroud)


Muh*_*uhd 7

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

HttpClient client = HttpClients.custom()
    .addInterceptorFirst(new RemoveSoapHeadersInterceptor())
    .build();
Run Code Online (Sandbox Code Playgroud)