Apache HTTP/2 客户端 5.0 POST 请求缺少有效负载/内容

Posted

技术标签:

【中文标题】Apache HTTP/2 客户端 5.0 POST 请求缺少有效负载/内容【英文标题】:Apache HTTP/2 Client 5.0 POST request missing payload/content 【发布时间】:2021-06-01 00:40:41 【问题描述】:

我有一个小样本 servlet 部署到 Tomcat,它将回显任何接收到的参数。 Tomcat 配置为支持 HTTP/1.1 和 HTTP/2。我可以使用curl 向 servlet 发出 GET 请求,证明它可以在 HTTP/1.1 和 HTTP/2 上工作。

使用 Apache HTTP 5.0 客户端我有一个单元测试来命中 servlet 和 POST 一个带有一些参数(请求内容)的请求,它工作正常 - 服务器接收参数并将它们返回给我可以的客户端阅读它们。在此测试中,我使用CloseableHttpAsyncClient.setVersionPolicy() 调用调用客户端以使用HTTP/1.1 或HTTP/2。但是,如果我更改为使用 HTTP/2,则客户端不会将请求内容发送到服务器。

下面是成功调用 HTTP/1.1 的示例代码 - 你可以看到我有 setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_1)。如果我将其更改为 FORCE_HTTP_2,则通过 HTTP/2.0 进行调用,但不会发送请求内容。

谁能建议我做错了什么或我需要做些什么额外的事情?我没有找到很多关于使用新的 Apache 5.0 客户端库的文档,而且这些示例没有显示发送和 POST 内容(或者至少是我能找到的那些)。

    public void testWithHTTP1() throws Exception 

        final String content = "Code=99&Message=Hello";
        final String contentType = "application/text";

        final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
                .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_1)
                .build();

        client.start();

        final HttpHost target = new HttpHost("http","localhost",8002);
        final String requestUri = "/VSFTestMT_Test/Test/Test_EchoHttpGet";

        final HttpClientContext clientContext = HttpClientContext.create();

        final SimpleHttpRequest httppost = SimpleHttpRequests.post(target, requestUri);     
        httppost.setBody(content, ContentType.create("application.x_www_form_urlencoded"));
        
        final Future<SimpleHttpResponse> future = client.execute(
                httppost,
                clientContext,
                new FutureCallback<SimpleHttpResponse>() 

                    @Override
                    public void completed(final SimpleHttpResponse response) 
                        System.out.println(requestUri + "->" + response.getCode());
                        System.out.println(response.getBody());
                    

                    @Override
                    public void failed(final Exception ex) 
                        System.out.println(requestUri + "->" + ex);
                    

                    @Override
                    public void cancelled() 
                        System.out.println(requestUri + " cancelled");
                    

                );


        System.out.println("Shutting down");
        client.close(CloseMode.GRACEFUL);
    

【问题讨论】:

在此处或将会话的线路日志发布到 httpclient-users@hc.apache.org 【参考方案1】:

HTTP/1 可以通过 HTTP 和 HTTPS 实现,但对于 HTTP/2,它只能通过 HTTPS 实现。

据我所知,您只调用了 http url,这可能是 servlet 无法获取有效负载内容的原因

请看更多detail

【讨论】:

谢谢,这让我对 CURL 进行了更多测试。我原以为我的 tomcat 服务器在 HTTP 和 HTTPS 上都可以使用 HTTP/2。然而,HTTP/2 的使用并不是那么明确。我可以使用 CURL 在非 SSL 连接上执行 HTTP/2 POST 请求,但前提是没有有效负载。我还可以在 HTTP 和 HTTPS 上使用或不使用 URL 参数执行 HTTP/2 GET 请求。因此,似乎将正文内容添加到非 SSL HTTP/2 请求将降级为 HTTP/1。在我的测试中,我可以成功地将正文内容添加到 HTTP/2 请求中,以便您指出我需要向 HTTPS 服务器发出请求。【参考方案2】:

看起来他们有一个完全不同的 Http/2 构建器来查看他们的源代码:

/**
 * Creates builder object for construction of custom HTTP/2
 * @link CloseableHttpAsyncClient instances optimized for HTTP/2 protocol
 * and message multiplexing
 */
public static H2AsyncClientBuilder customHttp2() 
    return H2AsyncClientBuilder.create();


/**
 * Creates HTTP/2 @link CloseableHttpAsyncClient instance with default configuration and
 * system properties optimized for HTTP/2 protocol and message multiplexing.
 */
public static CloseableHttpAsyncClient createHttp2System() 
    return H2AsyncClientBuilder.create().useSystemProperties().build();

因此我建议你尝试实际的 customHttp2(),而不是 custom()。

https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClients.java

【讨论】:

谢谢苏珊,但那里没有快乐。使用 customHttp2() 会给我一个 ClientBuilder,我从中得到另一个 CloseableHttpAsyncClient,但像以前一样继续,我仍然得到相同的结果。 @Susan Mustafa 此构建器适用于希望仅使用 HTTP/2 协议并充分利用消息交换多路复用的用户。

以上是关于Apache HTTP/2 客户端 5.0 POST 请求缺少有效负载/内容的主要内容,如果未能解决你的问题,请参考以下文章

Apache Lucene 5.0/Solr 5.0 发布

尝试在 YARN 上运行 Apache Apex 的 Yahoo Finance 示例

Apache 或其他一些 CLIENT JAVA 实现是不是支持 HTTP/2?

无法使用 Apache HTTP 从 OkHTTP/ALPN/Linux 客户端建立 HTTP/2 连接

Apache Lucene和Solr 5.0发布

是否可以使用 Apache HTTPClient 4.2.5 发出 HTTP/2 请求?