Skip to main content

rustack_apigatewayv2_http/
dispatch.rs

1//! API Gateway v2 handler trait and operation dispatch.
2//!
3//! Uses manual `Pin<Box<dyn Future>>` return types because `ApiGatewayV2Handler`
4//! requires object safety for dynamic dispatch (`Arc<dyn ApiGatewayV2Handler>`).
5
6use std::{future::Future, pin::Pin};
7
8use bytes::Bytes;
9use rustack_apigatewayv2_model::{error::ApiGatewayV2Error, operations::ApiGatewayV2Operation};
10
11use crate::{body::ApiGatewayV2ResponseBody, router::PathParams};
12
13/// The boundary between HTTP and business logic for API Gateway v2.
14///
15/// Implementations receive the resolved operation, extracted path parameters,
16/// the raw query string, request headers, and body bytes. They return a
17/// complete HTTP response or an [`ApiGatewayV2Error`].
18///
19/// This trait uses manual `Pin<Box<dyn Future>>` return types instead of
20/// `async fn` in the trait because it needs to be object-safe for use with
21/// `Arc<dyn ApiGatewayV2Handler>`.
22pub trait ApiGatewayV2Handler: Send + Sync + 'static {
23    /// Handle an API Gateway v2 operation.
24    fn handle_operation(
25        &self,
26        op: ApiGatewayV2Operation,
27        path_params: PathParams,
28        query: String,
29        headers: http::HeaderMap,
30        body: Bytes,
31    ) -> Pin<
32        Box<
33            dyn Future<Output = Result<http::Response<ApiGatewayV2ResponseBody>, ApiGatewayV2Error>>
34                + Send,
35        >,
36    >;
37}
38
39/// Dispatch an API Gateway v2 operation to the handler.
40pub async fn dispatch_operation<H: ApiGatewayV2Handler>(
41    handler: &H,
42    op: ApiGatewayV2Operation,
43    path_params: PathParams,
44    query: String,
45    headers: http::HeaderMap,
46    body: Bytes,
47) -> Result<http::Response<ApiGatewayV2ResponseBody>, ApiGatewayV2Error> {
48    tracing::debug!(operation = %op, "dispatching ApiGatewayV2 operation");
49    handler
50        .handle_operation(op, path_params, query, headers, body)
51        .await
52}
53
54/// Default handler that returns a "not implemented" error for all operations.
55#[derive(Debug, Clone, Default)]
56pub struct NotImplementedHandler;
57
58impl ApiGatewayV2Handler for NotImplementedHandler {
59    fn handle_operation(
60        &self,
61        op: ApiGatewayV2Operation,
62        _path_params: PathParams,
63        _query: String,
64        _headers: http::HeaderMap,
65        _body: Bytes,
66    ) -> Pin<
67        Box<
68            dyn Future<Output = Result<http::Response<ApiGatewayV2ResponseBody>, ApiGatewayV2Error>>
69                + Send,
70        >,
71    > {
72        Box::pin(async move { Err(ApiGatewayV2Error::not_implemented(op.as_str())) })
73    }
74}