Skip to content

Commit eeb849b

Browse files
authored
fix: create a valid URL for REST APIs and ALBs when the host header i… (#369)
* fix: create a valid URL for REST APIs and ALBs when the host header is missing * chore: cargo fmt
1 parent 576f601 commit eeb849b

File tree

2 files changed

+100
-24
lines changed

2 files changed

+100
-24
lines changed

lambda-http/src/request.rs

+46-24
Original file line numberDiff line numberDiff line change
@@ -440,18 +440,21 @@ impl<'a> From<LambdaRequest<'a>> for http::Request<Body> {
440440
let builder = http::Request::builder()
441441
.method(http_method)
442442
.uri({
443-
format!(
444-
"{}://{}{}",
445-
headers
446-
.get("X-Forwarded-Proto")
447-
.and_then(|val| val.to_str().ok())
448-
.unwrap_or("https"),
449-
headers
450-
.get(http::header::HOST)
451-
.and_then(|val| val.to_str().ok())
452-
.unwrap_or_default(),
453-
path
454-
)
443+
let host = headers.get(http::header::HOST).and_then(|val| val.to_str().ok());
444+
match host {
445+
Some(host) => {
446+
format!(
447+
"{}://{}{}",
448+
headers
449+
.get("X-Forwarded-Proto")
450+
.and_then(|val| val.to_str().ok())
451+
.unwrap_or("https"),
452+
host,
453+
path
454+
)
455+
}
456+
None => path.to_string(),
457+
}
455458
})
456459
// multi-valued query string parameters are always a super
457460
// set of singly valued query string parameters,
@@ -503,18 +506,21 @@ impl<'a> From<LambdaRequest<'a>> for http::Request<Body> {
503506
let builder = http::Request::builder()
504507
.method(http_method)
505508
.uri({
506-
format!(
507-
"{}://{}{}",
508-
headers
509-
.get("X-Forwarded-Proto")
510-
.and_then(|val| val.to_str().ok())
511-
.unwrap_or("https"),
512-
headers
513-
.get(http::header::HOST)
514-
.and_then(|val| val.to_str().ok())
515-
.unwrap_or_default(),
516-
path
517-
)
509+
let host = headers.get(http::header::HOST).and_then(|val| val.to_str().ok());
510+
match host {
511+
Some(host) => {
512+
format!(
513+
"{}://{}{}",
514+
headers
515+
.get("X-Forwarded-Proto")
516+
.and_then(|val| val.to_str().ok())
517+
.unwrap_or("https"),
518+
host,
519+
path
520+
)
521+
}
522+
None => path.to_string(),
523+
}
518524
})
519525
// multi valued query string parameters are always a super
520526
// set of singly valued query string parameters,
@@ -759,6 +765,22 @@ mod tests {
759765
assert_eq!(req.uri(), "http://127.0.0.1:3000/hello");
760766
}
761767

768+
#[test]
769+
fn deserialize_apigw_no_host() {
770+
// generated from the 'apigateway-aws-proxy' test event template in the Lambda console
771+
let input = include_str!("../tests/data/apigw_no_host.json");
772+
let result = from_str(input);
773+
assert!(
774+
result.is_ok(),
775+
"event was not parsed as expected {:?} given {}",
776+
result,
777+
input
778+
);
779+
let req = result.expect("failed to parse request");
780+
assert_eq!(req.method(), "GET");
781+
assert_eq!(req.uri(), "/test/hello");
782+
}
783+
762784
#[test]
763785
fn deserialize_with_null() {
764786
#[derive(Debug, PartialEq, Deserialize)]
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"path": "/test/hello",
3+
"headers": {
4+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
5+
"Accept-Encoding": "gzip, deflate, lzma, sdch, br",
6+
"Accept-Language": "en-US,en;q=0.8",
7+
"CloudFront-Forwarded-Proto": "https",
8+
"CloudFront-Is-Desktop-Viewer": "true",
9+
"CloudFront-Is-Mobile-Viewer": "false",
10+
"CloudFront-Is-SmartTV-Viewer": "false",
11+
"CloudFront-Is-Tablet-Viewer": "false",
12+
"CloudFront-Viewer-Country": "US",
13+
"Upgrade-Insecure-Requests": "1",
14+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
15+
"Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)",
16+
"X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==",
17+
"X-Forwarded-For": "192.168.100.1, 192.168.1.1",
18+
"X-Forwarded-Port": "443",
19+
"X-Forwarded-Proto": "https"
20+
},
21+
"pathParameters": {
22+
"proxy": "hello"
23+
},
24+
"requestContext": {
25+
"accountId": "123456789012",
26+
"resourceId": "us4z18",
27+
"stage": "test",
28+
"requestId": "41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9",
29+
"identity": {
30+
"cognitoIdentityPoolId": "",
31+
"accountId": "",
32+
"cognitoIdentityId": "",
33+
"caller": "",
34+
"apiKey": "",
35+
"sourceIp": "192.168.100.1",
36+
"cognitoAuthenticationType": "",
37+
"cognitoAuthenticationProvider": "",
38+
"userArn": "",
39+
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
40+
"user": ""
41+
},
42+
"resourcePath": "/{proxy+}",
43+
"httpMethod": "GET",
44+
"apiId": "wt6mne2s9k"
45+
},
46+
"resource": "/{proxy+}",
47+
"httpMethod": "GET",
48+
"queryStringParameters": {
49+
"name": "me"
50+
},
51+
"stageVariables": {
52+
"stageVarName": "stageVarValue"
53+
}
54+
}

0 commit comments

Comments
 (0)