scuffle_http/backend/h3/
utils.rs

1use bytes::{Buf, Bytes};
2use h3::quic::SendStream;
3use h3::server::RequestStream;
4use http_body::Body;
5
6use crate::service::{HttpService, HttpServiceFactory};
7
8/// Copy the response body to the given stream.
9pub(crate) async fn copy_response_body<S, F>(
10    mut send: RequestStream<S, Bytes>,
11    body: <F::Service as HttpService>::ResBody,
12) -> Result<(), crate::error::HttpError<F>>
13where
14    F: HttpServiceFactory,
15    F::Error: std::error::Error,
16    <F::Service as HttpService>::Error: std::error::Error,
17    S: SendStream<Bytes>,
18    <F::Service as HttpService>::ResBody: http_body::Body,
19    <<F::Service as HttpService>::ResBody as http_body::Body>::Error: std::error::Error,
20{
21    let mut body = std::pin::pin!(body);
22
23    while let Some(frame) = std::future::poll_fn(|cx| body.as_mut().poll_frame(cx)).await {
24        match frame
25            .map_err(crate::error::HttpError::ResBodyError)?
26            .into_data()
27            .map_err(|f| f.into_trailers())
28        {
29            Ok(mut data) => send.send_data(data.copy_to_bytes(data.remaining())).await?,
30            Err(Ok(trailers)) => {
31                send.send_trailers(trailers).await?;
32                return Ok(());
33            }
34            Err(Err(_)) => continue,
35        }
36    }
37
38    send.finish().await?;
39
40    Ok(())
41}