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

Double cookie headers #121

Closed
raymondbutchermpg opened this issue Jan 11, 2023 · 4 comments · Fixed by #122
Closed

Double cookie headers #121

raymondbutchermpg opened this issue Jan 11, 2023 · 4 comments · Fixed by #122

Comments

@raymondbutchermpg
Copy link

raymondbutchermpg commented Jan 11, 2023

Hi. I'm trying to use this with a Lambda Function URL and am seeing duplicate cookie headers.

I run this command:

curl -H "Cookie: test=hi" https://REDACTED.lambda-url.eu-west-2.on.aws/

The Lambda function behind it responds with the request headers. The response is this, with 2 cookie headers:

x-amzn-tls-cipher-suite: ECDHE-RSA-AES128-GCM-SHA256
x-amzn-tls-version: TLSv1.2
x-amzn-trace-id: REDACTED
cookie: test=hi
cookie: test=hi
x-forwarded-proto: https
host: REDACTED.lambda-url.eu-west-2.on.aws
x-forwarded-port: 443
x-forwarded-for: REDACTED
accept: */*
user-agent: curl/7.68.0
x-amzn-request-context: REDACTED

Contents of Dockerfile:

FROM python:3.10.8-slim-bullseye
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.6.0 /lambda-adapter /opt/extensions/lambda-adapter
COPY server.py ./
CMD python server.py

Contents of server.py:

from http.server import HTTPServer, BaseHTTPRequestHandler


class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(self.headers.as_bytes())


httpd = HTTPServer(('0.0.0.0', 8080), SimpleHTTPRequestHandler)
httpd.serve_forever()

I changed the Lambda function to a Python runtime zip package with this code:

import json

def lambda_handler(event, context):
    return json.dumps(event, indent=2)

And the curl response becomes this, with only 1 cookie:

{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/",
  "rawQueryString": "",
  "cookies": [
    "test=hi"
  ],
  "headers": {
    "x-amzn-tls-cipher-suite": "ECDHE-RSA-AES128-GCM-SHA256",
    "x-amzn-tls-version": "TLSv1.2",
    "x-amzn-trace-id": "REDACTED",
    "cookie": "test=hi",
    "x-forwarded-proto": "https",
    "host": "REDACTED.lambda-url.eu-west-2.on.aws",
    "x-forwarded-port": "443",
    "x-forwarded-for": "REDACTED",
    "accept": "*/*",
    "user-agent": "curl/7.68.0"
  },
  "requestContext": {
    "accountId": "anonymous",
    "apiId": "REDACTED",
    "domainName": "REDACTED.lambda-url.eu-west-2.on.aws",
    "domainPrefix": "REDACTED",
    "http": {
      "method": "GET",
      "path": "/",
      "protocol": "HTTP/1.1",
      "sourceIp": "REDACTED",
      "userAgent": "curl/7.68.0"
    },
    "requestId": "REDACTED",
    "routeKey": "$default",
    "stage": "$default",
    "time": "11/Jan/2023:11:45:34 +0000",
    "timeEpoch": 1673437534837
  },
  "isBase64Encoded": false
}

Unfortunately the extra header triggers a problem in my Gunicorn/Flask project making it unable to parse the session cookie. That seems like a bug in one of those projects, but it shouldn't be receiving 2 cookie headers in the first place.

@raymondbutchermpg
Copy link
Author

I haven't used Rust before but this might be the culprit:

https://github.com/awslabs/aws-lambda-rust-runtime/blob/381ac09653c8f802d63badce2cf8eaf4ef407d4b/lambda-http/src/request.rs#L121-L127

    let mut headers = ag.headers;
    update_xray_trace_id_header(&mut headers);
    if let Some(cookies) = ag.cookies {
        if let Ok(header_value) = HeaderValue::from_str(&cookies.join(";")) {
            headers.append(http::header::COOKIE, header_value);
        }
    }

It copies all of the the headers from the event, and then appends a cookie header if the event also contains cookies. If you look at the event JSON in my original comment, you can see the headers object already includes the cookie header.

@bnusunny
Copy link
Contributor

Thanks for reporting this issue. I can reproduce it with Lambda Function URL. I will investigate.

And, this does not happen with API GW HTTP API. You can use API GW as a workaround before this issue is fixed for Function URLs.

@bnusunny
Copy link
Contributor

bnusunny commented Jan 11, 2023

API GW HTTP API v2 request format is slightly different. It does not have cookie in the headers object.

We should use headers.insert() instead of headers.append() in lambda-http crate. I will send a PR there.

@raymondbutchermpg
Copy link
Author

Thanks for the quick fix @bnusunny - it's much appreciated!

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

Successfully merging a pull request may close this issue.

2 participants