Заголовок 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)

Есть идеи?

Solutions Collecting From Web of "Заголовок Content-Length уже присутствует"

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

Как указано 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-компонентов. Если кто-то знает более сжатый способ построения экземпляра HttpClient (помимо написания класса фабричного компонента), я все уши!

 <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, а не передавать его ему. Небольшая заметка об этом: по состоянию на весну-ws 2.2.0-RELEASE конструктор по умолчанию для HttpComponentsMessageSender продолжает использовать класс DefaultHttpClient, который теперь устарел. Надеюсь, это будет рассмотрено в следующем выпуске.

Это происходит со мной, когда я использовал http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/transport/http/HttpComponentsMessageSender.html в качестве отправителя сообщений Spring WebService. В этом случае такие вещи, как 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's ProtocolException("Content-Length header already present"); } } ... HttpClientBuilder httpClientBuilder = HttpClients.custom(); httpClientBuilder.addInterceptorFirst(new CcontentLengthHeaderRemover()); 

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

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

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