Skip to content

Commit 576f601

Browse files
authored
fix: null deserialization of stageVariables for sam local (#366)
1 parent 02a29ff commit 576f601

File tree

2 files changed

+88
-5
lines changed

2 files changed

+88
-5
lines changed

lambda-http/src/request.rs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ pub enum LambdaRequest<'a> {
3333
cookies: Option<Vec<Cow<'a, str>>>,
3434
#[serde(deserialize_with = "deserialize_headers")]
3535
headers: http::HeaderMap,
36-
#[serde(default)]
36+
#[serde(default, deserialize_with = "nullable_default")]
3737
query_string_parameters: StrMap,
38-
#[serde(default)]
38+
#[serde(default, deserialize_with = "nullable_default")]
3939
path_parameters: StrMap,
40-
#[serde(default)]
40+
#[serde(default, deserialize_with = "nullable_default")]
4141
stage_variables: StrMap,
4242
body: Option<Cow<'a, str>>,
4343
#[serde(default)]
@@ -55,7 +55,7 @@ pub enum LambdaRequest<'a> {
5555
/// the `lambda.multi_value_headers.enabled` target group setting turned on
5656
#[serde(default, deserialize_with = "deserialize_multi_value_headers")]
5757
multi_value_headers: http::HeaderMap,
58-
#[serde(deserialize_with = "nullable_default")]
58+
#[serde(default, deserialize_with = "nullable_default")]
5959
query_string_parameters: StrMap,
6060
/// For alb events these are only present when
6161
/// the `lambda.multi_value_headers.enabled` target group setting turned on
@@ -75,7 +75,7 @@ pub enum LambdaRequest<'a> {
7575
headers: http::HeaderMap,
7676
#[serde(default, deserialize_with = "deserialize_multi_value_headers")]
7777
multi_value_headers: http::HeaderMap,
78-
#[serde(deserialize_with = "nullable_default")]
78+
#[serde(default, deserialize_with = "nullable_default")]
7979
query_string_parameters: StrMap,
8080
#[serde(default, deserialize_with = "nullable_default")]
8181
multi_value_query_string_parameters: StrMap,
@@ -736,6 +736,29 @@ mod tests {
736736
);
737737
}
738738

739+
#[test]
740+
fn deserialize_apigw_v2_sam_local() {
741+
// manually generated from AWS SAM CLI
742+
// Steps to recreate:
743+
// * sam init
744+
// * Use, Zip Python 3.9, and Hello World example
745+
// * Change the template to use HttpApi instead of Api
746+
// * Change the function code to return the Lambda event serialized
747+
// * sam local start-api
748+
// * Invoke the API
749+
let input = include_str!("../tests/data/apigw_v2_sam_local.json");
750+
let result = from_str(input);
751+
assert!(
752+
result.is_ok(),
753+
"event was not parsed as expected {:?} given {}",
754+
result,
755+
input
756+
);
757+
let req = result.expect("failed to parse request");
758+
assert_eq!(req.method(), "GET");
759+
assert_eq!(req.uri(), "http://127.0.0.1:3000/hello");
760+
}
761+
739762
#[test]
740763
fn deserialize_with_null() {
741764
#[derive(Debug, PartialEq, Deserialize)]
@@ -749,4 +772,18 @@ mod tests {
749772
Test { foo: HashMap::new() }
750773
)
751774
}
775+
776+
#[test]
777+
fn deserialize_with_missing() {
778+
#[derive(Debug, PartialEq, Deserialize)]
779+
struct Test {
780+
#[serde(default, deserialize_with = "nullable_default")]
781+
foo: HashMap<String, String>,
782+
}
783+
784+
assert_eq!(
785+
serde_json::from_str::<Test>(r#"{}"#).expect("failed to deserialize"),
786+
Test { foo: HashMap::new() }
787+
)
788+
}
752789
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"version": "2.0",
3+
"routeKey": "GET /hello",
4+
"rawPath": "/hello",
5+
"rawQueryString": "",
6+
"cookies": [],
7+
"headers": {
8+
"Host": "127.0.0.1:3000",
9+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0",
10+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
11+
"Accept-Language": "en-US,en;q=0.5",
12+
"Accept-Encoding": "gzip, deflate",
13+
"Connection": "keep-alive",
14+
"Upgrade-Insecure-Requests": "1",
15+
"Sec-Fetch-Dest": "document",
16+
"Sec-Fetch-Mode": "navigate",
17+
"Sec-Fetch-Site": "none",
18+
"Sec-Fetch-User": "?1",
19+
"Cache-Control": "max-age=0",
20+
"X-Forwarded-Proto": "http",
21+
"X-Forwarded-Port": "3000"
22+
},
23+
"queryStringParameters": {},
24+
"requestContext": {
25+
"accountId": "123456789012",
26+
"apiId": "1234567890",
27+
"http": {
28+
"method": "GET",
29+
"path": "/hello",
30+
"protocol": "HTTP/1.1",
31+
"sourceIp": "127.0.0.1",
32+
"userAgent": "Custom User Agent String"
33+
},
34+
"requestId": "1ac06eee-f687-44ec-9036-dfd49d0be0a3",
35+
"routeKey": "GET /hello",
36+
"stage": "$default",
37+
"time": "16/Nov/2021:11:54:33 +0000",
38+
"timeEpoch": 1637063673,
39+
"domainName": "localhost",
40+
"domainPrefix": "localhost"
41+
},
42+
"body": "",
43+
"pathParameters": {},
44+
"stageVariables": null,
45+
"isBase64Encoded": false
46+
}

0 commit comments

Comments
 (0)