How can I send multiple Set-Cookie headers from API Gateway using a proxied Lambda

余生长醉 提交于 2019-12-01 17:13:07

Having experimented with this I've concluded that it isn't currently possible (will update if I hear back otherwise from AWS support).

I've tried sending the following manually curated JSON as a response:

{
  "statusCode": 200,
  "body": "testing multiple set-cookie headers",
  "headers": {
    "X-Test-Header": "baking experiment",
    "Set-Cookie": "cookie1=chocolate-chip",
    "Set-Cookie": "cookie2=oatmeal",
    "Content-Type": "text/plain"
  }
}

The cookies that API gateway returns in response to a CURL request are:

< Content-Type: text/plain
< Content-Length: 35
< Connection: keep-alive
< Date: Thu, 29 Sep 2016 11:22:09 GMT
< Set-Cookie: cookie2=oatmeal
< X-Test-Header: baking experiment
< X-Cache: Miss from cloudfront

As you can see the first Set-Cookie is dropped on the floor.

Ideally the JSON format for the headers in the JSON output format should be something like:

{
  "statusCode": httpStatusCode,
  "headers": [
    { "headerName": "headerValue" },
    ...
  ],
  "body": "..."
}

As Mark B pointed out, you can/should achieve this by setting multiple cookie name/value pairs in a single Set-Cookie header. The browser should interpret this correctly.

Cookie: a=1; b=2

Edit: as pointed out by OP, there are use cases that require multiple instances of the header. We've added it our backlog along with supporting multiple header names on incoming requests.

Use multiValueHeaders:

response.multiValueHeaders = {
  "Set-Cookie": [
    'cookie1=value1',
    'cookie1=value1'
  ]
}

or:

{
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2",...], ... },
    "body": "..."
}

https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format

As answered, to date, API Gateway will drop identical keys, only setting one of the cookies.

However, a workaround exists. You can change the casing of the string 'Set-Cookie' so the keys are not unique. For example, you could use the keys set-cookie, Set-cookie, sEt-cookie, and the headers will be preserved and 3 different cookies would be set.

Because the RFC standard makes headers case-insensitive this should work with all RFC-compliant clients.

So, you could rewrite your set-cookie headers, permuting all the possible casings of "Set-Cookie" to get around this.

This technique (hack) is employed by Zappa, a popular serverless framework written in Python.

Couple of years late, but I just required to implement something like this and this is how I was able to make it work:

...

//15 minutes
var expirationTime = new Date(new Date().getTime() + 15 * 60 * 1000);
//30 minutes
var expirationTime2 = new Date(new Date().getTime() + 30 * 60 * 1000);

var response = {};

var cookies = [];
cookies.push("testCookie={'keyX':'valx', 'keyy':'valy'}; Expires=" + expirationTime + ";");
cookies.push("testCookie2={'key1':'val1', 'key2':'val2'}; Expires=" + expirationTime2 + ";");

response.headers["Set-Cookie"] =  cookies;

...

Each array item will be processed independently, so you can add as many cookies to the array with different settings.

i.e.

cookies.push("testCookie3={'key1':'val1', 'key2':'val2'}; Expires=" + expirationTime2 + "; Max-Age=...");

cookies.push("testCookie4={'key1':'val1', 'key2':'val2'}; Expires=" + expirationTime2 + "; Domain=<domain-value>; Path=<path-value>");
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!