Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong queryStringParameters after serializing AlbTargetGroupRequest. #954

Open
DiscreteTom opened this issue Jan 3, 2025 · 2 comments
Open

Comments

@DiscreteTom
Copy link

DiscreteTom commented Jan 3, 2025

Currently AlbTargetGroupRequest::query_string_parameters is serialized with the default QueryMap serializer, which will serialize the value as a list instead of a string.

#[serde(default)]
pub query_string_parameters: QueryMap,

It should be serialized like in APIGW event, using query_map::serde::aws_api_gateway_v1::serialize_query_string_parameters.

#[serde(serialize_with = "query_map::serde::aws_api_gateway_v1::serialize_query_string_parameters")]
pub query_string_parameters: QueryMap,

Minimal repro:

#[cfg(test)]
mod tests {
    use aws_lambda_events::alb::{AlbTargetGroupRequest, AlbTargetGroupRequestContext, ElbContext};
    use axum::http::{request::Builder, Method};
    use std::collections::HashMap;

    #[test]
    fn test() {
        let (parts, body) = Builder::new()
            .method(Method::GET)
            .uri("https://example.com/")
            .header("key", "value")
            .body("")
            .unwrap()
            .into_parts();

        let query_string_parameters = HashMap::from([("k".to_string(), "v".to_string())]).into();

        let json = serde_json::to_string(&AlbTargetGroupRequest {
            http_method: parts.method,
            headers: parts.headers,
            path: "/".to_string().into(),
            query_string_parameters,
            body: body.to_string().into(),
            is_base64_encoded: false,
            request_context: AlbTargetGroupRequestContext {
                elb: ElbContext { target_group_arn: None },
            },
            multi_value_headers: Default::default(),
            multi_value_query_string_parameters: Default::default(),
        })
        .unwrap();

        println!("{}", json);
    }
}

Got output:

{"httpMethod":"GET","path":"/","queryStringParameters":{"k":["v"]},"multiValueQueryStringParameters":{},"headers":{"key":"value"},"multiValueHeaders":{},"requestContext":{"elb":{"targetGroupArn":null}},"isBase64Encoded":false,"body":""}

Expected: the value of "k" in queryStringParameters should be a string "v" instead of a list ["v"].

@bnusunny
Copy link
Contributor

bnusunny commented Jan 3, 2025

This is actually the correct behavior. You can verify this by using a real alb to trigger a Lambda function.

@DiscreteTom
Copy link
Author

Tested with a real ALB (multi-value-headers disabled) and a nodejs lambda function to print the event using console.log(JSON.stringify(event));. Here are the results:

Case 1:

curl 1234567890.us-east-1.elb.amazonaws.com/lambda?k=v

Output:

{
    "requestContext": {
        "elb": {
            "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:1234567890:targetgroup/lambda-print-request/1234567890"
        }
    },
    "httpMethod": "GET",
    "path": "/lambda",
    "queryStringParameters": {
        "k": "v"
    },
    "headers": {
        "accept": "*/*",
        "host": "1234567890.us-east-1.elb.amazonaws.com",
        "user-agent": "curl/8.9.1",
        "x-amzn-trace-id": "Root=1-1234567890-1234567890",
        "x-forwarded-for": "1.1.1.1",
        "x-forwarded-port": "80",
        "x-forwarded-proto": "http"
    },
    "body": "",
    "isBase64Encoded": false
}

Case 2:

curl "1234567890.us-east-1.elb.amazonaws.com/lambda?k=v&k=v2"

Output:

{
    "requestContext": {
        "elb": {
            "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:1234567890:targetgroup/lambda-print-request/1234567890"
        }
    },
    "httpMethod": "GET",
    "path": "/lambda",
    "queryStringParameters": {
        "k": "v2"
    },
    "headers": {
        "accept": "*/*",
        "host": "1234567890.us-east-1.elb.amazonaws.com",
        "user-agent": "curl/8.9.1",
        "x-amzn-trace-id": "Root=1-1234567890-1234567890",
        "x-forwarded-for": "1.1.1.1",
        "x-forwarded-port": "80",
        "x-forwarded-proto": "http"
    },
    "body": "",
    "isBase64Encoded": false
}

The behavior follows the documentation:

With the default format, the load balancer uses the last value sent by the client and sends you an event that includes query string parameters using queryStringParameters.

DiscreteTom added a commit to DiscreteTom/aws-lambda-rust-runtime that referenced this issue Jan 8, 2025
…e last value of each key

and prevent unnecessary mem alloc. awslabs#954
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants