Skip to content

Commit 797f0ab

Browse files
authored
Removed 'static bound requirements for the lambda_http crate and create a shared resources example for the crate (#333)
1 parent 0280da0 commit 797f0ab

File tree

3 files changed

+58
-16
lines changed

3 files changed

+58
-16
lines changed

lambda-http/examples/hello-http.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
use lambda_http::{
22
handler,
3-
lambda_runtime::{self, Context},
3+
lambda_runtime::{self, Context, Error},
44
IntoResponse, Request, RequestExt, Response,
55
};
66

7-
type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
8-
97
#[tokio::main]
108
async fn main() -> Result<(), Error> {
119
lambda_runtime::run(handler(func)).await?;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use lambda_http::{
2+
handler,
3+
lambda_runtime::{self, Context, Error},
4+
IntoResponse, Request, RequestExt, Response,
5+
};
6+
7+
struct SharedClient {
8+
name: &'static str,
9+
}
10+
11+
impl SharedClient {
12+
fn response(&self, req_id: String, first_name: &str) -> String {
13+
format!("{}: Client ({}) invoked by {}.", req_id, self.name, first_name)
14+
}
15+
}
16+
17+
#[tokio::main]
18+
async fn main() -> Result<(), Error> {
19+
// Create the "client" and a reference to it, so that we can pass this into the handler closure below.
20+
let shared_client = SharedClient {
21+
name: "random_client_name_1",
22+
};
23+
let shared_client_ref = &shared_client;
24+
25+
// Define a closure here that makes use of the shared client.
26+
let handler_func_closure = move |event: Request, ctx: Context| async move {
27+
Ok(match event.query_string_parameters().get("first_name") {
28+
Some(first_name) => shared_client_ref.response(ctx.request_id, first_name).into_response(),
29+
_ => Response::builder()
30+
.status(400)
31+
.body("Empty first name".into())
32+
.expect("failed to render response"),
33+
})
34+
};
35+
36+
// Pass the closure to the runtime here.
37+
lambda_runtime::run(handler(handler_func_closure)).await?;
38+
Ok(())
39+
}

lambda-http/src/lib.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ use crate::{
7777
};
7878
use std::{
7979
future::Future,
80+
marker::PhantomData,
8081
pin::Pin,
8182
task::{Context as TaskContext, Poll},
8283
};
@@ -87,28 +88,31 @@ pub type Request = http::Request<Body>;
8788
/// Functions serving as ALB and API Gateway REST and HTTP API handlers must conform to this type.
8889
///
8990
/// This can be viewed as a `lambda_runtime::Handler` constrained to `http` crate `Request` and `Response` types
90-
pub trait Handler: Sized {
91+
pub trait Handler<'a>: Sized {
9192
/// The type of Error that this Handler will return
9293
type Error;
9394
/// The type of Response this Handler will return
9495
type Response: IntoResponse;
9596
/// The type of Future this Handler will return
96-
type Fut: Future<Output = Result<Self::Response, Self::Error>> + Send + 'static;
97+
type Fut: Future<Output = Result<Self::Response, Self::Error>> + Send + 'a;
9798
/// Function used to execute handler behavior
9899
fn call(&self, event: Request, context: Context) -> Self::Fut;
99100
}
100101

101102
/// Adapts a [`Handler`](trait.Handler.html) to the `lambda_runtime::run` interface
102-
pub fn handler<H: Handler>(handler: H) -> Adapter<H> {
103-
Adapter { handler }
103+
pub fn handler<'a, H: Handler<'a>>(handler: H) -> Adapter<'a, H> {
104+
Adapter {
105+
handler,
106+
_pd: PhantomData,
107+
}
104108
}
105109

106110
/// An implementation of `Handler` for a given closure return a `Future` representing the computed response
107-
impl<F, R, Fut> Handler for F
111+
impl<'a, F, R, Fut> Handler<'a> for F
108112
where
109113
F: Fn(Request, Context) -> Fut,
110114
R: IntoResponse,
111-
Fut: Future<Output = Result<R, Error>> + Send + 'static,
115+
Fut: Future<Output = Result<R, Error>> + Send + 'a,
112116
{
113117
type Response = R;
114118
type Error = Error;
@@ -119,12 +123,12 @@ where
119123
}
120124

121125
#[doc(hidden)]
122-
pub struct TransformResponse<R, E> {
126+
pub struct TransformResponse<'a, R, E> {
123127
request_origin: RequestOrigin,
124-
fut: Pin<Box<dyn Future<Output = Result<R, E>> + Send>>,
128+
fut: Pin<Box<dyn Future<Output = Result<R, E>> + Send + 'a>>,
125129
}
126130

127-
impl<R, E> Future for TransformResponse<R, E>
131+
impl<'a, R, E> Future for TransformResponse<'a, R, E>
128132
where
129133
R: IntoResponse,
130134
{
@@ -146,11 +150,12 @@ where
146150
///
147151
/// See [this article](http://smallcultfollowing.com/babysteps/blog/2015/01/14/little-orphan-impls/)
148152
/// for a larger explaination of why this is nessessary
149-
pub struct Adapter<H: Handler> {
153+
pub struct Adapter<'a, H: Handler<'a>> {
150154
handler: H,
155+
_pd: PhantomData<&'a H>,
151156
}
152157

153-
impl<H: Handler> Handler for Adapter<H> {
158+
impl<'a, H: Handler<'a>> Handler<'a> for Adapter<'a, H> {
154159
type Response = H::Response;
155160
type Error = H::Error;
156161
type Fut = H::Fut;
@@ -159,9 +164,9 @@ impl<H: Handler> Handler for Adapter<H> {
159164
}
160165
}
161166

162-
impl<H: Handler> LambdaHandler<LambdaRequest<'_>, LambdaResponse> for Adapter<H> {
167+
impl<'a, H: Handler<'a>> LambdaHandler<LambdaRequest<'a>, LambdaResponse> for Adapter<'a, H> {
163168
type Error = H::Error;
164-
type Fut = TransformResponse<H::Response, Self::Error>;
169+
type Fut = TransformResponse<'a, H::Response, Self::Error>;
165170

166171
fn call(&self, event: LambdaRequest<'_>, context: Context) -> Self::Fut {
167172
let request_origin = event.request_origin();

0 commit comments

Comments
 (0)