内容长度标头已存在

2022-09-01 04:49:40

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

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 已经存在于 org.apache.http.protocol.RequestContent.process(RequestContent.java:70) at org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor.java:290)

有什么想法吗?


答案 1

正如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>

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


答案 2

我自己没有使用过HttpClient,但我怀疑问题在于隐式提供内容长度,并且您还通过其中一个调用显式设置它。putMethod.setEntity(...)putMethod.addHeader(...)


推荐