API шлюзу CORS: немає заголовка 'Access-Control-Allow-Origin'


102

Хоча 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 ... Якщо ви використовуєте в консолі функцію «Увімкнути CORS», конфігурація повинна бути правильною. Я найкраще здогадався б, що ви не використовуєте правильний шлях до ресурсу в своєму API в JavaScript, який виконує браузер. Якщо ви спробуєте здійснити виклик API до неіснуючого методу / ресурсу / етапу, ви отримаєте загальний 403 без жодного заголовка CORS. Я не бачу, як браузер міг пропустити заголовок Access-Control-Allow-Origin, якщо ви викликаєте потрібний ресурс, оскільки виклик OPTIONS у Postman явно містить усі правильні заголовки CORS.
jackko

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

2
@makinbacon: Ви знайшли рішення для цього? Я проходжу те саме питання тут.
Нірмал,

1
Мої методи та етап були сформовані автоматично Лямбдою. Я фактично включив CORS. Ті самі помилки, що і OP. Я підірвав автоматично згенерований матеріал, створив новий API та методи, розгорнув на новий етап, і він працював нормально.
ошпарити

Відповіді:


116

Я отримую ту саму проблему. Я використав 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
FYI, тут є проблема із прикладом, представленим тут. Якщо у вас є "Access-Control-Allow-Credentials": true, ви не можете мати підстановочний знак * для Access-Control-Allow-Origin. Це правило застосовується браузером. Дивіться тут і тут
Кевін,

1
Це не працює, знову показує ту саму помилку Поле заголовка запиту access-control-allow-credentials не допускається Access-Control-Allow-Headers у передпольоті.
mitesh7172

як ви можете це зробити за допомогою класу java RequestHandler <RequestClass, ResponseClass>?
Snedden27,

104

Якщо хтось інший стикається з цим досі - я зміг відстежити першопричину в моєму додатку.

Якщо ви використовуєте API-шлюз із користувацькими авторизаторами - API-шлюз надішле 401 або 403 назад, перш ніж він дійсно потрапить на ваш сервер. За замовчуванням - API-шлюз НЕ налаштований для CORS при поверненні 4xx від спеціального авторизатора.

Крім того - якщо ви будете отримувати код стану 0або 1з запиту , що проходить через API Gateway, це, ймовірно , ваше запитання.

Для виправлення - у конфігурації шлюзу API - перейдіть до «Відповіді шлюзу», розгорніть «За замовчуванням 4XX» і додайте туди заголовок конфігурації CORS. тобто

Access-Control-Allow-Origin: '*'

Переконайтеся, що перерозгорнули ваш шлюз - і вуаля!


7
я тебе люблю. серйозно працював над цим два дні.
efong5,

4
Для тих, хто хоче зробити це за допомогою AWS CLI, використовуйте: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='"'"'*'"'"'
Буде

1
Я не використовую власні авторизатори, і все одно мені це потрібно, оскільки в моєму запиті був поганий JSON - дякую!
Force Hero

9
зверніть увагу на себе - не забудьте згодом розгорнути API :)
danieln

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 для функції Лямбда за допомогою "Використовувати інтеграцію лямбда-проксі", ви повинні зробити те, що заявляєте ви та інші, і забезпечити додавання заголовків програмно у відповідь вашої лямбди. Матеріали автогенеру, створені за допомогою "Увімкнення CORS" на шлюзі API, і він створює респондент OPTIONS - це чудово, але не приведе вас до кінця, якщо ви встановите "Використовувати інтеграцію лямбда-проксі" у Запиті на інтеграцію в API Шлюз.

1
Це спрацювало для мене ... після належного прочитання посібника: Важливо. Застосовуючи наведені вище інструкції до БУДЬ-ЯКОГО методу в інтеграції проксі-сервера, будь-які відповідні заголовки CORS не встановлюватимуться. Натомість ваш сервер повинен повернути відповідні заголовки CORS, такі як Access-Control-Allow-Origin. docs.aws.amazon.com/apigateway/latest/developerguide/…
BennyHilarious

14

Якщо ви спробували все, що стосується цього питання, безрезультатно, ви опинитесь там, де я зробив. Виявляється, що існують CORS напрямки настройки Amazon працюють просто відмінно ... просто переконайтеся , що ви пам'ятаєте про перекидання ! Майстер редагування CORS, навіть з усіма його приємними маленькими зеленими позначками, не робить поточних оновлень вашого API. Можливо, очевидно, але це мене тупило півдня.

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


Це було все. Буквально працюючи над цим два дні. Не впевнений, що логіка не принаймні вимагає передислокації після редагування шлюзу.
Chris Christensen

@ChrisChristensen радий , що ви отримали це зрозумів, - завжди є що - то таке полегшення , але неймовірно перемагаючи про проблеми , як це
генерують випромінювання

Це відповідь, яка діє в 2020 році. Дякую
Рахул Ханна,

