diff --git a/lambda-http/src/lib.rs b/lambda-http/src/lib.rs index cea99750..d6f8dbb0 100644 --- a/lambda-http/src/lib.rs +++ b/lambda-http/src/lib.rs @@ -101,7 +101,7 @@ use std::{ }; mod streaming; -pub use streaming::run_with_streaming_response; +pub use streaming::{into_streaming_response, run_with_streaming_response}; /// Type alias for `http::Request`s with a fixed [`Body`](enum.Body.html) type pub type Request = http::Request; diff --git a/lambda-http/src/streaming.rs b/lambda-http/src/streaming.rs index a93408b4..67d772c0 100644 --- a/lambda-http/src/streaming.rs +++ b/lambda-http/src/streaming.rs @@ -3,7 +3,14 @@ use bytes::Bytes; pub use http::{self, Response}; use http_body::Body; use lambda_runtime::Diagnostic; -pub use lambda_runtime::{self, tower::ServiceExt, Error, LambdaEvent, MetadataPrelude, Service, StreamResponse}; +pub use lambda_runtime::{ + self, + tower::{ + util::{MapRequest, MapResponse}, + ServiceExt, + }, + Error, LambdaEvent, MetadataPrelude, Service, StreamResponse, +}; use std::{ fmt::Debug, pin::Pin, @@ -11,12 +18,21 @@ use std::{ }; use tokio_stream::Stream; -/// Starts the Lambda Rust runtime and stream response back [Configure Lambda -/// Streaming Response](https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html). +/// Converts a handler into a streaming-compatible service for use with AWS +/// Lambda. /// -/// This takes care of transforming the LambdaEvent into a [`Request`] and -/// accepts [`http::Response`] as response. -pub async fn run_with_streaming_response<'a, S, B, E>(handler: S) -> Result<(), Error> +/// This function wraps a `Service` implementation, transforming its input and +/// output to be compatible with AWS Lambda's streaming response feature. It +/// provides the necessary middleware to handle `LambdaEvent` requests and +/// converts the `http::Response` into a `StreamResponse` containing a metadata +/// prelude and body stream. +#[allow(clippy::type_complexity)] +pub fn into_streaming_response<'a, S, B, E>( + handler: S, +) -> MapResponse< + MapRequest) -> Request>, + impl FnOnce(Response) -> StreamResponse> + Clone, +> where S: Service, Error = E>, S::Future: Send + 'a, @@ -25,13 +41,13 @@ where B::Data: Into + Send, B::Error: Into + Send + Debug, { - let svc = ServiceBuilder::new() + ServiceBuilder::new() .map_request(|req: LambdaEvent| { let event: Request = req.payload.into(); event.with_lambda_context(req.context) }) .service(handler) - .map_response(|res| { + .map_response(|res: Response| { let (parts, body) = res.into_parts(); let mut prelude_headers = parts.headers; @@ -54,8 +70,25 @@ where metadata_prelude, stream: BodyStream { body }, } - }); + }) +} +/// Starts the Lambda Rust runtime and stream response back [Configure Lambda +/// Streaming +/// Response](https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html). +/// +/// This takes care of transforming the LambdaEvent into a [`Request`] and +/// accepts [`http::Response`] as response. +pub async fn run_with_streaming_response<'a, S, B, E>(handler: S) -> Result<(), Error> +where + S: Service, Error = E>, + S::Future: Send + 'a, + E: Debug + Into, + B: Body + Unpin + Send + 'static, + B::Data: Into + Send, + B::Error: Into + Send + Debug, +{ + let svc = into_streaming_response(handler); lambda_runtime::run(svc).await }