4
votes

My setup looks like this:

|––––––––––––|                  |–––––––––––––|     |–––––––––––––––––|
|            |  <- origin 1 ->  | API Gateway | <-> | Lambda function |
|            |                  |–––––––––––––|     |–––––––––––––––––|
| CloudFront |  
|            |                  |–––––––––––––|
|            |  <- origin 2 ->  |  S3 bucket  |
|––––––––––––|                  |–––––––––––––|

I need CloudFront in front of the API Gateway to get automatic http->https redirection.
I'm using a custom login.example.com subdomain w/ CloudFront.
API Gateway's generated URL is the origin 1 for CloudFront distribution.

This all works as expected.

I can even return one Set-Cookie header from the lambda function and it will get passed on until it reaches the browser.

{
  "statusCode": 302,
  "body": "",
  "headers": {
    "location": "/test",
    "surrogate-control": "no-store",
    "cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate",
    "pragma": "no-cache",
    "expires": "0",
    "content-length": "0",
    "date": "Fri, 19 Feb 2021 17:25:56 GMT",
    "connection": "keep-alive",
    "set-cookie": "cookie1=68abcdbefbef7d84c26e68; Max-Age=2592000; Domain=example.com; Path=/; HttpOnly; Secure; SameSite=Strict"
  },
  "isBase64Encoded": false
}

Adding another one isn't working - as expected when you look at the docs:

{
  "statusCode": 302,
  "headers": {
    "location": "/test",
    "set-cookie": [
      "cookie1=68abcdbefbef7d84c26e68; Max-Age=2592000; Domain=example.com; Path=/; HttpOnly; Secure; SameSite=Strict",
      "cookie2-login=; Max-Age=0; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure"
    ],
    "surrogate-control": "no-store",
    "cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate",
    "pragma": "no-cache",
    "expires": "0",
    "content-length": "0"
  }
}

Both of these will be ignored/removed.

But even when I'm using the multiValueHeaders object to return more than one of the same kind like this:

{
  "statusCode": 302,
  "body": "",
  "headers": {
    "location": "/test",
    "surrogate-control": "no-store",
    "cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate",
    "pragma": "no-cache",
    "expires": "0",
    "content-length": "0",
    "date": "Fri, 19 Feb 2021 17:25:56 GMT",
    "connection": "keep-alive"
  },
  "isBase64Encoded": false,
  "multiValueHeaders": {
    "Set-Cookie": [
      "cookie1=68abcdbefbef7d84c26e68; Max-Age=2592000; Domain=example.com; Path=/; HttpOnly; Secure; SameSite=Strict",
      "cookie2-login=; Max-Age=0; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure"
    ]
  }
}

the API Gateway removes/ignores them from the response it passes on to CloudFront.

What am I doing wrong?
Do I have to map something in the API Gateway when using the multiValueHeaders?
Normal headers['set-cookie'] is passed on automatically but multiValueHeaders not?
Are the additional attributes a problem?
Is it a problem that I'm trying to set the cookie for the root-domain and not the login.example.com domain?

1

1 Answers

1
votes

Finally found the answer myself:

The new payload format (2.0) does not support multiValueHeaders.

Working with AWS Lambda proxy integrations for HTTP APIs

[...] Format 2.0 doesn't have multiValueHeaders or multiValueQueryStringParameters fields. Duplicate headers are combined with commas and included in the headers field. Duplicate query strings are combined with commas and included in the queryStringParameters field. [...]

https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html

So I'm rewriting the set-cookie headers to different spellings:

Set-cookie
sEt-cookie
seT-cookie

That was the way you had to do it before there were multiValueHeaders - but it seems it is still the only when you're using the new payload format :(