Skip to content

Commit 3127592

Browse files
committed
Fix APIGW path with stage
APIGW HTTP has started adding the stage to the path in the event. This change checks if the stage is already a prefix in the path, and skips adding it if so. Signed-off-by: David Calavera <david.calavera@gmail.com>
1 parent f47d448 commit 3127592

File tree

4 files changed

+93
-8
lines changed

4 files changed

+93
-8
lines changed

lambda-http/src/request.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,17 @@ fn into_websocket_request(ag: ApiGatewayWebsocketProxyRequest) -> http::Request<
327327

328328
#[cfg(any(feature = "apigw_rest", feature = "apigw_http", feature = "apigw_websockets"))]
329329
fn apigw_path_with_stage(stage: &Option<String>, path: &str) -> String {
330-
match stage {
331-
None => path.into(),
332-
Some(stage) if stage == "$default" => path.into(),
333-
Some(stage) => format!("/{stage}{path}"),
330+
let stage = match stage {
331+
None => return path.into(),
332+
Some(stage) if stage == "$default" => return path.into(),
333+
Some(stage) => stage,
334+
};
335+
336+
let prefix = format!("/{stage}/");
337+
if path.starts_with(&prefix) {
338+
path.into()
339+
} else {
340+
format!("/{stage}{path}")
334341
}
335342
}
336343

@@ -531,7 +538,7 @@ mod tests {
531538
assert_eq!(req.method(), "GET");
532539
assert_eq!(
533540
req.uri(),
534-
"https://wt6mne2s9k.execute-api.us-west-2.amazonaws.com/test/test/hello?name=me"
541+
"https://wt6mne2s9k.execute-api.us-west-2.amazonaws.com/test/hello?name=me"
535542
);
536543

537544
// Ensure this is an APIGW request
@@ -733,7 +740,7 @@ mod tests {
733740
);
734741
let req = result.expect("failed to parse request");
735742
assert_eq!(req.method(), "GET");
736-
assert_eq!(req.uri(), "/test/test/hello?name=me");
743+
assert_eq!(req.uri(), "/test/hello?name=me");
737744
}
738745

739746
#[test]
@@ -768,4 +775,25 @@ mod tests {
768775
let url = build_request_uri("/path with spaces/and multiple segments", &HeaderMap::new(), None, None);
769776
assert_eq!("/path%20with%20spaces/and%20multiple%20segments", url);
770777
}
778+
779+
#[test]
780+
fn deserializes_apigw_http_request_with_stage_in_path() {
781+
let input = include_str!("../tests/data/apigw_v2_proxy_request_with_stage_in_path.json");
782+
let result = from_str(input);
783+
assert!(
784+
result.is_ok(),
785+
"event was not parsed as expected {result:?} given {input}"
786+
);
787+
let req = result.expect("failed to parse request");
788+
assert_eq!("/Prod/my/path", req.uri().path());
789+
assert_eq!("/Prod/my/path", req.raw_http_path());
790+
}
791+
792+
#[test]
793+
fn test_apigw_path_with_stage() {
794+
assert_eq!("/path", apigw_path_with_stage(&None, "/path"));
795+
assert_eq!("/path", apigw_path_with_stage(&Some("$default".into()), "/path"));
796+
assert_eq!("/Prod/path", apigw_path_with_stage(&Some("Prod".into()), "/Prod/path"));
797+
assert_eq!("/Prod/path", apigw_path_with_stage(&Some("Prod".into()), "/path"));
798+
}
771799
}

lambda-http/tests/data/apigw_no_host.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"path": "/test/hello",
2+
"path": "/hello",
33
"headers": {
44
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
55
"Accept-Encoding": "gzip, deflate, lzma, sdch, br",

lambda-http/tests/data/apigw_proxy_request.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"path": "/test/hello",
2+
"path": "/hello",
33
"headers": {
44
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
55
"Accept-Encoding": "gzip, deflate, lzma, sdch, br",
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"version": "2.0",
3+
"routeKey": "Prod",
4+
"rawPath": "/Prod/my/path",
5+
"rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
6+
"cookies": [
7+
"cookie1=value1",
8+
"cookie2=value2"
9+
],
10+
"headers": {
11+
"Header1": "value1",
12+
"Header2": "value2"
13+
},
14+
"queryStringParameters": {
15+
"parameter1": "value1,value2",
16+
"parameter2": "value"
17+
},
18+
"requestContext": {
19+
"accountId": "123456789012",
20+
"apiId": "api-id",
21+
"authorizer": {
22+
"jwt": {
23+
"claims": {
24+
"claim1": "value1",
25+
"claim2": "value2"
26+
},
27+
"scopes": [
28+
"scope1",
29+
"scope2"
30+
]
31+
}
32+
},
33+
"domainName": "id.execute-api.us-east-1.amazonaws.com",
34+
"domainPrefix": "id",
35+
"http": {
36+
"method": "POST",
37+
"path": "/Prod/my/path",
38+
"protocol": "HTTP/1.1",
39+
"sourceIp": "IP",
40+
"userAgent": "agent"
41+
},
42+
"requestId": "id",
43+
"routeKey": "Prod",
44+
"stage": "Prod",
45+
"time": "12/Mar/2020:19:03:58 +0000",
46+
"timeEpoch": 1583348638390
47+
},
48+
"body": "Hello from Lambda",
49+
"pathParameters": {
50+
"parameter1": "value1"
51+
},
52+
"isBase64Encoded": false,
53+
"stageVariables": {
54+
"stageVariable1": "value1",
55+
"stageVariable2": "value2"
56+
}
57+
}

0 commit comments

Comments
 (0)