API Gateway CORS: нет заголовка Access-Control-Allow-Origin


103

Хотя CORS был настроен через API Gateway и установлен Access-Control-Allow-Originзаголовок, я все равно получаю следующую ошибку при попытке вызвать API из AJAX в Chrome:

XMLHttpRequest не может загрузить http://XXXXX.execute-api.us-west-2.amazonaws.com/beta/YYYYY . На запрошенном ресурсе нет заголовка Access-Control-Allow-Origin. Следовательно, к источнику 'null' доступ не разрешен. Ответ имел код состояния HTTP 403.

Я попытался ПОЛУЧИТЬ URL-адрес через Postman, и он показывает, что указанный выше заголовок успешно передан:

Пройденные заголовки

И из ответа OPTIONS:

Заголовки ответа

Как я могу вызвать свой API из браузера, не возвращаясь к JSON-P?


У вас он настроен на S3? Если да, не могли бы вы поставить Bucket Policy? Убедитесь, что у вас есть метод в своей политике
iSkore

10
Команда API Gateway здесь ... Если вы используете функцию «Включить CORS» в консоли, конфигурация должна быть правильной. Я могу предположить, что вы не вызываете правильный путь к ресурсу в своем API в JavaScript, который выполняет браузер. Если вы попытаетесь выполнить вызов API к несуществующему методу / ресурсу / этапу, вы получите общий 403 без заголовков CORS. Я не понимаю, как браузер может пропустить заголовок Access-Control-Allow-Origin, если вы вызываете правильный ресурс, поскольку вызов OPTIONS в Postman явно содержит все правильные заголовки CORS.
jackko

1
@ RyanG-AWS клиент не подписывает запрос, потому что API аутентифицируется ресурсом, который он вызывает, с использованием пользовательского токена, поэтому учетные данные не имеют значения. Я могу вызвать API, посетив URL-адрес прямо в браузере, и получу соответствующий ответ.
Тайлер

2
@makinbacon: Вы нашли решение этой проблемы? У меня здесь та же проблема.
Nirmal

1
Мои методы и этап были автоматически сгенерированы Lambda. Я включил CORS постфактум. Те же ошибки, что и OP. Я убрал автоматически сгенерированный материал, создал новый API и методы, развернул на новом этапе, и все заработало.
ожог

Ответы:


118

У меня такая же проблема. Я использовал 10 часов, чтобы узнать.

https://serverless.com/framework/docs/providers/aws/events/apigateway/

// handler.js

'use strict';

module.exports.hello = function(event, context, callback) {

const response = {
  statusCode: 200,
  headers: {
    "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
    "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS 
  },
  body: JSON.stringify({ "message": "Hello World!" })
};

callback(null, response);
};

Исправлена ​​и моя проблема. Спасибо за ваш ответ!
Эрик Браун

Я не использую бессерверные, но это решило мою проблему. Думаю, вам нужно передать эти заголовки из фактического источника.
Коста

2
К вашему сведению, в представленном здесь примере есть проблема. Если у вас есть «Access-Control-Allow-Credentials»: true, у вас не может быть подстановочного знака * для Access-Control-Allow-Origin. Это правило применяется браузером. Смотрите здесь и здесь
Кевин

1
Это не работает, снова отображается та же ошибка. Поле заголовка запроса access-control-allow-credentials не разрешено Access-Control-Allow-Headers в ответе перед полетом.
mitesh7172

1
Для всех, кому интересно, вот официальные документы, в которых упоминается это: docs.aws.amazon.com/apigateway/latest/developerguide/… > Для интеграции Lambda или HTTP-прокси вы все равно можете настроить требуемые заголовки ответов> OPTIONS в API Gateway. Однако вы должны полагаться на> серверную часть, чтобы вернуть заголовки Access-Control-Allow-Origin, потому что ответ интеграции> отключен для интеграции прокси.
Леонид Усов

104

Если кто-то еще сталкивается с этим, я смог отследить основную причину в моем приложении.

Если вы используете API-Gateway с настраиваемыми авторизаторами, API-Gateway отправит 401 или 403 обратно, прежде чем он действительно попадет на ваш сервер. По умолчанию - API-шлюз НЕ настроен для CORS при возврате 4xx от настраиваемого авторизатора.

