grpc-quic-server 0.2.0

gRPC server over QUIC transport — QuicServer that delegates to tonic Router
Documentation
use crate::error::ServerError;
use bytes::Bytes;
use grpc_quic_core::body::ServerRecvBody;
use grpc_quic_metrics::{record_bytes_sent, record_request, record_stream};
use http_body::Body;
use tracing::error;

pub async fn handle_request<S>(
    req: http::Request<()>,
    stream: h3::server::RequestStream<h3_quinn::BidiStream<Bytes>, Bytes>,
    service: S,
) -> Result<(), ServerError>
where
    S: tower::Service<
            http::Request<tonic::body::BoxBody>,
            Response = http::Response<tonic::body::BoxBody>,
        > + Clone
        + Send
        + Sync
        + 'static,
    S::Future: Send + 'static,
    S::Error: Into<Box<dyn std::error::Error + Send + Sync>> + Send,
{
    let path = req.uri().path().to_owned();
    record_request("server", &path);
    record_stream("server");

    let (mut send, recv) = stream.split();
    let recv_body = ServerRecvBody::new(recv);
    let box_body = tonic::body::boxed(recv_body);

    let mut request = http::Request::new(box_body);
    *request.method_mut() = req.method().clone();
    *request.uri_mut() = req.uri().clone();
    *request.headers_mut() = req.headers().clone();

    use tower::ServiceExt;
    let mut service = service;

    let response = match service.ready().await {
        Ok(s) => match s.call(request).await {
            Ok(r) => r,
            Err(e) => {
                error!("service call failed: {:?}", e.into());
                if let Ok(resp) = http::Response::builder().status(500).body(()) {
                    if let Err(e) = send.send_response(resp).await {
                        error!("failed to send 500 response: {e}");
                    }
                }
                return Ok(());
            }
        },
        Err(e) => {
            error!("service not ready: {:?}", e.into());
            if let Ok(resp) = http::Response::builder().status(500).body(()) {
                if let Err(e) = send.send_response(resp).await {
                    error!("failed to send 500 response: {e}");
                }
            }
            return Ok(());
        }
    };

    let (parts, body) = response.into_parts();
    let resp = http::Response::from_parts(parts, ());
    if let Err(e) = send.send_response(resp).await {
        error!("failed to send response headers: {e}");
        return Ok(());
    }

    tokio::pin!(body);
    let mut data_frame_received = false;
    loop {
        let frame = futures::future::poll_fn(|cx| body.as_mut().poll_frame(cx)).await;
        match frame {
            Some(Ok(frame)) => match frame.into_data() {
                Ok(data) => {
                    data_frame_received = true;
                    let len = data.len() as u64;
                    if let Err(e) = send.send_data(data).await {
                        error!("failed to send data: {e}");
                        break;
                    }
                    record_bytes_sent("server", len);
                }
                Err(frame) => {
                    if let Ok(trailers) = frame.into_trailers() {
                        if let Err(e) = send.send_trailers(trailers).await {
                            error!("failed to send trailers: {e}");
                        }
                        return Ok(());
                    }
                }
            },
            Some(Err(e)) => {
                error!("response body error: {e}");
                break;
            }
            None => {
                if data_frame_received {
                    if let Err(e) = send.finish().await {
                        error!("failed to finish stream: {e}");
                    }
                }
                return Ok(());
            }
        }
    }

    if let Err(e) = send.finish().await {
        error!("failed to finish stream: {e}");
    }
    Ok(())
}