-
Notifications
You must be signed in to change notification settings - Fork 355
/
Copy pathlib.rs
126 lines (118 loc) · 3.62 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#![warn(missing_docs)]
//#![deny(warnings)]
//! Enriches the `lambda_runtime` crate with [http](https://github.com/hyperium/http)
//! types targeting ALB and API Gateway proxy events.
//!
//! Though ALB and API Gateway proxy events are separate Lambda triggers, they both share
//! similar shapes that contextually map to an http request handler. From a application perspective
//! the differences shouldn't matter. This crate
//! abstracts over both using standard [http](https://github.com/hyperium/http) types allowing
//! you to focus more on your application while giving you to the flexibility to
//! transparently use whichever http trigger suits your application's needs best.
//!
//! # Examples
//!
//! ```rust,no_run
//! use lambda_http::{lambda, IntoResponse, Request, RequestExt};
//! use lambda_runtime::{Context, error::HandlerError};
//!
//! fn main() {
//! lambda!(hello)
//! }
//!
//! fn hello(
//! request: Request,
//! _ctx: Context
//! ) -> Result<impl IntoResponse, HandlerError> {
//! Ok(format!(
//! "hello {}",
//! request
//! .query_string_parameters()
//! .get("name")
//! .unwrap_or_else(|| "stranger")
//! ))
//! }
//! ```
//!
//! You can also provide a closure directly to the `lambda!` macro
//!
//! ```rust,no_run
//! use lambda_http::{lambda, Request, RequestExt};
//!
//! fn main() {
//! lambda!(
//! |request: Request, context| Ok(
//! format!(
//! "hello {}",
//! request.query_string_parameters()
//! .get("name")
//! .unwrap_or_else(|| "stranger")
//! )
//! )
//! )
//! }
//! ```
pub use http::{self, Response};
use lambda_runtime::{self as lambda, error::HandlerError, Context};
use tokio::runtime::Runtime as TokioRuntime;
mod body;
mod ext;
pub mod request;
mod response;
mod strmap;
pub use crate::{body::Body, ext::RequestExt, response::IntoResponse, strmap::StrMap};
use crate::{request::LambdaRequest, response::LambdaResponse};
/// Type alias for `http::Request`s with a fixed `lambda_http::Body` body
pub type Request = http::Request<Body>;
/// Functions serving as ALB and API Gateway handlers must conform to this type.
pub trait Handler<R> {
/// Run the handler.
fn run(&mut self, event: Request, ctx: Context) -> Result<R, HandlerError>;
}
impl<F, R> Handler<R> for F
where
F: FnMut(Request, Context) -> Result<R, HandlerError>,
{
fn run(&mut self, event: Request, ctx: Context) -> Result<R, HandlerError> {
(*self)(event, ctx)
}
}
/// Creates a new `lambda_runtime::Runtime` and begins polling for ALB and API Gateway events
///
/// # Arguments
///
/// * `f` A type that conforms to the `Handler` interface.
///
/// # Panics
/// The function panics if the Lambda environment variables are not set.
pub fn start<R>(f: impl Handler<R>, runtime: Option<TokioRuntime>)
where
R: IntoResponse,
{
// handler requires a mutable ref
let mut func = f;
lambda::start(
|req: LambdaRequest<'_>, ctx: Context| {
let is_alb = req.request_context.is_alb();
func.run(req.into(), ctx)
.map(|resp| LambdaResponse::from_response(is_alb, resp.into_response()))
},
runtime,
)
}
/// A macro for starting new handler's poll for API Gateway and ALB events
#[macro_export]
macro_rules! lambda {
($handler:expr) => {
$crate::start($handler, None)
};
($handler:expr, $runtime:expr) => {
$crate::start($handler, Some($runtime))
};
($handler:ident) => {
$crate::start($handler, None)
};
($handler:ident, $runtime:expr) => {
$crate::start($handler, Some($runtime))
};
}