使用 hyper 时如何直接控制 http body(大尺寸)?

How do I directly control the http body (big size) when using hyper?

目前,我们正在将用 c 编写的 API 网关引擎切换到 tokio、hyper、rustls of rust。

在分析hyper_rustls(tokio_rustls)提供的echo server example时,有部分不懂,求助。 (我正在努力参考的例子不多)

https://github.com/rustls/hyper-rustls/blob/main/examples/server.rs

这是我想到的流程: 当收到一个 POST 请求体大小较大时,读取所有 http body → 读取到 content-length 后,执行传递给 make_service_fn 的 future 代码(示例中的 echo 操作)。

但是,一旦收到请求,就会执行传递给 make_service_fn 的代码并向客户端发送响应,并且 tokio::io::AsyncRead 的 poll_read 函数trait 被执行了很多次。这是 运行。

问:make_fn_service 代码 运行 的确切时间是什么时候,这是我可以控制的吗?

问:使用hyper的时候,好像是存储在内存中积累的body。因此,如果主体尺寸非常大,我想将其下载到一个单独的文件中。有没有什么方法可以直接控制每次本体来的时候?

关于第一季度:

let service = make_service_fn(|_| async { Ok::<_, io::Error>(service_fn(echo)) });

您调用 make_fn_service 将异步函数转换为可以传递给 serve() 的函数。它有一个 &AddrStream 类型的参数,可以做各种花哨的事情,比如过滤和节流,但如果你不需要这些,只需用你的异步函数调用 service_fn

然后您的函数,示例中的 echo,将根据客户端请求调用一次。

关于第二季度:

正文不在记忆中累积:

*response.body_mut() = req.into_body();

但是这些是 Body 类型,实现了 Stream<Item=Result<Bytes>>,因为这些 Bytes 正文的块 request/response。

并且通过将一个 Stream 分配给另一个 Stream,一个非常大的 ping 应该通过 echo 函数无痛地流式传输,一次一个块。

如果您想自己管理数据,您可以轮询流 (StreamExt::next()) 并单独处理每一块正文。只是不要调用 Body::to_bytes()Body::aggregate().

关于使用 HttpBody 特征:

当然你可以直接使用它,但这并不简单。我认为它通常是这样实现的,例如,您可以直接从请求中获取 JSON 对象,或者 XML 或 urlencoded 映射或任何 Content-Type 指示的对象,而无需执行中间操作字节数组和解析。

但正如您可能猜到的那样,在异步模式下处理巨大的 XML/JSON 有效载荷并不容易。如果你真的需要它,你可以更容易地驱动一个普通 Body.

的字节块