CloudFormation API Gateway CORS выдает доступ к XMLHttpRequest заблокирован - PullRequest
0 голосов
/ 20 июня 2019

Я пытаюсь использовать CloudFormation для создания шлюза API, но у меня есть проблема с CORS.

Ошибка на внешнем интерфейсе:

POST https://<>.execute-api.us-east-1.amazonaws.com/prod/<> 500
new:1 Access to XMLHttpRequest at '<>' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
  • APIсоздается без каких-либо проблем, и я даже дважды проверяю каждую страницу на консоли с рабочим API и не нахожу различий в их Method Request, Integration Request, Integration Response и Method Response для всехметоды (включая OPTIONS).
  • Если я удаляю ресурсы, созданные шаблоном, и создаю их вручную в том же шлюзе API, тогда мой код работает должным образом.Я проверил с помощью localhost, интерфейсного кода в S3 bucket и PostMan, поэтому я могу убедиться, что мой интерфейсный код, лямбда-функции и база данных работают правильно.
  • Я понимаю, что людиУ меня была эта проблема раньше, но я не смог найти ответ, который решает мою проблему.

  • Вот мой шаблон .

  • Обратите внимание, что "method.response.header.Access-Control-Allow-Origin": false фактически создает API с теми же настройками, что и рабочий.

  • Я также использую код из правильного ответа дляэтот вопрос .

  • Да, мой запрос OPTIONS имеет заголовок «Access-Control-Allow-Origin».

Обновление

Подписанответ Данимака ниже.Я получил это:

  • Я добавил console.log(event.requestContext); в свою функцию Lambda (написано в Node.js).
  • При проверке функции есть журналы для Lambda.
2019-06-27T20:07:03.118Z    462b93b2-9d4b-4ed3-bc04-f966fcd034cf    Debug CORS issue. Request ID:
2019-06-27T20:07:03.118Z    462b93b2-9d4b-4ed3-bc04-f966fcd034cf    undefined
  • Похоже, что нет event.requestContext.
  • Я выбрал Enable CloudWatch Logs-INFO и Enable Detailed CloudWatch Metrics с CloudWatch log role ARN*:arn:aws:iam::<ID>:role/ApiGatewayCloudWatchLogsRole (это роль, созданная AWS) внастройки API Gateway.
  • Однако для API Gateway нет журнала CloudWatch.В журнале по умолчанию CloudWatch - Log Groups: /aws/apigateway/welcome
Time (UTC +00:00)
2019-06-27
19:50:55
Cloudwatch logs enabled for API Gateway
  • Похоже, что журнал CloudWatch не получил тест из API Gateway.
  • Это то, что я получил от тестирования метода GET в моем API Gateway:
