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



目前,我们正在将c中制作的API网关引擎切换到tokio, hyper, rustls of rust。

在分析hyper_rustls (tokio_rustls)提供的echo server示例时,有不明白的地方,请求帮助。(我正在努力没有太多的例子来参考)

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

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

但是,一旦接收到请求,就执行传递给make_service_fn的代码,并向客户端发送响应,并且执行tokio::io::AsyncRead特性的poll_read函数多次。

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

Q:当使用hyper时,它似乎将body积累在内存中。因此,如果正文尺寸非常大,我想把它下载到一个单独的文件。有没有办法直接控制身体每次来?

  • 我可以使用hyper::body::HttpBody特性吗?

关于Q1:

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

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

那么您的函数,在示例中是echo,将在每个客户端请求中调用一次。

关于Q2:

正文未在内存中积累:

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

但是这些是Body类型的,实现了Stream<Item=Result<Bytes>>,这些Bytes是请求/响应的主体块。

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

如果你想自己管理数据,你可以轮询流(StreamExt::next())并单独处理每个体块。请不要调用Body::to_bytes()Body::aggregate()

关于使用HttpBody性状:

当然你可以直接使用它,但它不是微不足道的。我认为它通常是这样实现的,以便您可以直接从请求中获得例如JSON对象,或XML或urlencoded映射或任何您的Content-Type指示,而无需做中间字节数组和解析。

但是正如你可能猜到的那样,在异步模式下处理巨大的XML/JSON有效负载并不容易。如果你真的需要,你可以让它变得更简单,只是驱动普通Body的字节块。

相关内容

  • 没有找到相关文章

最新更新