now_lambda/
lib.rs

1pub use http::{self, Response};
2use lambda_runtime::{self as lambda, Context};
3use log::{self, debug, error};
4use serde_json::Error;
5use tokio::runtime::Runtime as TokioRuntime;
6
7mod body;
8pub mod error;
9pub mod request;
10mod response;
11mod strmap;
12
13pub use crate::{body::Body, response::IntoResponse, strmap::StrMap};
14use crate::{
15    error::NowError,
16    request::{NowEvent, NowRequest},
17    response::NowResponse,
18};
19
20/// Type alias for `http::Request`s with a fixed `now_lambda::Body` body
21pub type Request = http::Request<Body>;
22
23/// Functions acting as Now Lambda handlers must conform to this type.
24pub trait Handler<R, B, E> {
25    /// Method to execute the handler function
26    fn run(&mut self, event: http::Request<B>) -> Result<R, E>;
27}
28
29impl<Function, R, B, E> Handler<R, B, E> for Function
30where
31    Function: FnMut(http::Request<B>) -> Result<R, E>,
32{
33    fn run(&mut self, event: http::Request<B>) -> Result<R, E> {
34        (*self)(event)
35    }
36}
37
38/// Creates a new `lambda_runtime::Runtime` and begins polling for Now Lambda events
39///
40/// # Arguments
41///
42/// * `f` A type that conforms to the `Handler` interface.
43///
44/// # Panics
45/// The function panics if the Lambda environment variables are not set.
46pub fn start<R, B, E>(f: impl Handler<R, B, E>, runtime: Option<TokioRuntime>)
47where
48    B: From<Body>,
49    E: Into<NowError>,
50    R: IntoResponse,
51{
52    // handler requires a mutable ref
53    let mut func = f;
54    lambda::start(
55        |e: NowEvent, _ctx: Context| {
56            let req_str = e.body;
57            let parse_result: Result<NowRequest, Error> = serde_json::from_str(&req_str);
58            match parse_result {
59                Ok(req) => {
60                    debug!("Deserialized Now proxy request successfully");
61                    let request: http::Request<Body> = req.into();
62                    func.run(request.map(|b| b.into()))
63                        .map(|resp| NowResponse::from(resp.into_response()))
64                        .map_err(|e| e.into())
65                }
66                Err(e) => {
67                    error!("Could not deserialize event body to NowRequest {}", e);
68                    panic!("Could not deserialize event body to NowRequest {}", e);
69                }
70            }
71        },
72        runtime,
73    )
74}
75
76/// A macro for starting new handler's poll for Now Lambda events
77#[macro_export]
78macro_rules! lambda {
79    ($handler:expr) => {
80        $crate::start($handler, None)
81    };
82    ($handler:expr, $runtime:expr) => {
83        $crate::start($handler, Some($runtime))
84    };
85    ($handler:ident) => {
86        $crate::start($handler, None)
87    };
88    ($handler:ident, $runtime:expr) => {
89        $crate::start($handler, Some($runtime))
90    };
91}