Skip to content

Commit e79183b

Browse files
authored
Add assertions about multi value query parameters. (#803)
* Add assertions about multi value query parameters. Signed-off-by: David Calavera <david.calavera@gmail.com> * Add test for Axum Query extractor. Use the axum_extra package as it seems to be more correct: https://github.com/tokio-rs/axum/blob/main/axum-extra/src/extract/query.rs Signed-off-by: David Calavera <david.calavera@gmail.com> * Update MSRV because Axum doesn't support our MSRV. Signed-off-by: David Calavera <david.calavera@gmail.com> --------- Signed-off-by: David Calavera <david.calavera@gmail.com>
1 parent 1face57 commit e79183b

File tree

8 files changed

+185
-75
lines changed

8 files changed

+185
-75
lines changed

.github/workflows/build-events.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
strategy:
1515
matrix:
1616
toolchain:
17-
- "1.65.0" # Current MSRV
17+
- "1.66.0" # Current MSRV
1818
- stable
1919
env:
2020
RUST_BACKTRACE: 1

.github/workflows/build-extension.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
strategy:
1919
matrix:
2020
toolchain:
21-
- "1.65.0" # Current MSRV
21+
- "1.66.0" # Current MSRV
2222
- stable
2323
env:
2424
RUST_BACKTRACE: 1

.github/workflows/build-runtime.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
strategy:
2020
matrix:
2121
toolchain:
22-
- "1.65.0" # Current MSRV
22+
- "1.66.0" # Current MSRV
2323
- stable
2424
env:
2525
RUST_BACKTRACE: 1

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ This will make your function compile much faster.
440440

441441
## Supported Rust Versions (MSRV)
442442

443-
The AWS Lambda Rust Runtime requires a minimum of Rust 1.65, and is not guaranteed to build on compiler versions earlier than that.
443+
The AWS Lambda Rust Runtime requires a minimum of Rust 1.66, and is not guaranteed to build on compiler versions earlier than that.
444444

445445
## Security
446446

lambda-http/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ default-features = false
5050
features = ["alb", "apigw"]
5151

5252
[dev-dependencies]
53+
axum-core = "0.4.3"
54+
axum-extra = { version = "0.9.2", features = ["query"] }
5355
lambda_runtime_api_client = { version = "0.9", path = "../lambda-runtime-api-client" }
5456
log = "^0.4"
5557
maplit = "1.0"

lambda-http/src/request.rs

Lines changed: 87 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,9 @@ mod tests {
570570
matches!(req_context, &RequestContext::ApiGatewayV2(_)),
571571
"expected ApiGatewayV2 context, got {req_context:?}"
572572
);
573+
574+
let (parts, _) = req.into_parts();
575+
assert_eq!("https://id.execute-api.us-east-1.amazonaws.com/my/path?parameter1=value1&parameter1=value2&parameter2=value", parts.uri.to_string());
573576
}
574577

575578
#[test]
@@ -699,12 +702,16 @@ mod tests {
699702
.is_empty());
700703

701704
// test RequestExt#query_string_parameters_ref does the right thing
702-
assert_eq!(
703-
request
704-
.query_string_parameters_ref()
705-
.and_then(|params| params.all("multivalueName")),
706-
Some(vec!["you", "me"])
707-
);
705+
let params = request.query_string_parameters();
706+
assert_eq!(Some(vec!["you", "me"]), params.all("multiValueName"));
707+
assert_eq!(Some(vec!["me"]), params.all("name"));
708+
709+
let query = request.uri().query().unwrap();
710+
assert!(query.contains("name=me"));
711+
assert!(query.contains("multiValueName=you&multiValueName=me"));
712+
let (parts, _) = request.into_parts();
713+
assert!(parts.uri.to_string().contains("name=me"));
714+
assert!(parts.uri.to_string().contains("multiValueName=you&multiValueName=me"));
708715
}
709716

710717
#[test]
@@ -724,12 +731,13 @@ mod tests {
724731
.is_empty());
725732

726733
// test RequestExt#query_string_parameters_ref does the right thing
727-
assert_eq!(
728-
request
729-
.query_string_parameters_ref()
730-
.and_then(|params| params.all("myKey")),
731-
Some(vec!["val1", "val2"])
732-
);
734+
let params = request.query_string_parameters();
735+
assert_eq!(Some(vec!["val1", "val2"]), params.all("myKey"));
736+
assert_eq!(Some(vec!["val3", "val4"]), params.all("myOtherKey"));
737+
738+
let query = request.uri().query().unwrap();
739+
assert!(query.contains("myKey=val1&myKey=val2"));
740+
assert!(query.contains("myOtherKey=val3&myOtherKey=val4"));
733741
}
734742