Response Body
{
  "message": "Internal server error"
}
Response Headers
{}
Logs
Execution log for request 10d90173-9919-11e9-82e1-dd33dda3b9df
Thu Jun 27 20:20:54 UTC 2019 : Starting execution for request: 10d90173-9919-11e9-82e1-dd33dda3b9df
Thu Jun 27 20:20:54 UTC 2019 : HTTP Method: GET, Resource Path: /notes
Thu Jun 27 20:20:54 UTC 2019 : Method request path: {}
Thu Jun 27 20:20:54 UTC 2019 : Method request query string: {userid=<ID>}
Thu Jun 27 20:20:54 UTC 2019 : Method request headers: {}
Thu Jun 27 20:20:54 UTC 2019 : Method request body before transformations: 
Thu Jun 27 20:20:54 UTC 2019 : Endpoint request URI: https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1:770402430649:function:test-api-gateway-2-LambdaFunction-1XDONAN3QIY9I/invocations
Thu Jun 27 20:20:54 UTC 2019 : Endpoint request headers: {x-amzn-lambda-integration-tag=... [TRUNCATED]
Thu Jun 27 20:20:54 UTC 2019 : Endpoint request body after transformations: {"resource":"/notes","path":"/notes","httpMethod":"GET","headers":null,"multiValueHeaders":null,"queryStringParameters":{"userid":"<USERID>"},"multiValueQueryStringParameters":{"userid":["<USERID>"]},"pathParameters":null,"stageVariables":null,"requestContext":{"path":"/notes","accountId":"<ID>"...,"identity":{"cognitoIdentityPoolId":null,"cognitoIdentityId":null,"apiKey":"test-invoke-api-key","principalOrgId":null,"cognitoAuthenticationType":null,"userArn":"<ARN>","apiKeyId":"test-invoke-api-key-id","userAgent":..."test [TRUNCATED]
Thu Jun 27 20:20:54 UTC 2019 : Sending request to https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1:<ID>:function:test-api-gateway-2-LambdaFunction-<STRING>/invocations
Thu Jun 27 20:20:54 UTC 2019 : Received response. Status: 403, Integration latency: 6 ms
Thu Jun 27 20:20:54 UTC 2019 : Endpoint response headers: {Date=Thu, 27 Jun 2019 20:20:54 GMT, Content-Length=130, Connection=keep-alive, x-amzn-RequestId=<ID>}
Thu Jun 27 20:20:54 UTC 2019 : Endpoint response body before transformations: <AccessDeniedException>
  <Message>Unable to determine service/operation name to be authorized</Message>
</AccessDeniedException>

Thu Jun 27 20:20:54 UTC 2019 : Lambda invocation failed with status: 403. Lambda request id: feb22917-0dea-4f91-a274-fb6b85a69121
Thu Jun 27 20:20:54 UTC 2019 : Execution failed due to configuration error: 
Thu Jun 27 20:20:54 UTC 2019 : Method completed with status: 500
  • Я также экспортировал рабочий и не работающий API-шлюз вSwagger 2. Единственная разница:
// working one:
"x-amazon-apigateway-any-method": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "noteid",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "security": [
          {
            "mobile-notes-api-authorizer": []
          }
        ]
      }
// not working one:
"x-amazon-apigateway-any-method": {
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "security": [
          {
            "test-api-gateway-2-authorizer": []
          }
        ]
      }
  • Они оба имеют:
"headers": {
              "Access-Control-Allow-Origin": {
                "type": "string"
              },
              "Access-Control-Allow-Methods": {
                "type": "string"
              },
              "Access-Control-Allow-Headers": {
                "type": "string"
              }
            }
  • Я пыталсяиспользуйте шаблон Swagger в Body моего шлюза API прежде, но не сможете решить проблему с недействительным авторизатором.

Ответы [ 2 ]

1 голос
/ 28 июня 2019

Я понял проблему. Есть 2 основные вещи:

  1. IntegrationHttpMethod для лямбды должно быть POST. Я нашел ответ здесь .
  2. В шаблоне не было AWS::Lambda::Permission, что позволяет API-шлюзу вызывать функцию Lambda. С шаблоном, когда вы используете AWS::Lambda::Permission, он покажет API в качестве триггера вашей функции Lambda. Однако, если вы вручную создадите API-шлюз и свяжете его с вашей функцией Lambda, он не покажет API-шлюз в качестве триггера, но все равно будет работать.

Так что для шаблона, который я выложил выше, мне нужно было добавить его для работы:

"LambdaPermission": {
            "Type": "AWS::Lambda::Permission",
            "Description": "Permission for API GateWay to invoke Lambda.",
            "Properties": {
                "Action": "lambda:invokeFunction",
                "FunctionName": {
                    "Fn::GetAtt": [
                        "LambdaFunction",
                        "Arn"
                    ]
                },
                "Principal": "apigateway.amazonaws.com",
                "SourceArn": {
                    "Fn::Join": [
                        "",
                        [
                            "arn:aws:execute-api:",
                            {
                                "Ref": "AWS::Region"
                            },
                            ":",
                            {
                                "Ref": "AWS::AccountId"
                            },
                            ":",
                            {
                                "Ref": "ApiGateway"
                            },
                            "/*"
                        ]
                    ]
                }
            }
        },

И отредактируйте метод ЛЮБОЙ, чтобы он выглядел так

"methodNotesANY": {
            "Type": "AWS::ApiGateway::Method",
            "DependsOn": "LambdaPermission",
            "Properties": {
                "AuthorizationType": "COGNITO_USER_POOLS",
                "AuthorizerId": {
                    "Ref": "GatewayAuthorizer"
                },
                "RestApiId": {
                    "Ref": "ApiGateway"
                },
                "ResourceId": {
                    "Ref": "resourceNotes"
                },
                "HttpMethod": "ANY",
                "Integration": {
                    "Type": "AWS_PROXY",
                    "IntegrationHttpMethod": "POST",
                    "Uri": {
                        "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations"
                    },
                    "IntegrationResponses": [{
                        "StatusCode": "200"
                    }]
                },
                "MethodResponses": [{
                    "ResponseModels": {
                        "application/json": "Empty"
                    },
                    "StatusCode": "200"
                }]
            }
        },
1 голос
/ 27 июня 2019

My Best Guess : функция POST для ANY лямбда-функции не выполняется во время выполнения и не устанавливает заголовок Access-Control-Allow-Origin на * (или ваш домен). Каждый раз, когда я получаю ошибку 5XX и CORS одновременно из запроса не OPTIONS, для меня это почти всегда так.

Рекомендуемые следующие шаги : Воспроизвести ситуацию с ошибкой после добавления журнала отладки в исходный код Lambda и включения журналов CloudWatch в API API Gateway Rest. Это можно сделать, перейдя в консоль API Gateway, щелкнув Stages> Prod> Logs/Tracing, а затем проверив эти два параметра: Enable CloudWatch Logs (уровень журнала: INFO) и Enable Detailed CloudWatch Metrics. Затем вы должны «развернуть» изменения, чтобы они вступили в силу. Сделайте это, нажав кнопку Actions в меню Resources вашего Rest API и выбрав Deploy API. Я также рекомендую записать extendedRequestId (свойство события, переданное вашему обработчику) из функции Lambda, чтобы связать запрос Lambda с запросом шлюза API: event.requestContext.extendedRequestId.

Пример журналов шлюза API:

(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Extended Request Id: b5zpBGS3IAMFvqw=
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Verifying Usage Plan for request: b66b3876-984b-11e9-95eb-dd93c7e40ca0. API Key: API Stage: 1234567890/Prod
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) API Key authorized because method 'ANY /forms' does not require API Key. Request will not contribute to throttle or quota limits
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Usage Plan check succeeded for API Key and API Stage 1234567890/Prod
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Starting execution for request: b66b3876-984b-11e9-95eb-dd93c7e40ca0
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) HTTP Method: GET, Resource Path: /forms
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Lambda execution failed with status 200 due to customer function error: select count(*) AS `count(*)` from (select `user`.* from `user` where (id IN ('some_id_123'))) as `temp` - Cannot enqueue Query after fatal error.. Lambda request id: 1ae2bb06-5347-4775-9277-caccc42f18f2
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Method completed with status: 502
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) AWS Integration Endpoint RequestId : 1ae2bb06-5347-4775-9277-caccc42f18f2
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) X-ray Tracing ID : 1-5d13cca0-3be96a1ab93a877edc70577c

Пример коррелированных журналов выполнения лямбды:

START RequestId: 1ae2bb06-5347-4775-9277-caccc42f18f2 Version: $LATEST
2019-06-26T19:50:56.391Z  1ae2bb06-5347-4775-9277-caccc42f18f2 { "extendedRequestId": "b5zpBGS3IAMFvqw=", ... }
2019-06-26T19:50:57.853Z  1ae2bb06-5347-4775-9277-caccc42f18f2 { "errorMessage": "select count(*) AS `count(*)` from (select `user`.* from `user` where (id IN ('some_id_123'))) as `temp` - Cannot enqueue Query after fatal error.", ... }
END RequestId: 1ae2bb06-5347-4775-9277-caccc42f18f2
REPORT RequestId: 1ae2bb06-5347-4775-9277-caccc42f18f2  Duration: 1660.45 ms  Billed Duration: 1700 ms Memory Size: 256 MB  Max Memory Used: 57 MB  

Другие мысли : Экспорт определения Swagger как сломанного API, так и рабочего API. Сравните и посмотрите, что отличается. Сделайте это из консоли, перейдя к Stages> Prod> Export> Export as Swagger + API Gateway Extensions. Он может не совпадать с шаблоном CloudFormation, но он довольно близок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...