如何使用 AWS SAM 启用 CORS
How to enable CORS with AWS SAM
我正在尝试在我的 AWS SAM 应用程序中启用 CORS。这是我的 template.yaml
:
的片段
Globals:
Api:
Cors:
AllowMethods: "'*'"
AllowHeaders: "'*'"
AllowOrigin: "'*'"
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
Auth:
Authorizers:
MyCognitoAuthorizer: ...
getByIdFunc:
Type: AWS::Serverless::Function
Properties:
Handler: src/handler.handle
Events:
ApiEvent:
Type: Api
Properties:
Path: /{id}
Method: GET
RestApiId: !Ref MyApi
根据这个 and that https://github.com/aws/serverless-application-model/issues/373,cors 配置应该可以工作,但不幸的是 API 响应中没有设置 header,如下所示。
< HTTP/2 200
< content-type: application/json
< content-length: 770
< date: Tue, 13 Apr 2021 19:55:31 GMT
< x-amzn-requestid: ...
< x-amz-apigw-id: ...
< x-amzn-trace-id: Root=1-...-...;Sampled=0
< x-cache: Miss from cloudfront
< via: 1.1 ...cloudfront.net (CloudFront)
< x-amz-cf-pop: FRA2-C2
< x-amz-cf-id: ...==
<
* Connection #0 to host ....execute-api.eu-central-1.amazonaws.com left intact
[{"model": ..}]
我也尝试将 cors 配置添加到 API 定义 (MyApi) 本身,就像 offical docs here 中所述,但没有成功。
我可以自己在响应中添加 header,但我宁愿将其添加到模板文件中。
使用 SAM/CLoudformation 或 AWS 控制台,您可以为 OPTIONS 方法设置 CORS headers,浏览器将在调用您的实际 API 方法(GE/POST 等)之前调用该方法.从邮递员或任何其他服务只会调用您的端点。
当我们使用 lambda proxy with API Gateway 时,我们需要在来自 lambda 的响应 object 中设置 CORS headers。
To enable CORS for the Lambda proxy integration, you must add Access-Control-Allow-Origin:domain-name to the output headers. domain-name can be * for any domain name.
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*", // Allow from anywhere
"Access-Control-Allow-Methods": "GET" // Allow only GET request
},
body: JSON.stringify(response)
}
使用您的脚本,CORS 在 API 网关上启用,但 SAM 始终创建从 API 网关到 Lambda 的代理集成,这意味着 API 网关无法添加任何集成response ,它将传递将从 LAMBDA 收到的响应。这就是为什么您需要在 lambda 中处理 CORS header 而不是依赖于 API 网关。下面是来自 LAMBDA 的 return 的示例代码以及响应。
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with",
"Access-Control-Allow-Origin": "*", // Allow from anywhere
"Access-Control-Allow-Methods": "OPTIONS,POST,GET,PUT,DELETE,PATCH" // Allow only GET request
},
body: JSON.stringify(response)
}
晚会迟到了,但对于来自 Google 的其他人:将此添加到 Auth 部分,这将不允许 Authorizer 处理 CORS HTTP headers
Api:
Auth:
AddDefaultAuthorizerToCorsPreflight: false
为我解决的是将以下内容添加到我的 template.yaml:
Globals:
Api:
Cors:
AllowMethods: "'GET,POST,OPTIONS'"
AllowHeaders: "'content-type'"
AllowOrigin: "'*'"
AllowCredentials: true
就像 nirvana124 和 Nitesh 所说的那样,您还需要 return 这些 headers 以及每个端点的响应:
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*", // Allow from anywhere
"Access-Control-Allow-Methods": "GET" // Allow only GET request
},
body: JSON.stringify(response)
}
对于使用 API 网关版本 2 的任何人(HttpApi), it doesn't have support for 'AddDefaultAuthorizerToCorsPreflight', at least not specified in their documentation。
相反(根据 AWS guidelines),我们需要在 lambda 函数中为 OPTIONS /{proxy+} 添加路由并关闭该路由的身份验证。
MyHttpApi:
Type: AWS::Serverless::HttpApi
Properties:
Auth:
DefaultAuthorizer: OAuth2
Authorizers:
OAuth2:
JwtConfiguration:
issuer: "..."
audience:
- ...
IdentitySource: "$request.header.Authorization"
CorsConfiguration:
AllowOrigins:
- "*"
AllowMethods:
- GET
- POST
- OPTIONS
AllowHeaders:
- Content-Type
- Accept
- Access-Control-Allow-Headers
- Access-Control-Request-Method
- Access-Control-Request-Headers
- Authorization
MyLambdaFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Events:
CorsPreflightEvent:
Type: HttpApi
Properties:
Path: /{proxy+}
Method: OPTIONS
Auth:
Authorizer: NONE
ApiId: !Ref MyHttpApi
我正在尝试在我的 AWS SAM 应用程序中启用 CORS。这是我的 template.yaml
:
Globals:
Api:
Cors:
AllowMethods: "'*'"
AllowHeaders: "'*'"
AllowOrigin: "'*'"
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
Auth:
Authorizers:
MyCognitoAuthorizer: ...
getByIdFunc:
Type: AWS::Serverless::Function
Properties:
Handler: src/handler.handle
Events:
ApiEvent:
Type: Api
Properties:
Path: /{id}
Method: GET
RestApiId: !Ref MyApi
根据这个
< HTTP/2 200
< content-type: application/json
< content-length: 770
< date: Tue, 13 Apr 2021 19:55:31 GMT
< x-amzn-requestid: ...
< x-amz-apigw-id: ...
< x-amzn-trace-id: Root=1-...-...;Sampled=0
< x-cache: Miss from cloudfront
< via: 1.1 ...cloudfront.net (CloudFront)
< x-amz-cf-pop: FRA2-C2
< x-amz-cf-id: ...==
<
* Connection #0 to host ....execute-api.eu-central-1.amazonaws.com left intact
[{"model": ..}]
我也尝试将 cors 配置添加到 API 定义 (MyApi) 本身,就像 offical docs here 中所述,但没有成功。
我可以自己在响应中添加 header,但我宁愿将其添加到模板文件中。
使用 SAM/CLoudformation 或 AWS 控制台,您可以为 OPTIONS 方法设置 CORS headers,浏览器将在调用您的实际 API 方法(GE/POST 等)之前调用该方法.从邮递员或任何其他服务只会调用您的端点。
当我们使用 lambda proxy with API Gateway 时,我们需要在来自 lambda 的响应 object 中设置 CORS headers。
To enable CORS for the Lambda proxy integration, you must add Access-Control-Allow-Origin:domain-name to the output headers. domain-name can be * for any domain name.
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*", // Allow from anywhere
"Access-Control-Allow-Methods": "GET" // Allow only GET request
},
body: JSON.stringify(response)
}
使用您的脚本,CORS 在 API 网关上启用,但 SAM 始终创建从 API 网关到 Lambda 的代理集成,这意味着 API 网关无法添加任何集成response ,它将传递将从 LAMBDA 收到的响应。这就是为什么您需要在 lambda 中处理 CORS header 而不是依赖于 API 网关。下面是来自 LAMBDA 的 return 的示例代码以及响应。
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with",
"Access-Control-Allow-Origin": "*", // Allow from anywhere
"Access-Control-Allow-Methods": "OPTIONS,POST,GET,PUT,DELETE,PATCH" // Allow only GET request
},
body: JSON.stringify(response)
}
晚会迟到了,但对于来自 Google 的其他人:将此添加到 Auth 部分,这将不允许 Authorizer 处理 CORS HTTP headers
Api:
Auth:
AddDefaultAuthorizerToCorsPreflight: false
为我解决的是将以下内容添加到我的 template.yaml:
Globals:
Api:
Cors:
AllowMethods: "'GET,POST,OPTIONS'"
AllowHeaders: "'content-type'"
AllowOrigin: "'*'"
AllowCredentials: true
就像 nirvana124 和 Nitesh 所说的那样,您还需要 return 这些 headers 以及每个端点的响应:
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*", // Allow from anywhere
"Access-Control-Allow-Methods": "GET" // Allow only GET request
},
body: JSON.stringify(response)
}
对于使用 API 网关版本 2 的任何人(HttpApi), it doesn't have support for 'AddDefaultAuthorizerToCorsPreflight', at least not specified in their documentation。
相反(根据 AWS guidelines),我们需要在 lambda 函数中为 OPTIONS /{proxy+} 添加路由并关闭该路由的身份验证。
MyHttpApi:
Type: AWS::Serverless::HttpApi
Properties:
Auth:
DefaultAuthorizer: OAuth2
Authorizers:
OAuth2:
JwtConfiguration:
issuer: "..."
audience:
- ...
IdentitySource: "$request.header.Authorization"
CorsConfiguration:
AllowOrigins:
- "*"
AllowMethods:
- GET
- POST
- OPTIONS
AllowHeaders:
- Content-Type
- Accept
- Access-Control-Allow-Headers
- Access-Control-Request-Method
- Access-Control-Request-Headers
- Authorization
MyLambdaFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Events:
CorsPreflightEvent:
Type: HttpApi
Properties:
Path: /{proxy+}
Method: OPTIONS
Auth:
Authorizer: NONE
ApiId: !Ref MyHttpApi