Включение CORS при локальном запуске AWS SAM CLI

Всякий раз, когда я пытаюсь получить доступ к бессерверной лямбда-функции через POST через браузер, я получаю сообщение об ошибке

Ответ на предполетный запрос не проходит проверку контроля доступа: в запрошенном ресурсе присутствует заголовок No> 'Access-Control-Allow-Origin'.

Когда это /GET, он работает нормально, я читал, это потому, что он не отправляет предварительный запрос к полету. Когда я меняю его на POST, он терпит неудачу.

Команда, которую я выполняю:

sam local start-api

И мой template.yaml:

...

Resources:
    PropertiesFunction:
        Type: AWS::Serverless::Function
        Properties:
            CodeUri: target/service-0.0.1-SNAPSHOT.jar
            Handler: com.aws.PropertiesHandler::handleRequest
            Runtime: java8
            Events:
                PropertiesApi:
                    Type: Api
                    Properties:
                        Path: /properties
                        Method: post

...

Как я могу включить CORS на этих конечных точках?


person Eduardo Dennis    schedule 15.11.2018    source источник


Ответы (3)


У меня была такая же ошибка, и я уже исправил ее за 3 шага. (AWS Lambda в Java8, SAM CLI v0.37.0)

  1. Добавьте параметры для заголовка:
    Map<String, String> headers = new HashMap<>();
    headers.put("Content-Type", "application/json");
    headers.put("X-Custom-Header", "application/json");
    headers.put("Access-Control-Allow-Origin", "*");
    headers.put("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
    headers.put("Access-Control-Allow-Headers", "X-Requested-With,content-type");
  1. Добавить вариант Cors в template.yaml
    Globals:
      Function:
        Timeout: 20
      Api:
        Cors:
          AllowMethods: "'GET,POST,OPTIONS'"
          AllowHeaders: "'content-type'"
          AllowOrigin: "'*'"
          AllowCredentials: "'*'"
  1. Обновить функцию ресурса свойств в template.yaml
          Events:
            HelloWorld:
              Type: Api 
              Properties:
                # Path: /hello
                # Method: get
                Path: "/{proxy+}"
                Method: ANY
person ngoctrambui    schedule 17.01.2020
comment
ты спас мне день. Мой YAML был почти таким же, но в lamda мне не хватало заголовка, поэтому после добавления заголовка он работает для меня. - person Nirmal; 02.05.2020

Вы должны иметь возможность обойти это при локальном тестировании, явно добавив следующие заголовки в свой ответ в функции обработчика:

    "Access-Control-Allow-Origin": "*"

Вы можете использовать переменную среды, которая добавляет заголовки, только если вы работаете локально.

Вот простой пример Python из имеющейся у меня функции-обработчика:

   if not all(field in values for field in required_fields):
    response = {
        'statusCode': 400,
        'body': json.dumps(
            {
                'message': 'Required data missing from request body'
            }
        )        
    }
    # explicitly add CORs headers for local testing
    response['headers'] = {"Access-Control-Allow-Origin": "*"}
    return response

Это подходит только для локального тестирования, когда вы развертываете на шлюзе API. CORs обрабатываются конфигурацией на шлюзе API.

Это решение работало для меня, пока я также не добавил авторизацию в API с пулом пользователей Cognito, с которым я сейчас пытаюсь работать.

Вот аналогичное сообщение по этой проблеме: Как включить CORS для ресурса AWS API Gateway

Вот ссылка на него в официальной документации AWS.

person user10682499    schedule 20.11.2018
comment
Вам когда-нибудь повезло после добавления аутентификации - к сожалению, я нахожусь в том же положении. - person Chris Owens; 04.02.2019
comment
Я также собираюсь добавить аутентификацию и получаю ошибки CORS. Вам когда-нибудь везло? - person K. Peters; 04.03.2020

Во-первых, вам нужно будет добавить следующий раздел в template.yml, чтобы включить cors в шлюзе API:

Globals:
  Api:
    Cors:
      AllowMethods: "'GET,POST,OPTIONS'"
      AllowHeaders: "'content-type'"
      AllowOrigin: "'*'"
      AllowCredentials: "'*'"

Затем в вашем ответе лямбда-функции


        MultivaluedMap<String, Object> headers = responseContext.getHeaders();

        headers.add("Access-Control-Allow-Origin", "*");
        headers.add("Access-Control-Allow-Headers", requestContext.getHeaderString("Access-Control-Request-Headers"));
        headers.add("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,HEAD,OPTIONS");
person me2resh    schedule 20.01.2020