簡體   English   中英

Content-Length 標頭已存在

[英]Content-Length header already present

我正在使用 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

原因:org.apache.http.ProtocolException: Content-Length 標頭已經存在於 org.apache.http.protocol.RequestContent.process(RequestContent.java:70) 的 org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor .java:290)

有任何想法嗎?

正如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 類。 希望這將在未來的版本中得到解決。

我自己沒有使用過 HttpClient ,但我懷疑問題在於putMethod.setEntity(...)隱式提供了內容長度,並且您還通過其中一個putMethod.addHeader(...)調用顯式設置它.

當我使用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());

約翰·里克斯的回答有正確的想法。 以下是使用普通 java 的方法:

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

如果您檢查http://docjar.org/docs/api/org/apache/http/protocol/RequestContent.html ,您會注意到如果您自己設置它會引發該異常。 因此,內部工作自動設置內容長度。 這也意味着,要將其設置為“0”,您需要將實體設置為空。

如果您采用 John Rix 的 XML 配置答案,請確保向httpClient bean 添加一個depends-on屬性,以便在創建httpClient bean之前RemoveSoapHeadersInterceptor攔截器添加到ClientBuilder 在我這樣做之前,SOAP 標頭刪除尚未生效。

<bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build" depends-on="interceptedHttpClientBuilder"/>

@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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM