如何在 Serverless 中允许自定义 headers 的 CORS?
How to allow CORS for custom headers in Serverless?
这里的核心问题是:“如何在使用无服务器框架处理的 CORS GET 请求中允许自定义 header?”。如果您知道该问题的答案,请通过 Go,收取 200 美元并请回答该问题。如果不是直接回答的问题,请查看详细信息:
我正在 AWS Lambda 上使用无服务器框架编写应用程序(API 通过 AWS API 网关管理。坦率地说,我不完全确定这意味着什么或有什么好处提供给我,但这就是 Serverless 自动为我配置的)。我正在尝试创建一个需要启用 CORS 的开放 API。我正在使用 Lambda 代理集成。我遵循了发现的做法 here。他们给我带来了部分成功。如果我不包含我的自定义 headers,我的应用程序当前启用了 CORS。但是,它仍然不适用于自定义 headers。
当我向 API 发送以下请求时:
var data = null;
var xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://api.spongebobify.com/");
xhr.setRequestHeader("text", "hey");
xhr.send(data);
...我收到此错误:
Failed to load https://api.spongebobify.com/: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://forum.serverless.com' is therefore not allowed access.
如果我使用 Chrome 开发工具检查 "response headers",则确认此错误消息:响应 headers 中没有 Access-Control-Allow-Origin。
但是,如果我发送相同的请求并注释掉 setRequestHeader()
,它会完美运行(是的,我知道它 returns 一个 403 错误:这是故意的行为)。
这是我认为正在发生的事情。我的服务有两个潜在的 CORS 问题:域相关(请求不是来自原始域)和自定义 header 相关(CORS 规范 header 而不是 safe-listed,更多 here).不知何故,无服务器框架在第二个问题上出错,导致它甚至没有达到发出适当的 headers 以允许所有(“*”)域的地步。
这是我的 serverless.yml 配置文件:
# serverless.yml
service: spongebobify
provider:
name: aws
runtime: nodejs6.10
stage: dev
region: us-east-1
functions:
app:
handler: handler.endpoint
events:
- http: GET /
cors:
origin: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- Startlower
- Text
- Access-Control-Allow-Headers
- Access-Control-Allow-Origin
allowCredentials: false
这是我正在尝试的功能 运行。您可以看到我 多次 尝试正确设置 header。我有 60% 的信心现在会通过 serverless.yml
文件进行修复。
"use strict";
const spongebobify = require("spongebobify");
module.exports.endpoint = (event, context, callback) => {
let startLower = event.headers.startlower === "false" ? false : true;
try {
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*", // Required for CORS support to work
"Access-Control-Allow-Headers": "content-type,origin,text,startlower",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"content-type": "text/plain",
"Access-Control-Allow-Credentials": true // Required for cookies, authorization headers with HTTPS
},
body: spongebobify(event.headers.text, startLower)
};
callback(null, response);
} catch (err) {
console.log(err);
const response = {
statusCode: 403,
headers: {
"Access-Control-Allow-Origin": "*", // Required for CORS support to work
"Access-Control-Allow-Headers": "content-type,origin,X-text,startlower",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"content-type": "text/plain",
"Access-Control-Allow-Credentials": true // Required for cookies, authorization headers with HTTPS
},
body: "Malformed request."
};
callback(null, response);
}
};
您可以在以下站点的开发控制台中复制我的 运行 上述 XMLHttpRequest
问题:
- api.spongebobify.com 启用或禁用自定义 header。它在这两种情况下都能完美运行(因为它不会跨源)。
- 任何没有正确配置 CSP 并启用自定义 header 的站点。 OPTIONS请求会失败,会准确的报告没有Access-Control-Allow-Originheader
- 没有正确配置 CSP 的任何站点 没有 自定义 header 启用。 OPTIONS 请求将通过(你会知道,因为 Chrome 永远不会告诉你它发生了)并且你会在响应 header 中看到 Access-Control-Allow-Origin。您还将看到响应 "Malformed request.".
我认为问题在于您将 HTTP 事件的短格式 (- http: GET /
) 与添加了额外选项的长格式混合在一起。
试试这个:
functions:
app:
handler: handler.endpoint
events:
- http:
method: GET
path: /
cors:
origin: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- Startlower
- Text
- Access-Control-Allow-Headers
- Access-Control-Allow-Origin
allowCredentials: false
主要变化是:
1) 在http
事件对象上添加method
和path
键,以及
2) 将 cors
对象缩进另一个层次。它以前在 http
事件的顶层。
如果有帮助请告诉我:)
问题是 Prefilght request 是如何工作的,根据我的经验,此过程仅在 GET 方法上配置自定义 header 时效果不佳,因此,只需添加 POST方法也解决了 CORS 问题:
events:
- http:
path: admin/{type}
method: get
cors:
origin: '*'
headers:
- token
allowCredentials: false
- http:
path: admin/{type}
method: post
cors:
origin: '*'
headers:
- token
allowCredentials: false
这 CORS and API Gateway survival guide and Fixing Common Problems with CORS and JavaScript 帮助我理解问题和解决方案。
最后这是我的 JS 代码
fetch(api_url,{
method : 'GET',
mode: 'cors',
headers: {
token: 'XXXX-XXXX'
}
}).then((resp) => resp.json())
这里的核心问题是:“如何在使用无服务器框架处理的 CORS GET 请求中允许自定义 header?”。如果您知道该问题的答案,请通过 Go,收取 200 美元并请回答该问题。如果不是直接回答的问题,请查看详细信息:
我正在 AWS Lambda 上使用无服务器框架编写应用程序(API 通过 AWS API 网关管理。坦率地说,我不完全确定这意味着什么或有什么好处提供给我,但这就是 Serverless 自动为我配置的)。我正在尝试创建一个需要启用 CORS 的开放 API。我正在使用 Lambda 代理集成。我遵循了发现的做法 here。他们给我带来了部分成功。如果我不包含我的自定义 headers,我的应用程序当前启用了 CORS。但是,它仍然不适用于自定义 headers。
当我向 API 发送以下请求时:
var data = null;
var xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://api.spongebobify.com/");
xhr.setRequestHeader("text", "hey");
xhr.send(data);
...我收到此错误:
Failed to load https://api.spongebobify.com/: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://forum.serverless.com' is therefore not allowed access.
如果我使用 Chrome 开发工具检查 "response headers",则确认此错误消息:响应 headers 中没有 Access-Control-Allow-Origin。
但是,如果我发送相同的请求并注释掉 setRequestHeader()
,它会完美运行(是的,我知道它 returns 一个 403 错误:这是故意的行为)。
这是我认为正在发生的事情。我的服务有两个潜在的 CORS 问题:域相关(请求不是来自原始域)和自定义 header 相关(CORS 规范 header 而不是 safe-listed,更多 here).不知何故,无服务器框架在第二个问题上出错,导致它甚至没有达到发出适当的 headers 以允许所有(“*”)域的地步。
这是我的 serverless.yml 配置文件:
# serverless.yml
service: spongebobify
provider:
name: aws
runtime: nodejs6.10
stage: dev
region: us-east-1
functions:
app:
handler: handler.endpoint
events:
- http: GET /
cors:
origin: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- Startlower
- Text
- Access-Control-Allow-Headers
- Access-Control-Allow-Origin
allowCredentials: false
这是我正在尝试的功能 运行。您可以看到我 多次 尝试正确设置 header。我有 60% 的信心现在会通过 serverless.yml
文件进行修复。
"use strict";
const spongebobify = require("spongebobify");
module.exports.endpoint = (event, context, callback) => {
let startLower = event.headers.startlower === "false" ? false : true;
try {
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*", // Required for CORS support to work
"Access-Control-Allow-Headers": "content-type,origin,text,startlower",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"content-type": "text/plain",
"Access-Control-Allow-Credentials": true // Required for cookies, authorization headers with HTTPS
},
body: spongebobify(event.headers.text, startLower)
};
callback(null, response);
} catch (err) {
console.log(err);
const response = {
statusCode: 403,
headers: {
"Access-Control-Allow-Origin": "*", // Required for CORS support to work
"Access-Control-Allow-Headers": "content-type,origin,X-text,startlower",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"content-type": "text/plain",
"Access-Control-Allow-Credentials": true // Required for cookies, authorization headers with HTTPS
},
body: "Malformed request."
};
callback(null, response);
}
};
您可以在以下站点的开发控制台中复制我的 运行 上述 XMLHttpRequest
问题:
- api.spongebobify.com 启用或禁用自定义 header。它在这两种情况下都能完美运行(因为它不会跨源)。
- 任何没有正确配置 CSP 并启用自定义 header 的站点。 OPTIONS请求会失败,会准确的报告没有Access-Control-Allow-Originheader
- 没有正确配置 CSP 的任何站点 没有 自定义 header 启用。 OPTIONS 请求将通过(你会知道,因为 Chrome 永远不会告诉你它发生了)并且你会在响应 header 中看到 Access-Control-Allow-Origin。您还将看到响应 "Malformed request.".
我认为问题在于您将 HTTP 事件的短格式 (- http: GET /
) 与添加了额外选项的长格式混合在一起。
试试这个:
functions:
app:
handler: handler.endpoint
events:
- http:
method: GET
path: /
cors:
origin: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- Startlower
- Text
- Access-Control-Allow-Headers
- Access-Control-Allow-Origin
allowCredentials: false
主要变化是:
1) 在http
事件对象上添加method
和path
键,以及
2) 将 cors
对象缩进另一个层次。它以前在 http
事件的顶层。
如果有帮助请告诉我:)
问题是 Prefilght request 是如何工作的,根据我的经验,此过程仅在 GET 方法上配置自定义 header 时效果不佳,因此,只需添加 POST方法也解决了 CORS 问题:
events:
- http:
path: admin/{type}
method: get
cors:
origin: '*'
headers:
- token
allowCredentials: false
- http:
path: admin/{type}
method: post
cors:
origin: '*'
headers:
- token
allowCredentials: false
这 CORS and API Gateway survival guide and Fixing Common Problems with CORS and JavaScript 帮助我理解问题和解决方案。
最后这是我的 JS 代码
fetch(api_url,{
method : 'GET',
mode: 'cors',
headers: {
token: 'XXXX-XXXX'
}
}).then((resp) => resp.json())