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
use std::result::Result;
use lambda_http::{Body, Request, Response};
use lambda_runtime::{error::HandlerError, Context};
use crate::error;
type LambdaResponse = Response<Body>;
type HandlerResult<E> = Result<LambdaResponse, E>;
pub type Handler<E = error::Error> = Box<dyn Fn(Request, Context) -> HandlerResult<E>>;
pub trait WrappingHandler<E> {
fn wrap_with<M: Fn(Handler<E>) -> Handler<E>>(self, middleware: M) -> Handler<E>
where
Self: 'static + Fn(Request, Context) -> Result<LambdaResponse, E> + Sized,
{
middleware(Box::new(self))
}
fn handler(self) -> Handler<HandlerError>
where
Self: 'static + Fn(Request, Context) -> Result<LambdaResponse, E> + Sized,
E: Send + Sync + failure::Fail + From<failure::Error>,
{
Box::new(move |request, context| {
Ok(self(request, context).map_err(|e| -> failure::Error { e.into() })?)
})
}
}
impl<E> WrappingHandler<E> for Handler<E> {}
pub fn default_handler<E>() -> Handler<E> {
Box::new(|_, _| Ok(Response::default()))
}
#[cfg(test)]
mod tests {
use std::fmt::Debug;
use lambda_http::{
http::{header::HeaderValue, StatusCode},
Body, IntoResponse,
};
use lambda_runtime::Context;
use crate::middleware::{body, header};
use super::*;
fn echo_body(_: Handler) -> Handler {
Box::new(move |request, _context| Ok(request.into_body().into_response()))
}
fn handler_resp<E: Debug>(handler: Handler<E>) -> LambdaResponse {
let request = Request::default();
let context = Context::default();
handler(request, context).unwrap()
}
#[test]
fn test_wrapping_handler_echo_body() {
let handler = default_handler().wrap_with(echo_body).handler();
let resp = handler_resp(handler);
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.into_body(), Body::default());
}
#[test]
fn test_wrapping_handler_hello_world() {
let handler = default_handler::<error::Error>()
.wrap_with(body("Hello, world!"))
.handler();
let resp = handler_resp(handler);
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.into_body(), Body::Text("Hello, world!".to_string()));
}
#[test]
fn test_wrapping_handler_chaining() {
let handler = default_handler::<error::Error>()
.wrap_with(body("Hello, world!"))
.wrap_with(header("x-hello", "world"))
.handler();
let resp = handler_resp(handler);
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get("x-hello"),
Some(&HeaderValue::from_static("world"))
);
assert_eq!(resp.into_body(), Body::Text("Hello, world!".to_string()));
}
}