Skip to content

Commit c01811a

Browse files
authored
Set env_config value and add Serialize/Deserialize for Context (#308)
* Added changes from 2020 on top of v.0.3 master * Init Lambda env vars for an end to end test * Formatting change for cargo fmt * Bumped the version to 0.3.1 * Added debugging section to ReadMe * ReadMe Debugging section mentioned non-AWS project * Roll back version bump back to 0.3.0
1 parent d3ff435 commit c01811a

File tree

4 files changed

+53
-13
lines changed

4 files changed

+53
-13
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ $ unzip -o \
155155
# Ctrl-D to yield control back to your function
156156
```
157157

158+
### Debugging
159+
160+
Lambdas can be run and debugged locally using a special [Lambda debug proxy](https://github.com/rimutaka/lambda-debug-proxy) (a non-AWS repo maintained by @rimutaka), which is a Lambda function that forwards incoming requests to one AWS SQS queue and reads responses from another queue. A local proxy running on your development computer reads the queue, calls your lambda locally and sends back the response. This approach allows debugging of Lambda functions locally while being part of your AWS workflow. The lambda handler code does not need to be modified between the local and AWS versions.
161+
158162
## `lambda`
159163

160164
`lambda_runtime` is a library for authoring reliable and performant Rust-based AWS Lambda functions. At a high level, it provides a few major components:

lambda-runtime/src/client.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ mod endpoint_tests {
6767
use hyper::{server::conn::Http, service::service_fn, Body};
6868
use serde_json::json;
6969
use simulated::DuplexStreamWrapper;
70-
use std::convert::TryFrom;
70+
use std::{convert::TryFrom, env};
7171
use tokio::{
7272
io::{self, AsyncRead, AsyncWrite},
7373
select,
@@ -274,9 +274,30 @@ mod endpoint_tests {
274274
}
275275
let f = crate::handler_fn(func);
276276

277+
// set env vars needed to init Config if they are not already set in the environment
278+
if env::var("AWS_LAMBDA_RUNTIME_API").is_err() {
279+
env::set_var("AWS_LAMBDA_RUNTIME_API", "http://localhost:9001");
280+
}
281+
if env::var("AWS_LAMBDA_FUNCTION_NAME").is_err() {
282+
env::set_var("AWS_LAMBDA_FUNCTION_NAME", "test_fn");
283+
}
284+
if env::var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE").is_err() {
285+
env::set_var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "128");
286+
}
287+
if env::var("AWS_LAMBDA_FUNCTION_VERSION").is_err() {
288+
env::set_var("AWS_LAMBDA_FUNCTION_VERSION", "1");
289+
}
290+
if env::var("AWS_LAMBDA_LOG_STREAM_NAME").is_err() {
291+
env::set_var("AWS_LAMBDA_LOG_STREAM_NAME", "test_stream");
292+
}
293+
if env::var("AWS_LAMBDA_LOG_GROUP_NAME").is_err() {
294+
env::set_var("AWS_LAMBDA_LOG_GROUP_NAME", "test_log");
295+
}
296+
let config = crate::Config::from_env().expect("Failed to read env vars");
297+
277298
let client = &runtime.client;
278299
let incoming = incoming(client).take(1);
279-
runtime.run(incoming, f).await?;
300+
runtime.run(incoming, f, &config).await?;
280301

281302
// shutdown server
282303
tx.send(()).expect("Receiver has been dropped");

lambda-runtime/src/lib.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use types::Diagnostic;
3434
pub type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
3535

3636
/// Configuration derived from environment variables.
37-
#[derive(Debug, Default, Clone, PartialEq)]
37+
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
3838
pub struct Config {
3939
/// The host and port of the [runtime API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html).
4040
pub endpoint: String,
@@ -54,12 +54,15 @@ impl Config {
5454
/// Attempts to read configuration from environment variables.
5555
pub fn from_env() -> Result<Self, Error> {
5656
let conf = Config {
57-
endpoint: env::var("AWS_LAMBDA_RUNTIME_API")?,
58-
function_name: env::var("AWS_LAMBDA_FUNCTION_NAME")?,
59-
memory: env::var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE")?.parse::<i32>()?,
60-
version: env::var("AWS_LAMBDA_FUNCTION_VERSION")?,
61-
log_stream: env::var("AWS_LAMBDA_LOG_STREAM_NAME")?,
62-
log_group: env::var("AWS_LAMBDA_LOG_GROUP_NAME")?,
57+
endpoint: env::var("AWS_LAMBDA_RUNTIME_API").expect("Missing AWS_LAMBDA_RUNTIME_API env var"),
58+
function_name: env::var("AWS_LAMBDA_FUNCTION_NAME").expect("Missing AWS_LAMBDA_FUNCTION_NAME env var"),
59+
memory: env::var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE")
60+
.expect("Missing AWS_LAMBDA_FUNCTION_MEMORY_SIZE env var")
61+
.parse::<i32>()
62+
.expect("AWS_LAMBDA_FUNCTION_MEMORY_SIZE env var is not <i32>"),
63+
version: env::var("AWS_LAMBDA_FUNCTION_VERSION").expect("Missing AWS_LAMBDA_FUNCTION_VERSION env var"),
64+
log_stream: env::var("AWS_LAMBDA_LOG_STREAM_NAME").expect("Missing AWS_LAMBDA_LOG_STREAM_NAME env var"),
65+
log_group: env::var("AWS_LAMBDA_LOG_GROUP_NAME").expect("Missing AWS_LAMBDA_LOG_GROUP_NAME env var"),
6366
};
6467
Ok(conf)
6568
}
@@ -133,6 +136,7 @@ where
133136
&self,
134137
incoming: impl Stream<Item = Result<http::Response<hyper::Body>, Error>> + Send,
135138
handler: F,
139+
config: &Config,
136140
) -> Result<(), Error>
137141
where
138142
F: Handler<A, B> + Send + Sync + 'static,
@@ -150,6 +154,7 @@ where
150154
let (parts, body) = event.into_parts();
151155

152156
let ctx: Context = Context::try_from(parts.headers)?;
157+
let ctx: Context = ctx.with_config(config);
153158
let body = hyper::body::to_bytes(body).await?;
154159
trace!("{}", std::str::from_utf8(&body)?); // this may be very verbose
155160
let body = serde_json::from_slice(&body)?;
@@ -299,16 +304,16 @@ where
299304
{
300305
trace!("Loading config from env");
301306
let config = Config::from_env()?;
302-
let uri = config.endpoint.try_into().expect("Unable to convert to URL");
307+
let uri = config.endpoint.clone().try_into().expect("Unable to convert to URL");
303308
let runtime = Runtime::builder()
304309
.with_connector(HttpConnector::new())
305310
.with_endpoint(uri)
306311
.build()
307-
.expect("Unable create runtime");
312+
.expect("Unable to create a runtime");
308313

309314
let client = &runtime.client;
310315
let incoming = incoming(client);
311-
runtime.run(incoming, handler).await
316+
runtime.run(incoming, handler, &config).await
312317
}
313318

314319
fn type_name_of_val<T>(_: T) -> &'static str {

lambda-runtime/src/types.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pub struct CognitoIdentity {
9393
/// are populated using the [Lambda environment variables](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html)
9494
/// and the headers returned by the poll request to the Runtime APIs.
9595
#[non_exhaustive]
96-
#[derive(Clone, Debug, PartialEq, Default)]
96+
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
9797
pub struct Context {
9898
/// The AWS request ID generated by the Lambda service.
9999
pub request_id: String,
@@ -141,3 +141,13 @@ impl TryFrom<HeaderMap> for Context {
141141
Ok(ctx)
142142
}
143143
}
144+
145+
impl Context {
146+
/// Add environment details to the context by setting `env_config`.
147+
pub fn with_config(self, config: &Config) -> Self {
148+
Self {
149+
env_config: config.clone(),
150+
..self
151+
}
152+
}
153+
}

0 commit comments

Comments
 (0)