ПОВТОРНЕ ВИКОНАННЯ ПОВТОРНЕ ВИКОРИСТАННЯ ПОВТОРНЕ ВИКОРИСТАННЯ
Surjith SM

11

Зробок працює: я щойно вставив 'Access-Control-Allow-Origin': '*', всередині заголовків: {} у створену функцію лямбда-нодея. Я не вніс жодних змін у рівень 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 автоматично створив метод «БУДЬ-ЯКИЙ», а кнопка CORS автоматично створив метод «ВАРІАНТИ» - я нічого не додав до API. "GET" вище працює, і з тих пір я додав ajax "POST", який також працює, не торкаючись API.
MannyC

Я витратив майже дві години, намагаючись зрозуміти, як отримати Access-Control-Allow-Origin доданий до відповіді методу за допомогою консолі AWS, але це також було єдине, що працювало для мене.
Shn_Android_Dev

8

Для працівників Google:

Ось чому:

  • Простий запит, або, GET/ POSTбез файлів cookie не викликає попередній перегляд
  • Коли ви налаштовуєте CORS для шляху, шлюз API створює лише OPTIONSметод для цього шляху, а потім надсилає Allow-Originзаголовки, використовуючи фіктивні відповіді під час дзвінків користувача OPTIONS, але GET/ POSTне отримує Allow-Originавтоматично
  • Якщо ви спробуєте надіслати прості запити з увімкненим режимом CORS, ви отримаєте повідомлення про помилку, оскільки відповідь не має Allow-Originзаголовка
  • Ви можете дотримуватися найкращої практики, прості запити не призначені для надсилання відповіді користувачеві, надсилання автентифікації / файлу cookie разом із вашими запитами, щоб зробити це "не простим", і попередній політ спрацює
  • Тим не менше, вам доведеться надсилати заголовки CORS самостійно для наступного запиту OPTIONS

Підсумовуючи:

  • OPTIONSAPI Gateway автоматично генерує лише нешкідливі
  • OPTIONSвикористовуються браузером лише як запобіжний захід для перевірки можливості CORS на шляху
  • Якщо CORS буде прийнято в залежності від фактичного методу , наприклад , GET/POST
  • Вам потрібно вручну надіслати відповідні заголовки у відповіді

5

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

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

4

Я знайшов просте рішення всередині

Шлюз API> Виберіть кінцеву точку API> Виберіть метод (у моєму випадку це був POST)

Тепер є спадне меню ДІЇ> Увімкнути CORS .. виберіть його.

Тепер знову виберіть спадне меню ДІЇ> Розгорнути API (повторно розгорнути його)

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

Це спрацювало !


Чому за цю відповідь не голосують, але нижче є інші подібні відповіді?
Dinesh Kumar

Для виклику шлюзу API на базі AWS це рішення працює
щороку,

3

Я почав працювати після того, як зрозумів, що лямбда-авторизатор вийшов з ладу, і з якоїсь невідомої причини це перетворилося на помилку CORS. Просте виправлення мого авторизатора (і деяких тестів авторизатора, які я мав би додати в першу чергу), і воно спрацювало. Для мене потрібна дія шлюзу API "Увімкнути CORS". Це додало всі заголовки та інші налаштування, які мені потрібні в моєму API.


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

2

Після зміни функції або коду Виконайте ці два кроки.

Спочатку ввімкніть CORS, а потім щоразу розгортайте API .


Дякую тобі за це. Не помітив "Увімкнути CORS" у ресурсі. Змусив мене втратити розум.
Шломі Базель

2

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


1
Дякуємо за ваш внесок, однак, чи можете ви пояснити, чому це спрацювало для вас? Запрошую вас прочитати цей посібник, щоб покращити свою відповідь: "Як я пишу хорошу відповідь" тут: stackoverflow.com/help/how-to-answer
Гійом Реймонд

2

Для мене відповіддю, яка НАРЕШТУ ПРАЦЮВАЛА, був коментар Джеймса Шапіро з відповіді Алекса Р (другий за рейтингом). Перш за все я потрапив у цю проблему шлюзу API, намагаючись отримати статичну веб-сторінку, розміщену в S3, щоб використовувати лямбда-обробку для обробки сторінки зв’язку з нами та надсилання електронного листа. Просто перевіривши [] За замовчуванням 4XX виправлено повідомлення про помилку.

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


Де ви знайдете це меню? Я ніде цього не бачу.
Нік Х,

@NickH поглянь на знімок Раві Рама. У розділі "Дії" повинен бути пункт "Увімкнути CORS", і коли ви виберете це, відобразиться меню.
Джейсон,

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, мені потрібно було надати дозволи на роль IAM для досягнення кінцевої точки.


2
Чоловік, я радий, що залишив цей коментар. Це постійно відбувається зі мною: D.
CamHart

Я люблю знаходити власне рішення майбутнього повторюваного питання.
Zac Grierson

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.