Подтвердить что ты не робот

Заголовок Content-Length уже присутствует

Я использую Apache HttpClient (4.1), включенную в Android, для выполнения 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)

Любые идеи?

4b9b3361

Ответ 1

Я сам не использовал HttpClient, но я подозреваю, что проблема заключается в том, что putMethod.setEntity(...) неявно снабжает длину содержимого, и вы также явно устанавливаете его через один из вызовов putMethod.addHeader(...).

Ответ 2

Как указано 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 (помимо написания класса factory 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, который теперь устарел. Надеюсь, это будет рассмотрено в следующем выпуске.

Ответ 3

Это происходит со мной, когда я использовал http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/transport/http/HttpComponentsMessageSender.html в качестве отправителя сообщений WebService Spring. В этом случае такие вещи, как HttpPut или HttpRequest, недоступны, поэтому, построив HttpClient с помощью HttpClientBuilder, я закончил тем, что вставил HttpRequestInterceptor перед виновником RequestContent:

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 ProtocolException("Content-Length header already present");
    }
}
...
    HttpClientBuilder httpClientBuilder = HttpClients.custom();
    httpClientBuilder.addInterceptorFirst(new CcontentLengthHeaderRemover());

Ответ 4

Если вы закажете http://docjar.org/docs/api/org/apache/http/protocol/RequestContent.html, вы заметите, что оно выбрасывает это исключение, если вы его установили сами. Поэтому внутренняя работа автоматически устанавливает длину содержимого. Это также означает, что для установки значения "0" вам нужно установить сущность в значение null.

Ответ 5

Ответ Джона Рикса имеет правильную идею. Вот как вы это делаете с простой java:

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