如何使用代理 Lambda 从 API 网关发送多个 Set-Cookie headers
How can I send multiple Set-Cookie headers from API Gateway using a proxied Lambda
我正在使用 API Gateway 的代理集成来调用 Lambda。输出格式规范如下 JSON 格式:
{
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
在一个响应中,我希望设置两个 cookie(两个不同的身份验证 cookie)但是 JSON 不允许在 headers
object 中有两个相同的密钥(好的,技术上规范有,但大多数图书馆没有)。
RFC 7230 指出 Set-Cookie 应该特别处理,但我看不出如何通过 API 网关发送多个 Set-Cookie 值。
有谁知道这是否可行?
自 2018 年 11 月起,可以使用响应中的 multiValueHeaders
字段代替 headers
(参见 announcement)。
作为示例而不是:
{
"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"
}
}
您可以回复:
{
"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"]
}
}
请注意,您可以混合使用 headers
和 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"]
}
}
然而,在两者中使用相同的 header 将意味着 headers
下的值被丢弃。
有关详细信息,请参阅 documentation。
仅使用 header 字段(2018 年 11 月之前可用)时,我尝试发送以下手动策划的 JSON 作为回复:
{
"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"
}
}
API 网关 returns 响应 CURL 请求的 cookie 是:
< 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
如您所见,第一个 Set-Cookie
掉在地上。
正如 Mark B 指出的那样,您 can/should 通过在单个 Set-Cookie header 中设置多个 cookie name/value 对来实现此目的。浏览器应该正确解释它。
Cookie: a=1; b=2
编辑:正如 OP 所指出的,有些用例需要 header 的多个实例。我们已将其添加到我们的积压工作中,并在传入请求中支持多个 header 名称。
晚了几年,但我只需要实现这样的东西,这就是我让它工作的方式:
...
//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;
...
每个数组项将被独立处理,因此您可以使用不同的设置向数组中添加尽可能多的 cookie。
即
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>");
使用多值标头:
response.multiValueHeaders = {
"Set-Cookie": [
'cookie1=value1',
'cookie1=value1'
]
}
或:
{
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"multiValueHeaders": { "headerName": ["headerValue", "headerValue2",...], ... },
"body": "..."
}
根据回答,迄今为止,API 网关将丢弃相同的密钥,仅设置其中一个 cookie。
但是,存在解决方法。您可以更改字符串 'Set-Cookie'
的大小写,这样键就不是唯一的了。例如,您可以使用键 set-cookie
、Set-cookie
、sEt-cookie
,headers 将被保留并设置 3 个不同的 cookie。
因为 RFC 标准使 headers case-insensitive 这应该适用于所有 RFC-compliant 客户端。
因此,您可以重写 set-cookie headers、permuting all the possible casings of "Set-Cookie" 来解决这个问题。
此技术(hack)是 employed by Zappa,一个用 Python 编写的流行的无服务器框架。
我正在使用 API Gateway 的代理集成来调用 Lambda。输出格式规范如下 JSON 格式:
{
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
在一个响应中,我希望设置两个 cookie(两个不同的身份验证 cookie)但是 JSON 不允许在 headers
object 中有两个相同的密钥(好的,技术上规范有,但大多数图书馆没有)。
RFC 7230 指出 Set-Cookie 应该特别处理,但我看不出如何通过 API 网关发送多个 Set-Cookie 值。
有谁知道这是否可行?
自 2018 年 11 月起,可以使用响应中的 multiValueHeaders
字段代替 headers
(参见 announcement)。
作为示例而不是:
{
"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"
}
}
您可以回复:
{
"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"]
}
}
请注意,您可以混合使用 headers
和 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"]
}
}
然而,在两者中使用相同的 header 将意味着 headers
下的值被丢弃。
有关详细信息,请参阅 documentation。
仅使用 header 字段(2018 年 11 月之前可用)时,我尝试发送以下手动策划的 JSON 作为回复:
{
"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"
}
}
API 网关 returns 响应 CURL 请求的 cookie 是:
< 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
如您所见,第一个 Set-Cookie
掉在地上。
正如 Mark B 指出的那样,您 can/should 通过在单个 Set-Cookie header 中设置多个 cookie name/value 对来实现此目的。浏览器应该正确解释它。
Cookie: a=1; b=2
编辑:正如 OP 所指出的,有些用例需要 header 的多个实例。我们已将其添加到我们的积压工作中,并在传入请求中支持多个 header 名称。
晚了几年,但我只需要实现这样的东西,这就是我让它工作的方式:
...
//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;
...
每个数组项将被独立处理,因此您可以使用不同的设置向数组中添加尽可能多的 cookie。
即
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>");
使用多值标头:
response.multiValueHeaders = {
"Set-Cookie": [
'cookie1=value1',
'cookie1=value1'
]
}
或:
{
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"multiValueHeaders": { "headerName": ["headerValue", "headerValue2",...], ... },
"body": "..."
}
根据回答,迄今为止,API 网关将丢弃相同的密钥,仅设置其中一个 cookie。
但是,存在解决方法。您可以更改字符串 'Set-Cookie'
的大小写,这样键就不是唯一的了。例如,您可以使用键 set-cookie
、Set-cookie
、sEt-cookie
,headers 将被保留并设置 3 个不同的 cookie。
因为 RFC 标准使 headers case-insensitive 这应该适用于所有 RFC-compliant 客户端。
因此,您可以重写 set-cookie headers、permuting all the possible casings of "Set-Cookie" 来解决这个问题。
此技术(hack)是 employed by Zappa,一个用 Python 编写的流行的无服务器框架。