我正在学习最新的 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 或异步客户端的任何标签,如果标签不准确,我们深表歉意。
找到解决方案并自己回答,希望对像我这样的新手有所帮助。 仍然欢迎更多优雅的解决方案。
问题原因
由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)