735743
#[test]
@@ -845,4 +853,71 @@ mod tests {
845853
assert_eq!("/Prod/path", apigw_path_with_stage(&Some("Prod".into()), "/Prod/path"));
846854
assert_eq!("/Prod/path", apigw_path_with_stage(&Some("Prod".into()), "/path"));
847855
}
856+
857+
#[tokio::test]
858+
#[cfg(feature = "apigw_rest")]
859+
async fn test_axum_query_extractor_apigw_rest() {
860+
use axum_core::extract::FromRequestParts;
861+
use axum_extra::extract::Query;
862+
// from docs
863+
// https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
864+
let input = include_str!("../tests/data/apigw_multi_value_proxy_request.json");
865+
let request = from_str(input).expect("failed to parse request");
866+
let (mut parts, _) = request.into_parts();
867+
868+
#[derive(Deserialize)]
869+
#[serde(rename_all = "camelCase")]
870+
struct Params {
871+
name: Vec<String>,
872+
multi_value_name: Vec<String>,
873+
}
874+
struct State;
875+
876+
let query = Query::<Params>::from_request_parts(&mut parts, &State).await.unwrap();
877+
assert_eq!(vec!["me"], query.0.name);
878+
assert_eq!(vec!["you", "me"], query.0.multi_value_name);
879+
}
880+
881+
#[tokio::test]
882+
#[cfg(feature = "apigw_http")]
883+
async fn test_axum_query_extractor_apigw_http() {
884+
use axum_core::extract::FromRequestParts;
885+
use axum_extra::extract::Query;
886+
let input = include_str!("../tests/data/apigw_v2_proxy_request.json");
887+
let request = from_str(input).expect("failed to parse request");
888+
let (mut parts, _) = request.into_parts();
889+
890+
#[derive(Deserialize)]
891+
struct Params {
892+
parameter1: Vec<String>,
893+
parameter2: Vec<String>,
894+
}
895+
struct State;
896+
897+
let query = Query::<Params>::from_request_parts(&mut parts, &State).await.unwrap();
898+
assert_eq!(vec!["value1", "value2"], query.0.parameter1);
899+
assert_eq!(vec!["value"], query.0.parameter2);
900+
}
901+
902+
#[tokio::test]
903+
#[cfg(feature = "alb")]
904+
async fn test_axum_query_extractor_alb() {
905+
use axum_core::extract::FromRequestParts;
906+
use axum_extra::extract::Query;
907+
let input = include_str!("../tests/data/alb_multi_value_request.json");
908+
let request = from_str(input).expect("failed to parse request");
909+
let (mut parts, _) = request.into_parts();
910+
911+
#[derive(Deserialize)]
912+
#[serde(rename_all = "camelCase")]
913+
struct Params {
914+
my_key: Vec<String>,
915+
my_other_key: Vec<String>,
916+
}
917+
struct State;
918+
919+
let query = Query::<Params>::from_request_parts(&mut parts, &State).await.unwrap();
920+
assert_eq!(vec!["val1", "val2"], query.0.my_key);
921+
assert_eq!(vec!["val3", "val4"], query.0.my_other_key);
922+
}
848923
}
Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,70 @@
11
{
2-
"requestContext": {
3-
"elb": {
4-
"targetGroupArn": "arn:aws:elasticloadbalancing:region:123456789012:targetgroup/my-target-group/6d0ecf831eec9f09"
5-
}
6-
},
7-
"httpMethod": "GET",
8-
"path": "/",
9-
"queryStringParameters": { "myKey": "val2" },
10-
"multiValueQueryStringParameters": { "myKey": ["val1", "val2"] },
11-
"headers": {
12-
"accept": "text/html,application/xhtml+xml",
13-
"accept-language": "en-US,en;q=0.8",
14-
"content-type": "text/plain",
15-
"cookie": "name1=value1",
16-
"host": "lambda-846800462-us-east-2.elb.amazonaws.com",
17-
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)",
18-
"x-amzn-trace-id": "Root=1-5bdb40ca-556d8b0c50dc66f0511bf520",
19-
"x-forwarded-for": "72.21.198.66",
20-
"x-forwarded-port": "443",
21-
"x-forwarded-proto": "https"
22-
},
23-
"multiValueHeaders": {
24-
"accept": ["text/html,application/xhtml+xml"],
25-
"accept-language": ["en-US,en;q=0.8"],
26-
"content-type": ["text/plain"],
27-
"cookie": ["name1=value1", "name2=value2"],
28-
"host": ["lambda-846800462-us-east-2.elb.amazonaws.com"],
29-
"user-agent": ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)"],
30-
"x-amzn-trace-id": ["Root=1-5bdb40ca-556d8b0c50dc66f0511bf520"],
31-
"x-forwarded-for": ["72.21.198.66"],
32-
"x-forwarded-port": ["443"],
33-
"x-forwarded-proto": ["https"]
34-
},
35-
"isBase64Encoded": false,
36-
"body": "request_body"
2+
"requestContext": {
3+
"elb": {
4+
"targetGroupArn": "arn:aws:elasticloadbalancing:region:123456789012:targetgroup/my-target-group/6d0ecf831eec9f09"
5+
}
6+
},
7+
"httpMethod": "GET",
8+
"path": "/",
9+
"queryStringParameters": {
10+
"myKey": "val2",
11+
"myOtherKey": "val3"
12+
},
13+
"multiValueQueryStringParameters": {
14+
"myKey": [
15+
"val1",
16+
"val2"
17+
],
18+
"myOtherKey": [
19+
"val3",
20+
"val4"
21+
]
22+
},
23+
"headers": {
24+
"accept": "text/html,application/xhtml+xml",
25+
"accept-language": "en-US,en;q=0.8",
26+
"content-type": "text/plain",
27+
"cookie": "name1=value1",
28+
"host": "lambda-846800462-us-east-2.elb.amazonaws.com",
29+
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)",
30+
"x-amzn-trace-id": "Root=1-5bdb40ca-556d8b0c50dc66f0511bf520",
31+
"x-forwarded-for": "72.21.198.66",
32+
"x-forwarded-port": "443",
33+
"x-forwarded-proto": "https"
34+
},
35+
"multiValueHeaders": {
36+
"accept": [
37+
"text/html,application/xhtml+xml"
38+
],
39+
"accept-language": [
40+
"en-US,en;q=0.8"
41+
],
42+
"content-type": [
43+
"text/plain"
44+
],
45+
"cookie": [
46+
"name1=value1",
47+
"name2=value2"
48+
],
49+
"host": [
50+
"lambda-846800462-us-east-2.elb.amazonaws.com"
51+
],
52+
"user-agent": [
53+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)"
54+
],
55+
"x-amzn-trace-id": [
56+
"Root=1-5bdb40ca-556d8b0c50dc66f0511bf520"
57+
],
58+
"x-forwarded-for": [
59+
"72.21.198.66"
60+
],
61+
"x-forwarded-port": [
62+
"443"
63+
],
64+
"x-forwarded-proto": [
65+
"https"
66+
]
67+
},
68+
"isBase64Encoded": false,
69+
"body": "request_body"
3770
}

