Content-Length 标头已存在

发布于 2024-09-11 05:24:25 字数 643 浏览 6 评论 0 原文

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

有什么想法吗?

I am using the Apache HttpClient (4.1) included in Android to execute a HttpPut. I have verified that I only have 1 content-length header. However, every time I send the request, I get a protocol exception about the Content-Length header already specified.

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 already present
at org.apache.http.protocol.RequestContent.process(RequestContent.java:70)
at org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor.java:290)

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

沉默的熊 2024-09-18 05:24:25

正如 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 类,该类现已弃用。希望这个问题能够在未来的版本中得到解决。

As pointed out by igor.zh, this problem can occur if using Spring's HttpComponentsMessageSender class. To be more precise though, this is only a problem if you are passing your own instance of HttpClient into the HttpComponentsMessageSender constructor - the issue is handled automatically otherwise.

As of spring-ws 2.1.4, the HttpComponentsMessageSender.RemoveSoapHeadersInterceptor subclass that is used in the default constructor was made public to address this issue (see https://jira.spring.io/browse/SWS-835) and so can be used in your own HttpClient instances instead of writing your own class to do it. It also clears the HTTP.TRANSFER_ENCODING header.

Use the HttpClientBuilder.addInterceptorFirst method to inject this interceptor into your own HttpClient instance. Example below using XML bean wiring. If anybody knows a more concise way of constructing the HttpClient instance (aside from writing a factory bean class), I'm all ears!

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

Alternatively, if you can, just allow HttpComponentsMessageSender to construct its own HttpClient instance rather than passing one to it. Minor note on this: as of spring-ws 2.2.0-RELEASE, the default constructor for HttpComponentsMessageSender continues to use the DefaultHttpClient class, which is now deprecated. Hopefully this will be addressed in a future release.

吾家有女初长成 2024-09-18 05:24:25

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

I've not used HttpClient myself, but I suspect that the problem is that putMethod.setEntity(...) is implicitly supplying a content length and you are also setting it explicitly via one of the putMethod.addHeader(...) calls.

酷到爆炸 2024-09-18 05:24:25

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

That happens to me when I used http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/transport/http/HttpComponentsMessageSender.html as a Spring WebService Message Sender. In that case the stuff like HttpPut or HttpRequest are not easily accessible, so, building HttpClient with HttpClientBuilder, I ended up inserting a HttpRequestInterceptor in front of the culprit 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());
养猫人 2024-09-18 05:24:25

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

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

John Rix's answer has the right idea. Here's how you do it with plain java:

HttpClient client = HttpClients.custom()
    .addInterceptorFirst(new RemoveSoapHeadersInterceptor())
    .build();
你げ笑在眉眼 2024-09-18 05:24:25

如果您签出 http://docjar.org/docs/api/ org/apache/http/protocol/RequestContent.html 您会注意到,如果您自己设置了它,它会抛出该异常。因此,内部工作自动设置内容长度。这也意味着,要将其设置为“0”,您需要将实体设置为空。

If you checkout http://docjar.org/docs/api/org/apache/http/protocol/RequestContent.html you'll notice that it throws that exception if you've set it yourself. Therefore, the internal working set the content length automatically. This also means, to set it to "0", you need to set the entity to null.

熟人话多 2024-09-18 05:24:25

如果您采用 John Rix 的 XML 配置答案,请确保向 httpClient bean 添加 depends-on 属性,以便 RemoveSoapHeadersInterceptor 拦截器在创建 httpClient bean 之前添加到 ClientBuilder 中。在我完成此操作之前,SOAP 标头删除尚未生效。

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

If you are adopting the XML configuration answer by John Rix, make sure to add a depends-on attribute to the httpClient bean so the RemoveSoapHeadersInterceptor interceptor is added to the ClientBuilder before the httpClient bean gets created. SOAP headers removal hasn't taken effect until I have done so.

<bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build" depends-on="interceptedHttpClientBuilder"/>
谁的新欢旧爱 2024-09-18 05:24:25

@约翰·里克斯的回答
这段代码帮助解决了问题

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

@John Rix's answer
This code helped solved the problem

    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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文