diff --git a/lambda-http/src/request.rs b/lambda-http/src/request.rs index 6bef39ce..e5e3cd8d 100644 --- a/lambda-http/src/request.rs +++ b/lambda-http/src/request.rs @@ -440,18 +440,21 @@ impl<'a> From> for http::Request { let builder = http::Request::builder() .method(http_method) .uri({ - format!( - "{}://{}{}", - headers - .get("X-Forwarded-Proto") - .and_then(|val| val.to_str().ok()) - .unwrap_or("https"), - headers - .get(http::header::HOST) - .and_then(|val| val.to_str().ok()) - .unwrap_or_default(), - path - ) + let host = headers.get(http::header::HOST).and_then(|val| val.to_str().ok()); + match host { + Some(host) => { + format!( + "{}://{}{}", + headers + .get("X-Forwarded-Proto") + .and_then(|val| val.to_str().ok()) + .unwrap_or("https"), + host, + path + ) + } + None => path.to_string(), + } }) // multi-valued query string parameters are always a super // set of singly valued query string parameters, @@ -503,18 +506,21 @@ impl<'a> From> for http::Request { let builder = http::Request::builder() .method(http_method) .uri({ - format!( - "{}://{}{}", - headers - .get("X-Forwarded-Proto") - .and_then(|val| val.to_str().ok()) - .unwrap_or("https"), - headers - .get(http::header::HOST) - .and_then(|val| val.to_str().ok()) - .unwrap_or_default(), - path - ) + let host = headers.get(http::header::HOST).and_then(|val| val.to_str().ok()); + match host { + Some(host) => { + format!( + "{}://{}{}", + headers + .get("X-Forwarded-Proto") + .and_then(|val| val.to_str().ok()) + .unwrap_or("https"), + host, + path + ) + } + None => path.to_string(), + } }) // multi valued query string parameters are always a super // set of singly valued query string parameters, @@ -759,6 +765,22 @@ mod tests { assert_eq!(req.uri(), "http://127.0.0.1:3000/hello"); } + #[test] + fn deserialize_apigw_no_host() { + // generated from the 'apigateway-aws-proxy' test event template in the Lambda console + let input = include_str!("../tests/data/apigw_no_host.json"); + let result = from_str(input); + assert!( + result.is_ok(), + "event was not parsed as expected {:?} given {}", + result, + input + ); + let req = result.expect("failed to parse request"); + assert_eq!(req.method(), "GET"); + assert_eq!(req.uri(), "/test/hello"); + } + #[test] fn deserialize_with_null() { #[derive(Debug, PartialEq, Deserialize)] diff --git a/lambda-http/tests/data/apigw_no_host.json b/lambda-http/tests/data/apigw_no_host.json new file mode 100644 index 00000000..369c4870 --- /dev/null +++ b/lambda-http/tests/data/apigw_no_host.json @@ -0,0 +1,54 @@ +{ + "path": "/test/hello", + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, lzma, sdch, br", + "Accept-Language": "en-US,en;q=0.8", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Upgrade-Insecure-Requests": "1", + "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", + "Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==", + "X-Forwarded-For": "192.168.100.1, 192.168.1.1", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "pathParameters": { + "proxy": "hello" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "us4z18", + "stage": "test", + "requestId": "41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9", + "identity": { + "cognitoIdentityPoolId": "", + "accountId": "", + "cognitoIdentityId": "", + "caller": "", + "apiKey": "", + "sourceIp": "192.168.100.1", + "cognitoAuthenticationType": "", + "cognitoAuthenticationProvider": "", + "userArn": "", + "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", + "user": "" + }, + "resourcePath": "/{proxy+}", + "httpMethod": "GET", + "apiId": "wt6mne2s9k" + }, + "resource": "/{proxy+}", + "httpMethod": "GET", + "queryStringParameters": { + "name": "me" + }, + "stageVariables": { + "stageVarName": "stageVarValue" + } +} \ No newline at end of file