Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm using API Gateway's Proxy integration to call a Lambda. The output format specification is this follow JSON format:

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

In one response I wish to set two cookies (two different auth cookies) but JSON doesn't allow having two identical keys in the headers object (OK, technically the spec does but most libraries do not).

RFC 7230 notes that Set-Cookie should be handled specially but I can't see how I can send multiple Set-Cookie values through API gateway.

Does anyone know whether this is possible?

like image 327
sihil Avatar asked Sep 29 '16 11:09

sihil


People also ask

How do I pass headers from API gateway to Lambda?

To pass custom headers from an API Gateway API to a Lambda function, use a body mapping template. The API sends the updated API request to a Lambda function to process the headers. Then, the Lambda function returns one or more header values from the original API request.

Can we call API gateway from Lambda?

You can create a web API with an HTTP endpoint for your Lambda function by using Amazon API Gateway. API Gateway provides tools for creating and documenting web APIs that route HTTP requests to Lambda functions.

Can a request have multiple cookies?

When the user agent generates an HTTP request, the user agent MUST NOT attach more than one Cookie header field. It looks like the use of multiple Cookie headers is, in fact, prohibited!

How do I return custom HTTP status codes from a Lambda function in Amazon API gateway?

The easiest way to set custom HTTP status code is to setup a Lambda Proxy Integration in API Gateway. In API Gateway > Resource > Actions Dropdown > Create Method > tick Lambda Proxy Integration and select appropriate Lambda function. For async functions just return with an object with statusCode and body .


3 Answers

Note: API gateway now has a version 2 payload that is fundamentally different from that described here (and the default for new APIs). Documentation on the differences here. See other accepted answer from Samuel for some more details.

As of November 2018 this is possible using the multiValueHeaders field in the response instead of headers (see announcement).

As an example instead of:

{
  "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"
  }
}

You can respond with:

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

Note that you can use a mix of headers and multiValueHeaders:

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

However using the same header in both will mean that the value under headers is dropped.

See the documentation for more details.

When using only the header field (as available prior to Nov 2018) I 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.

like image 83
sihil Avatar answered Oct 12 '22 17:10

sihil


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.

like image 6
sytech Avatar answered Oct 12 '22 16:10

sytech


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.

like image 3
jackko Avatar answered Oct 12 '22 18:10

jackko