Reactor httpclient 使用 Content-Length 发送表单

huangapple go评论82阅读模式
英文:

Reactor httpclient sendForm with Content-Length

问题

我正在学习 reactor-netty 作为 HTTP 客户端来发送多部分表单数据。我的服务器需要 Content-Length 字段,但似乎 reactor-netty 不会自动设置它(有趣的是它在每个部分中设置了 Content-Length,这并不满足我的服务器的要求)。

与 http apache 客户端中的 CloseableHttpClient 相比,Http 流量(错误)如下所示:

POST /post HTTP/1.1
user-agent: ReactorNetty/1.1.4
host: myservername
accept: */*
content-type: application/json
content-type: multipart/form-data; boundary=40e3ae2412eea9a2
transfer-encoding: chunked

--40e3ae2412eea9a2
content-disposition: form-data; name="a"
content-length: 94
content-type: application/json
content-transfer-encoding: binary

dataa...
--40e3ae2412eea9a2
content-disposition: form-data; name="b"
content-length: 205
content-type: application/json
content-transfer-encoding: binary

datab...
--40e3ae2412eea9a2--

与之相比,http apache 客户端中的 CloseableHttpClient 的 Http 流量(正确)如下:

POST /post HTTP/1.1
Accept-Encoding: gzip, x-gzip, deflate
Content-Length: 611
Content-Type: multipart/form-data; charset=ISO-8859-1; boundary=dbiD5AN62qhyG8C8HAbOPu5zlltTOSu2q
Host: myservername
Connection: keep-alive
User-Agent: Apache-HttpClient/5.2.1 (Java/11.0.12)

--dbiD5AN62qhyG8C8HAbOPu5zlltTOSu2q
Content-Disposition: form-data; name="a"
Content-Type: application/json; charset=UTF-8

dataa...
--dbiD5AN62qhyG8C8HAbOPu5zlltTOSu2q
Content-Disposition: form-data; name="b"
Content-Type: application/json; charset=UTF-8

datab...
--dbiD5AN62qhyG8C8HAbOPu5zlltTOSu2q--

请问有人可以告诉我如何设置 Content-Length?最好是自动设置。我正在使用 jdk11 和 reactor-netty 1.1.4。

英文:

I'm learning reactor-netty as http client to send multi form data.
My Server requires Content-Length field but seems reactor-netty doesn't set it automatically.(Interestingly it sets Content-Length in each part, which doesn't satisfy my server)

HttpClient.create().port(server.port()).post().uri("/postpath")
        .sendForm((req, form) -> form
            .multipart(true)
            .file("a", new ByteArrayInputStream(jsona.getBytes(StandardCharsets.UTF_8)), "application/json")
            .file("b", new ByteArrayInputStream(jsonb.getBytes(StandardCharsets.UTF_8)), "application/json")
        )
        //...omitted, same as the github examples
  • Http traffic(wrong)
Http traffic is like following:
POST /post HTTP/1.1
user-agent: ReactorNetty/1.1.4
host: myservernmae
accept: */*
content-type: application/json
content-type: multipart/form-data; boundary=40e3ae2412eea9a2
transfer-encoding: chunked

--40e3ae2412eea9a2
content-disposition: form-data; name="a"
content-length: 94
content-type: application/json
content-transfer-encoding: binary

dataa...
--40e3ae2412eea9a2
content-disposition: form-data; name="b"
content-length: 205
content-type: application/json
content-transfer-encoding: binary

datab...
--40e3ae2412eea9a2--

Compared to CloseableHttpClient in http apache client

      final HttpPost httppost = new HttpPost("http://myservernmae/postpath");
      final HttpEntity reqEntity = MultipartEntityBuilder.create()
          .addPart("a", aBody)
          .addPart("b", bBody)
          .build();
      httppost.setEntity(reqEntity);
      final CloseableHttpClient httpclient = HttpClients.createDefault();
      httpclient.execute(httppost, response -> {
      // omit remaining
  • http traffic(correct)
POST /post HTTP/1.1
Accept-Encoding: gzip, x-gzip, deflate
Content-Length: 611
Content-Type: multipart/form-data; charset=ISO-8859-1; boundary=dbiD5AN62qhyG8C8HAbOPu5zlltTOSu2q
Host: myservernmae
Connection: keep-alive
User-Agent: Apache-HttpClient/5.2.1 (Java/11.0.12)

--dbiD5AN62qhyG8C8HAbOPu5zlltTOSu2q
Content-Disposition: form-data; name="a"
Content-Type: application/json; charset=UTF-8

dataa...
--dbiD5AN62qhyG8C8HAbOPu5zlltTOSu2q
Content-Disposition: form-data; name="b"
Content-Type: application/json; charset=UTF-8

datab...
--dbiD5AN62qhyG8C8HAbOPu5zlltTOSu2q--

Could anyone tell me how to set the Content-Length? better automatically. I'm using jdk11, reactor-netty 1.1.4.

答案1

得分: 1

默认情况下,Reactor Netty 添加了 Transfer-Encoding: chunked。只需在组合请求之前删除此标头,Reactor Netty 将添加 Content-Length,其值是所有部分长度的总和。请参考下面的修改示例:

HttpClient.create().port(server.port()).post().uri("/postpath")
        .sendForm((req, form) -> {
            req.requestHeaders().remove(HttpHeaderNames.TRANSFER_ENCODING);

            form.multipart(true)
                .file("a", new ByteArrayInputStream(jsona.getBytes(StandardCharsets.UTF_8)), "application/json")
                .file("b", new ByteArrayInputStream(jsonb.getBytes(StandardCharsets.UTF_8)), "application/json")
        })
        //...omitted, same as the github examples
英文:

By default, Reactor Netty adds Transfer-Encoding: chunked. Just remove this header before composing your request and Reactor Netty will add Content-Length with a value summing the lengths of all parts. See below the modified example:

    HttpClient.create().port(server.port()).post().uri("/postpath")
            .sendForm((req, form) -> {
                req.requestHeaders().remove(HttpHeaderNames.TRANSFER_ENCODING);

                form.multipart(true)
                    .file("a", new ByteArrayInputStream(jsona.getBytes(StandardCharsets.UTF_8)), "application/json")
                    .file("b", new ByteArrayInputStream(jsonb.getBytes(StandardCharsets.UTF_8)), "application/json")
            })
            //...omitted, same as the github examples

huangapple
  • 本文由 发表于 2023年3月9日 17:19:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75682569.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定