Cloudfront + S3 上的静态网站 + API 网关 + Lambda + DynamoDb 设置的 AWS CDK CORS 错误
AWS CDK CORS error with Cloudfront + Static Website on S3 + API Gateway + Lambda + DynamoDb setup
我正在使用 AWS CDK (v1.87.1 (build 9eeaa93)) 将我的基础设施定义为代码。我使用 C# 来定义我的 CDK 堆栈。
我将数据存储在 DynamoDb 中,并且由 Lambda 函数支持的 API 网关 read/write 连接到 DynamoDb。这是我的后端。
我的前端是一个简单的静态网站 (HTML + JS),托管在通过 CloudFront 分发的 AWS S3 上。
我的 API 在我使用 curl 或在 AWS 控制台中独立测试时工作正常。但是,当我在静态网站页面中使用 fetch() 浏览器 API 调用 API 时,出现以下错误(在浏览器中):
Access to fetch at
'https://xxxxxxxx.execute-api.ap-south-1.amazonaws.com/prod/Account'
from origin 'https://abcdefg.cloudfront.net' has been blocked by
CORS policy: No 'Access-Control-Allow-Origin' header is present on the
requested resource. If an opaque response serves your needs, set the
request's mode to 'no-cors' to fetch the resource with CORS disabled.
我的CorsOptions定义如下:
var defaultCorsPreflightOptions = new CorsOptions() {
AllowOrigins = Cors.ALL_ORIGINS,
AllowMethods = Cors.ALL_METHODS,
AllowHeaders = new [] {"*"},
AllowCredentials = true,
MaxAge = Duration.Days(0)
};
我的API如下:
var api = new RestApi(this, "my-api", new RestApiProps {
RestApiName = "My Service",
Description = "This is the service API"
});
我的资源创建为预检添加了 CorsOption(在上面的错误消息中 'Account' 将是添加到根的资源):
var resourceType = api.Root.AddResource(ent);
resourceType.AddCorsPreflight(defaultCorsPreflightOptions);
我的 lambda 处理程序也有
if(method == "OPTIONS") {
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,PUT,GET,DELETE"
}
};
return response;
} else if(method === "POST") {
// ... omitted
}
调用REST的JS客户端代码API是:
const response = await fetch(`${api_url}/${entity}`,{
method: 'POST',
mode: 'cors',
body: item,
headers: {
'Content-Type': 'application/json'
}
});
附加到 CloudFront 分配的行为:
// The cloudfront distribution for the website
var behavior = new Behavior() {
IsDefaultBehavior = true,
AllowedMethods = CloudFrontAllowedMethods.ALL,
MaxTtl = Duration.Seconds(0),
MinTtl = Duration.Seconds(0),
DefaultTtl = Duration.Seconds(0),
Compress = false,
ForwardedValues = new CfnDistribution.ForwardedValuesProperty() {
QueryString = true,
Headers = new [] {"Authorization", "Access-Control-Allow-Origin"}
}
};
我的 CloudFront 分布如下:
var distribution = new CloudFrontWebDistribution(this, "StaticWebsiteDistribution", new CloudFrontWebDistributionProps() {
OriginConfigs = new [] {
new SourceConfiguration() {
S3OriginSource = new S3OriginConfig() {
S3BucketSource = bucket
},
Behaviors = new [] {
behavior
}
}
}
});
我的 S3 Bucket 部署代码是:
// The S3 bucket deployment for the website
var deployment = new BucketDeployment(this, "WebsiteDeployment", new BucketDeploymentProps(){
Sources = new [] {Source.Asset("./website")},
DestinationBucket = bucket,
Distribution = distribution
});
我已尝试查看 AWS CDK 文档。我也尝试在 API 级别添加默认的 CORS 选项,但没有成功。我错过了什么?请帮忙
我明白了。错误出现在 POST / GET / DELETE / PUT 方法的 Lambda 处理程序中。我需要 return headers(下面给出的示例):
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*", // I was missing this
"Content-Type": "application/json" // and this
},
body: JSON.stringify({"id":`${id}`}) // and this was a string earlier
};
我在客户端处理 fetch() 响应时遇到另一个错误。我使用的是 response.json() 而它应该是 response.text() (因为我之前在响应 body 中发送了文本)。
我被 curl 响应(在我的测试中)误导了,它只是纯文本,而处理 fetch() 响应时存在 JSON 解析问题。
要点:检查您的 Lambda 处理程序响应。
我正在使用 AWS CDK (v1.87.1 (build 9eeaa93)) 将我的基础设施定义为代码。我使用 C# 来定义我的 CDK 堆栈。
我将数据存储在 DynamoDb 中,并且由 Lambda 函数支持的 API 网关 read/write 连接到 DynamoDb。这是我的后端。
我的前端是一个简单的静态网站 (HTML + JS),托管在通过 CloudFront 分发的 AWS S3 上。
我的 API 在我使用 curl 或在 AWS 控制台中独立测试时工作正常。但是,当我在静态网站页面中使用 fetch() 浏览器 API 调用 API 时,出现以下错误(在浏览器中):
Access to fetch at 'https://xxxxxxxx.execute-api.ap-south-1.amazonaws.com/prod/Account' from origin 'https://abcdefg.cloudfront.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
我的CorsOptions定义如下:
var defaultCorsPreflightOptions = new CorsOptions() {
AllowOrigins = Cors.ALL_ORIGINS,
AllowMethods = Cors.ALL_METHODS,
AllowHeaders = new [] {"*"},
AllowCredentials = true,
MaxAge = Duration.Days(0)
};
我的API如下:
var api = new RestApi(this, "my-api", new RestApiProps {
RestApiName = "My Service",
Description = "This is the service API"
});
我的资源创建为预检添加了 CorsOption(在上面的错误消息中 'Account' 将是添加到根的资源):
var resourceType = api.Root.AddResource(ent);
resourceType.AddCorsPreflight(defaultCorsPreflightOptions);
我的 lambda 处理程序也有
if(method == "OPTIONS") {
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,PUT,GET,DELETE"
}
};
return response;
} else if(method === "POST") {
// ... omitted
}
调用REST的JS客户端代码API是:
const response = await fetch(`${api_url}/${entity}`,{
method: 'POST',
mode: 'cors',
body: item,
headers: {
'Content-Type': 'application/json'
}
});
附加到 CloudFront 分配的行为:
// The cloudfront distribution for the website
var behavior = new Behavior() {
IsDefaultBehavior = true,
AllowedMethods = CloudFrontAllowedMethods.ALL,
MaxTtl = Duration.Seconds(0),
MinTtl = Duration.Seconds(0),
DefaultTtl = Duration.Seconds(0),
Compress = false,
ForwardedValues = new CfnDistribution.ForwardedValuesProperty() {
QueryString = true,
Headers = new [] {"Authorization", "Access-Control-Allow-Origin"}
}
};
我的 CloudFront 分布如下:
var distribution = new CloudFrontWebDistribution(this, "StaticWebsiteDistribution", new CloudFrontWebDistributionProps() {
OriginConfigs = new [] {
new SourceConfiguration() {
S3OriginSource = new S3OriginConfig() {
S3BucketSource = bucket
},
Behaviors = new [] {
behavior
}
}
}
});
我的 S3 Bucket 部署代码是:
// The S3 bucket deployment for the website
var deployment = new BucketDeployment(this, "WebsiteDeployment", new BucketDeploymentProps(){
Sources = new [] {Source.Asset("./website")},
DestinationBucket = bucket,
Distribution = distribution
});
我已尝试查看 AWS CDK 文档。我也尝试在 API 级别添加默认的 CORS 选项,但没有成功。我错过了什么?请帮忙
我明白了。错误出现在 POST / GET / DELETE / PUT 方法的 Lambda 处理程序中。我需要 return headers(下面给出的示例):
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*", // I was missing this
"Content-Type": "application/json" // and this
},
body: JSON.stringify({"id":`${id}`}) // and this was a string earlier
};
我在客户端处理 fetch() 响应时遇到另一个错误。我使用的是 response.json() 而它应该是 response.text() (因为我之前在响应 body 中发送了文本)。
我被 curl 响应(在我的测试中)误导了,它只是纯文本,而处理 fetch() 响应时存在 JSON 解析问题。
要点:检查您的 Lambda 处理程序响应。