lambda-http/tests/data/apigw_multi_value_proxy_request.json

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,74 +23,74 @@
2323
"X-Forwarded-Port": "443",
2424
"X-Forwarded-Proto": "https"
2525
},
26-
"multiValueHeaders":{
27-
"Accept":[
26+
"multiValueHeaders": {
27+
"Accept": [
2828
"*/*"
2929
],
30-
"Accept-Encoding":[
30+
"Accept-Encoding": [
3131
"gzip, deflate"
3232
],
33-
"cache-control":[
33+
"cache-control": [
3434
"no-cache"
3535
],
36-
"CloudFront-Forwarded-Proto":[
36+
"CloudFront-Forwarded-Proto": [
3737
"https"
3838
],
39-
"CloudFront-Is-Desktop-Viewer":[
39+
"CloudFront-Is-Desktop-Viewer": [
4040
"true"
4141
],
42-
"CloudFront-Is-Mobile-Viewer":[
42+
"CloudFront-Is-Mobile-Viewer": [
4343
"false"
4444
],
45-
"CloudFront-Is-SmartTV-Viewer":[
45+
"CloudFront-Is-SmartTV-Viewer": [
4646
"false"
4747
],
48-
"CloudFront-Is-Tablet-Viewer":[
48+
"CloudFront-Is-Tablet-Viewer": [
4949
"false"
5050
],
51-
"CloudFront-Viewer-Country":[
51+
"CloudFront-Viewer-Country": [
5252
"US"
5353
],
54-
"Content-Type":[
54+
"Content-Type": [
5555
"application/json"
5656
],
57-
"headerName":[
57+
"headerName": [
5858
"headerValue"
5959
],
60-
"Host":[
60+
"Host": [
6161
"gy415nuibc.execute-api.us-east-1.amazonaws.com"
6262
],
63-
"Postman-Token":[
63+
"Postman-Token": [
6464
"9f583ef0-ed83-4a38-aef3-eb9ce3f7a57f"
6565
],
66-
"User-Agent":[
66+
"User-Agent": [
6767
"PostmanRuntime/2.4.5"
6868
],
69-
"Via":[
69+
"Via": [
7070
"1.1 d98420743a69852491bbdea73f7680bd.cloudfront.net (CloudFront)"
7171
],
72-
"X-Amz-Cf-Id":[
72+
"X-Amz-Cf-Id": [
7373
"pn-PWIJc6thYnZm5P0NMgOUglL1DYtl0gdeJky8tqsg8iS_sgsKD1A=="
7474
],
75-
"X-Forwarded-For":[
75+
"X-Forwarded-For": [
7676
"54.240.196.186, 54.182.214.83"
7777
],
78-
"X-Forwarded-Port":[
78+
"X-Forwarded-Port": [
7979
"443"
8080
],
81-
"X-Forwarded-Proto":[
81+
"X-Forwarded-Proto": [
8282
"https"
8383
]
8484
},
8585
"queryStringParameters": {
8686
"name": "me",
87-
"multivalueName": "me"
87+
"multiValueName": "me"
8888
},
89-
"multiValueQueryStringParameters":{
90-
"name":[
89+
"multiValueQueryStringParameters": {
90+
"name": [
9191
"me"
9292
],
93-
"multivalueName":[
93+
"multiValueName": [
9494
"you",
9595
"me"
9696
]

0 commit comments

Comments
 (0)