Apache HttpComponents 异步客户端设置请求正文问题

问题描述 投票:0回答:1

我正在学习最新的 apache hc 异步客户端 的示例。 response streaming feature 非常有用,正是我需要的(例如计算每个块到达时的延迟,

CloseableHttpClient
似乎缺少)。

但是遇到麻烦setting the request body.

AsyncClientHttpExchangeStreaming为例,我可以运行这个例子,但是当尝试向请求添加一些正文时,如下所示,我发现它不起作用(httpbin响应非常清楚,

data
json
字段为空)。

      String bodyString = "{\"k\":\"v\"}";
      final SimpleHttpRequest request = SimpleRequestBuilder
        .post()
        .setHttpHost(target)
        .setPath("/post")
        .setBody(bodyString, ContentType.APPLICATION_JSON)
        .build();

然后我注意到

client.execute(new BasicRequestProducer(request, null),
并尝试用替换
null
new BasicAsyncEntityProducer(bodyString, ContentType.APPLICATION_JSON);
,这次 httpbin 告诉我它收到了 bodyString(这个 walkaround 是否正确,为什么需要?)。

当我尝试发布多部分表单时,如上面的解决方法,服务器报告错误,例如“内容长度缺失”或“格式错误的请求”:

    final StringBody inputBody = new StringBody(inputJson, ContentType.APPLICATION_JSON);
    final StringBody parametersBody = new StringBody(parametersJson, ContentType.APPLICATION_JSON);

    final HttpEntity reqEntity = MultipartEntityBuilder.create()
        .addPart("Input", inputBody)
        .addPart("Parameters", parametersBody)
        .build();
    //above reqEntity can successful request my server in sync client
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    reqEntity.writeTo(baos);
    byte[] bytes = baos.toByteArray();
    BasicAsyncEntityProducer multiPartProducer = new BasicAsyncEntityProducer(
        bytes,
        ContentType.MULTIPART_FORM_DATA
    );

我搜索了很多,有人

HttpEntity
创建的
MultipartEntityBuilder
不能与异步客户端一起使用。我非常失望和沮丧。谁能在 apache hc 或其他库中建议正确的方法?

我正在使用 openjdk11,没有找到 apache hc 5 或异步客户端的任何标签,如果标签不准确,我们深表歉意。

java http networking multipartform-data apache-httpclient-4.x
1个回答
0
投票

找到解决方案并自己回答,希望对像我这样的新手有所帮助。 仍然欢迎更多优雅的解决方案。

  • 问题原因

    HttpEntity

    创建的
    MultipartEntityBuilder
    作为字节包装到
    BasicAsyncEntityProducer
    中,库按原样发送字节,http post header缺少边界信息。

  • 解决方案

    获取包含边界信息的

    Content-Type
    标头,然后将其更新为请求标头。

//get the `Content-Type` header including the boundery info
//value is like:
//Content-Type: multipart/form-data; charset=ISO-8859-1; boundary=fLC0K1nKdSI-Q9vzFpU2WleMTXyWbOBp6
String contentType = reqEntity.getContentType();
final SimpleHttpRequest request = SimpleRequestBuilder
//...omit other methods
.setHeader("Content-Type", contentType)
© www.soinside.com 2019 - 2024. All rights reserved.