Также - если вы получаете код состояния 0или 1из запроса, проходящего через API Gateway, вероятно, это ваша проблема.

Чтобы исправить - в конфигурации шлюза API - перейдите в «Ответы шлюза», разверните «По умолчанию 4XX» и добавьте туда заголовок конфигурации CORS. т.е.

Access-Control-Allow-Origin: '*'

Не забудьте повторно развернуть свой шлюз - и вуаля!


7
я люблю тебя. серьезно над этим работали два дня.
efong5 03

4
Для тех, кто хочет сделать это с помощью интерфейса командной строки AWS, используйте:aws apigateway update-gateway-response --rest-api-id "XXXXXXXXX" --response-type "DEFAULT_4XX" --patch-operations op="add",path="/responseParameters/gatewayresponse.header.Access-Control-Allow-Origin",value='"'"'*'"'"'
Will

1
Я не использую пользовательские авторизаторы, и они все еще нужны, так как в моем запросе был плохой JSON - спасибо!
Force Hero

9
на заметку - не забудьте потом развернуть API :)
Дэниелн

2
Странно, у меня это сработало, но передислоцировать не пришлось. Я пробовал перераспределить раньше. Не уверен, почему это сработало для меня.
Майкл

19

1) Мне нужно было сделать то же самое, что и @riseres, и некоторые другие изменения. Это мои заголовки ответов:

headers: {
            'Access-Control-Allow-Origin' : '*',
            'Access-Control-Allow-Headers':'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
            'Access-Control-Allow-Credentials' : true,
            'Content-Type': 'application/json'
        }

2) И

Согласно этой документации:

http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

Когда вы используете прокси для лямбда-функций в конфигурации шлюза API, методы post или get не имеют добавленных заголовков, только параметры. Вы должны сделать это вручную в ответе (ответ сервера или лямбда-ответа).

3) И

Кроме того, мне нужно было отключить опцию «Требуется ключ API» в моем методе публикации шлюза API.


5
Да, я думаю, что многие из нас сначала упускают тонкую вещь: как только вы настроите интеграцию шлюза API для функции Lambda с помощью «Use Lambda Proxy Integration», вы должны сделать то, что вы и другие заявляете, и убедиться, что заголовки добавлены. программно в вашем лямбда-ответе. Автоматическая генерация, которая создается с помощью «Включение CORS» на API-шлюзе и создает ответчик OPTIONS, великолепна, но не поможет вам полностью, если вы установите «Использовать интеграцию Lambda Proxy» в запросе интеграции в API. Шлюз.

1
Это сработало для меня ... после правильного прочтения руководства: Внимание! При применении приведенных выше инструкций к ЛЮБОМУ методу в интеграции прокси никакие применимые заголовки CORS не будут установлены. Вместо этого ваш бэкэнд должен возвращать соответствующие заголовки CORS, такие как Access-Control-Allow-Origin. docs.aws.amazon.com/apigateway/latest/developerguide/…
BennyHilarious

14

Если вы попробовали все, что касалось этой проблемы, безрезультатно, вы окажетесь там же, где и я. Оказывается, существующие в Amazon инструкции по настройке CORS работают нормально ... просто убедитесь, что вы не забыли выполнить повторное развертывание ! Мастер редактирования CORS, даже со всеми его красивыми маленькими зелеными галочками, не обновляет ваш API в реальном времени. Возможно, очевидно, но это озадачило меня на полдня.

введите описание изображения здесь


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

@ChrisChristensen рад , что вы получили это понял, - всегда есть что - то такое облегчение , но невероятно побеждая о проблемах , как это
генерируют излучение

Это ответ, который действителен в 2020 году. Спасибо
Рахул Кханна,

RE-DEPLOY RE-DPLOY RE-DEPLOY
Surjith SM

11

Получил мой образец работы: я просто вставил 'Access-Control-Allow-Origin': '*' внутри заголовков: {} в сгенерированную функцию nodejs Lambda. Я не сделал ни одного изменения в лямбда-генерируемой API слоя.

Вот мой NodeJS:

