英文:
Apache HttpComponents Async Client Setting Request Body Issue
问题
我正在学习最新的apache hc异步客户端的示例。响应流式传输功能非常有用,正是我需要的(比如在每个数据块到达时计算延迟,这在CloseableHttpClient
中似乎缺失)。
但是在设置请求体方面遇到了问题。
以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(这个解决方法是否正确以及为什么需要?)。
当我尝试像上面的解决方法一样发布多部分表单时,服务器报告错误,如'content-length missing'或'malformed request':
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();
//上面的reqEntity可以在同步客户端中成功请求我的服务器
ByteArrayOutputStream baos = new ByteArrayOutputStream();
reqEntity.writeTo(baos);
byte[] bytes = baos.toByteArray();
BasicAsyncEntityProducer multiPartProducer = new BasicAsyncEntityProducer(
bytes,
ContentType.MULTIPART_FORM_DATA
);
我搜索了很多,有人说MultipartEntityBuilder
创建的HttpEntity
不能与异步客户端一起使用。我感到非常失望和沮丧。有人能否建议在apache hc中正确的方法,或者是否有其他库可以代替?
英文:
I'm learning examples of latest apache hc async client. The response streaming feature is very useful and exactly what I need(such as calculating latency when each chunk arrived, which seems lack in CloseableHttpClient
).
But having trouble setting the request body.
Take the AsyncClientHttpExchangeStreaming as example, I can run this example, but when trying to add some body to request, like following, I find it not work(httpbin response is very clear, and data
or json
field is empty).
String bodyString = "{\"k\":\"v\"}";
final SimpleHttpRequest request = SimpleRequestBuilder
.post()
.setHttpHost(target)
.setPath("/post")
.setBody(bodyString, ContentType.APPLICATION_JSON)
.build();
Then I noticed client.execute(new BasicRequestProducer(request, null),
and tried to replace null
with
new BasicAsyncEntityProducer(bodyString, ContentType.APPLICATION_JSON);
, this time httpbin tells me it received the bodyString(is this walkaround correct and why need?).
When I tried posting multi part form, like above walkaround, the server reports errors such as 'content-length missing' or 'malformed request':
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
);
I searched a lot and someone says the HttpEntity
created by MultipartEntityBuilder
cannot be used along with async client. I'm very disappointed and frustrated. Could anyone suggest the correct way in apache hc, or rather other libraries instead?
答案1
得分: 0
"Found solution and answer myself, hope helpful for some newcomers like me. Still welcome more elgant solution.
-
Cause of the issue
HttpEntity
created byMultipartEntityBuilder
is wrapped intoBasicAsyncEntityProducer
as bytes, library sends the bytes as they are, and http post header missing boundary information. -
Solution
Get theContent-Type
header including the boundery info then update it into request headers.
//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)
```"
<details>
<summary>英文:</summary>
Found solution and answer myself, hope helpful for some newcomers like me.
Still welcome more elgant solution.
- Cause of the issue
`HttpEntity` created by `MultipartEntityBuilder` is wrapped into `BasicAsyncEntityProducer` as bytes, library sends the bytes as they are, and http post header missing boundary information.
- Solution
Get the `Content-Type` header including the boundery info then update it into request headers.
```java
//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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论