对 API 网关的 CORS 请求在浏览器中不工作
CORS Request to API Gateway not working in browser
好吧,我准备好看起来很傻了。我敢打赌这是一个简单的问题,我只是没有看到我做错了什么。
我最近部署了一个设置 API 网关的 SAM 应用程序。相关配置如下
# SAM Template Headers + Some Parameters; nothing relating to this.
Resources:
# The Api Gateway necessary for the authorizers.
ApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: !Ref Stage
Cors: "'*'"
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
Authorizers:
MyCognitoAuthorizer:
UserPoolArn: !ImportValue UserPoolArn
# some other functions, but one function should do it.
# Verified that all functions are referencing the custom ApiGateway resource.
PutTodosFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/add.putItemHandler
Description: Adds a todo.
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref TodosTable
Environment:
Variables:
TODOS_TABLE: !Ref TodosTable
NODE_ENV: !If [isProd, 'production', 'development']
REGION: !Ref AWS::Region
Events:
PutTodo:
Type: Api
Properties:
RestApiId: !Ref ApiGateway
Path: /
Method: PUT
这就是我觉得自己快要疯了的地方。如您所见,我的 API 网关使用 AWS Cognito 进行授权,因此我使用 Insomnia 桌面应用程序测试流程。
只要我记得提供必要的令牌,所有请求都可以正常工作。在我开始尝试通过浏览器发出相同的请求之前,我认为自己是黄金。
现在我在尝试发出请求时遇到如下错误:
Access to fetch at 'https://xpquux202j.execute-api.us-west-2.amazonaws.com/alpha/' from origin 'https://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.
调用它的代码经过了一些迭代,但最近的是:
const headers = new Headers();
headers.append('Authorization', 'Bearer <JWT Token Goes Here>');
fetch(API_URL, {
headers,
method: 'options', // have tried put/get as well. Neither goes through.
mode: 'cors' // tried cors and no-cors
})
.then(console.log)
.catch(console.log);
最初由于错误我认为 API 网关端配置错误,但向端点发出 OPTIONS
请求(Insomnia)给出:
并在
中进行测试
TYIA 寻求帮助;我确定这是我遗漏的一些小东西我已经厌倦了试图解决这个问题。
好吧,原来的问题已经解决了……有点。
Tl;Dr 您可以在 AWS::Serverless::Api
调用的 Auth
键中使用 AddDefaultAuthorizerToCorsPreflight
选项,例如
ApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: !Ref Stage
Cors: "'*'"
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
AddDefaultAuthorizerToCorsPreflight: false
Authorizers:
MyCognitoAuthorizer:
UserPoolArn: !ImportValue UserPoolArn
然而,这会产生另一个与 CORS 相关的问题。当您使用此设置创建 API 网关时,OPTIONS 请求在其响应中没有 Access-Control-Allow-Headers
header。我仍在等待 AWS Sam 团队关于 Github 问题的回复:https://github.com/aws/serverless-application-model/issues/2136#issuecomment-915708356
到目前为止,解决方法是简单地从控制台启用 CORS,然后控制台将获得必要的授权 header。显然不是很好,但也不是特别破坏游戏。
更新
经过一番挖掘,我发现进行这些更改后 API 网关可以毫无错误地进行部署。 CORS 部分需要在 ApiGateway 资源中看起来像这样。
ApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: !Ref Stage
Cors:
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
AllowMethods: "'*'"
AllowOrigin: "'*'"
# same Auth: definition as above.
好吧,我准备好看起来很傻了。我敢打赌这是一个简单的问题,我只是没有看到我做错了什么。
我最近部署了一个设置 API 网关的 SAM 应用程序。相关配置如下
# SAM Template Headers + Some Parameters; nothing relating to this.
Resources:
# The Api Gateway necessary for the authorizers.
ApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: !Ref Stage
Cors: "'*'"
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
Authorizers:
MyCognitoAuthorizer:
UserPoolArn: !ImportValue UserPoolArn
# some other functions, but one function should do it.
# Verified that all functions are referencing the custom ApiGateway resource.
PutTodosFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/add.putItemHandler
Description: Adds a todo.
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref TodosTable
Environment:
Variables:
TODOS_TABLE: !Ref TodosTable
NODE_ENV: !If [isProd, 'production', 'development']
REGION: !Ref AWS::Region
Events:
PutTodo:
Type: Api
Properties:
RestApiId: !Ref ApiGateway
Path: /
Method: PUT
这就是我觉得自己快要疯了的地方。如您所见,我的 API 网关使用 AWS Cognito 进行授权,因此我使用 Insomnia 桌面应用程序测试流程。
只要我记得提供必要的令牌,所有请求都可以正常工作。在我开始尝试通过浏览器发出相同的请求之前,我认为自己是黄金。
现在我在尝试发出请求时遇到如下错误:
Access to fetch at 'https://xpquux202j.execute-api.us-west-2.amazonaws.com/alpha/' from origin 'https://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.
调用它的代码经过了一些迭代,但最近的是:
const headers = new Headers();
headers.append('Authorization', 'Bearer <JWT Token Goes Here>');
fetch(API_URL, {
headers,
method: 'options', // have tried put/get as well. Neither goes through.
mode: 'cors' // tried cors and no-cors
})
.then(console.log)
.catch(console.log);
最初由于错误我认为 API 网关端配置错误,但向端点发出 OPTIONS
请求(Insomnia)给出:
并在
TYIA 寻求帮助;我确定这是我遗漏的一些小东西我已经厌倦了试图解决这个问题。
好吧,原来的问题已经解决了……有点。
Tl;Dr 您可以在 AWS::Serverless::Api
调用的 Auth
键中使用 AddDefaultAuthorizerToCorsPreflight
选项,例如
ApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: !Ref Stage
Cors: "'*'"
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
AddDefaultAuthorizerToCorsPreflight: false
Authorizers:
MyCognitoAuthorizer:
UserPoolArn: !ImportValue UserPoolArn
然而,这会产生另一个与 CORS 相关的问题。当您使用此设置创建 API 网关时,OPTIONS 请求在其响应中没有 Access-Control-Allow-Headers
header。我仍在等待 AWS Sam 团队关于 Github 问题的回复:https://github.com/aws/serverless-application-model/issues/2136#issuecomment-915708356
到目前为止,解决方法是简单地从控制台启用 CORS,然后控制台将获得必要的授权 header。显然不是很好,但也不是特别破坏游戏。
更新
经过一番挖掘,我发现进行这些更改后 API 网关可以毫无错误地进行部署。 CORS 部分需要在 ApiGateway 资源中看起来像这样。
ApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: !Ref Stage
Cors:
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
AllowMethods: "'*'"
AllowOrigin: "'*'"
# same Auth: definition as above.