'use strict';
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();
exports.handler = ( event, context, callback ) => {
    const done = ( err, res ) => callback( null, {
        statusCode: err ? '400' : '200',
        body: err ? err.message : JSON.stringify(res),
        headers:{ 'Access-Control-Allow-Origin' : '*' },
    });
    switch( event.httpMethod ) {
        ...
    }
};

Вот мой вызов AJAX

$.ajax({
    url: 'https://x.execute-api.x-x-x.amazonaws.com/prod/fnXx?TableName=x',
    type: 'GET',
    beforeSend: function(){ $( '#loader' ).show();},
    success: function( res ) { alert( JSON.stringify(res) ); },
    error:function(e){ alert('Lambda returned error\n\n' + e.responseText); },
    complete:function(){ $('#loader').hide(); }
});

Я обнаружил, что большая часть документации Amazon устарела, даже с фрагментом пути «../latest/ ..». После того, как неделю назад все было убрано, кнопка CORS внезапно заявила, что работает правильно. API автоматически создал метод «ANY», а кнопка CORS автоматически создала метод «OPTIONS» - я ничего не добавил в API. Вышеупомянутый «GET» работает, и с тех пор я добавил ajax «POST», который также работает без моего вмешательства в API.
MannyC

Я потратил почти два часа, пытаясь выяснить, как добавить Access-Control-Allow-Origin в ответ метода с помощью консоли AWS, но это также было единственное, что у меня сработало.
Shn_Android_Dev 02

8

Для гуглеров:

Вот почему:

  • Простой запрос или GET/ POSTбез файлов cookie не запускает предполетную проверку
  • Когда вы настраиваете CORS для пути, API Gateway создает только OPTIONSметод для этого пути, а затем отправляет Allow-Originзаголовки, используя фиктивные ответы при вызове пользователя OPTIONS, но GET/ POSTне будет Allow-Originавтоматически
  • Если вы попытаетесь отправить простые запросы с включенным режимом CORS, вы получите сообщение об ошибке, потому что этот ответ не имеет Allow-Originзаголовка.
  • Вы можете придерживаться передовой практики, простые запросы не предназначены для отправки ответа пользователю, отправьте аутентификацию / файл cookie вместе с вашими запросами, чтобы сделать его «непростым», и предварительная проверка запустит
  • Тем не менее, вам придется самостоятельно отправлять заголовки CORS для следующего запроса. OPTIONS

Подвести итог:

  • Только безвредные OPTIONSбудут сгенерированы API Gateway автоматически
  • OPTIONSиспользуются браузером только в качестве меры предосторожности для проверки возможности CORS на пути
  • Если CORS будет принято в зависимости от фактического метода , например , GET/POST
  • Вы должны вручную отправить соответствующие заголовки в свой ответ.

6

Я просто добавил заголовки в свой ответ лямбда-функции, и это сработало как шарм

exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hey it works'),
        headers:{ 'Access-Control-Allow-Origin' : '*' }
    };
    return response;
};

4

Я нашел простое решение в

API Gateway> Выберите конечную точку API> Выберите метод (в моем случае это был POST)

Теперь есть выпадающий список ДЕЙСТВИЯ> Включить CORS .. выберите его.

Теперь снова выберите раскрывающийся список ДЕЙСТВИЯ> Развернуть API (повторно развернуть)

введите описание изображения здесь

Это сработало !


Почему этот ответ отклонен, но есть другие похожие ответы ниже?
Динеш Кумар

Для вызова шлюза API на основе AWS это решение работает
ewalel

3

Я получил свою работу после того, как понял, что авторизатор лямбда не работает и по какой-то неизвестной причине это переводится в ошибку CORS. Простое исправление для моего авторизатора (и некоторых тестов авторизатора, которые я должен был добавить в первую очередь), и это сработало. Для меня требовалось действие шлюза API «Включить CORS». Это добавило все заголовки и другие настройки, которые мне нужны в моем API.


и повторно развернуть! :)
Робин С Сэмюэл

3

Для меня ответ, который НАКОНЕЦ Сработал, был комментарием Джеймса Шапиро к ответу Alex R (второй по популярности). Я столкнулся с этой проблемой API-шлюза в первую очередь, пытаясь получить статическую веб-страницу, размещенную на S3, для использования лямбда-выражения для обработки страницы контактов и отправки электронного письма. Простая проверка [] Default 4XX исправила сообщение об ошибке.

введите описание изображения здесь


Где вы найдете это меню? Я этого нигде не вижу.
Ник Х,

@NickH, взгляни на фотографию Рави Рама. В разделе «Действия» должен быть пункт «Включить CORS», и когда вы его выберете, появится меню.
Джейсон

2

После изменения функции или кода Выполните эти два шага.

Сначала включайте CORS, затем каждый раз развертывайте API .


Спасибо тебе за это. Не заметил в ресурсе «Включить CORS». Я потерял рассудок.
Шломи Базель,

2

Развертывание кода после включения CORS для обоих POSTи OPTIONSработал для меня.


1
Спасибо за ваш вклад, но можете ли вы объяснить, почему это сработало для вас? Я предлагаю вам прочитать это руководство, чтобы улучшить свой ответ: «Как я могу написать хороший ответ» здесь: stackoverflow.com/help/how-to-answer
Гийом Раймон,

1

Я работаю aws-serverless-express, и в моем случае нужно отредактировать simple-proxy-api.yaml.

До того, как CORS был настроен https://example.com, я просто заменил имя своего сайта и повторно развернул через npm run setup, и он обновил мой существующий лямбда / стек.

#...
/:
#...
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...
/{proxy+}:
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...

1

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


2
Я рад, что оставил этот комментарий. Со мной такое происходит: D.
CamHart

Мне нравится находить собственное решение повторяющейся проблемы в будущем.
Зак Грирсон,

0

Другой основной причиной этой проблемы может быть разница между HTTP / 1.1 и HTTP / 2.

Симптом: некоторые пользователи, но не все, сообщали об ошибке CORS при использовании нашего Программного обеспечения.

Проблема:Access-Control-Allow-Origin заголовок отсутствовал иногда .

Контекст: у нас есть лямбда-выражение, предназначенное для обработки OPTIONSзапросов и ответов с соответствующими заголовками CORS, например для Access-Control-Allow-Originсопоставления с белым списком Origin.

Решение . Кажется, что шлюз API преобразует все заголовки в нижний регистр для вызовов HTTP / 2, но сохраняет заглавные буквы для HTTP / 1.1. Это привело к event.headers.originсбою доступа к .

Убедитесь, что у вас тоже есть эта проблема:

Предполагая, что ваш API находится в https://api.example.com, а ваш интерфейс - в https://www.example.com. Используя CURL, сделайте запрос по HTTP / 2:

curl -v -X OPTIONS -H 'Origin: https://www.example.com' https://api.example.com

Выходные данные ответа должны включать заголовок:

< Access-Control-Allow-Origin: https://www.example.com

Повторите тот же шаг, используя HTTP / 1.1 (или с Originзаголовком в нижнем регистре ):

curl -v -X OPTIONS --http1.1 -H 'Origin: https://www.example.com' https://api.example.com

Если Access-Control-Allow-Originзаголовок отсутствует, вы можете проверить чувствительность к регистру при чтении Originзаголовка.


0

Помимо других комментариев, следует обратить внимание на статус, возвращаемый вашей базовой интеграцией, и если для этого статуса возвращается заголовок Access-Control-Allow-Origin.

Выполнение функции «Включить CORS» устанавливает только статус 200. Если у вас есть другие на конечной точке, например 4xx и 5xx, вам нужно добавить заголовок самостоятельно.


-2

В моем случае я просто неправильно писал URL-адрес запроса на выборку. На serverless.yml, вы установите corsна true:

register-downloadable-client:
    handler: fetch-downloadable-client-data/register.register
    events:
      - http:
          path: register-downloadable-client
          method: post
          integration: lambda
          cors: true
          stage: ${self:custom.stage}

а затем в обработчике лямбда вы отправляете заголовки, но если вы сделаете запрос на выборку неправильно во внешнем интерфейсе, вы не получите этот заголовок в ответе, и вы получите эту ошибку. Итак, дважды проверьте URL-адрес вашего запроса на передней панели.


-3

В Python вы можете сделать это, как показано в коде ниже:

{ "statusCode" : 200,
'headers': 
    {'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': "*"
     },
"body": json.dumps(
    {
    "temperature" : tempArray,
    "time": timeArray
    })
 }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.