API Gateway CORS: 'Access-Control-Allow-Origin' başlığı yok


103

CORS, API Gateway aracılığıyla ve Access-Control-Allow-Originüstbilgi ayarlanmış olmasına rağmen , API'yi Chrome içinde AJAX'tan çağırmaya çalışırken aşağıdaki hatayı almaya devam ediyorum:

XMLHttpRequest http://XXXXX.execute-api.us-west-2.amazonaws.com/beta/YYYYY yüklenemiyor . İstenen kaynakta 'Access-Control-Allow-Origin' başlığı yok. Bu nedenle 'boş' kaynağına erişime izin verilmiyor. Yanıtta 403 HTTP durum kodu vardı.

Postman aracılığıyla URL’yi ALMAYA çalıştım ve yukarıdaki başlığın başarıyla geçtiğini gösteriyor:

Başlıklar geçti

SEÇENEKLER cevabından:

Yanıt üstbilgileri

API'mi JSON-P'ye dönmeden tarayıcıdan nasıl çağırabilirim?


S3'te kurulu mu? Eğer öyleyse, koyabilir misin Bucket Policy? Politikanızda yöntemin bulunduğundan emin olun
iSkore

10
API Ağ Geçidi ekibi burada ... Konsolda 'CORS'yi Etkinleştir' özelliğini kullanıyorsanız, yapılandırma doğru olmalıdır. En iyi tahminim, tarayıcının çalıştırdığı JavaScript'te API'nizde doğru kaynak yolunu çağırmadığınızdır. Varolmayan bir yönteme / kaynağa / aşamaya bir API çağrısı yapmaya çalışırsanız, hiçbir CORS üstbilgisi içermeyen genel bir 403 alırsınız. Postman'daki OPTIONS çağrısı tüm doğru CORS başlıklarını açıkça içerdiğinden, doğru kaynağı arıyorsanız, tarayıcının Access-Control-Allow-Origin başlığını nasıl kaçırabileceğini anlamıyorum.
jackko

1
@ RyanG-AWS İstemci isteği imzalamıyor çünkü API, kullanıcıya özel bir belirteç kullanarak çağırdığı kaynak tarafından doğrulanıyor, bu nedenle kimlik bilgileri bir faktör değil. URL'yi doğrudan tarayıcıda ziyaret ederek API'yi çağırabilirim ve uygun yanıtı alırım.
Tyler

2
@makinbacon: Bunun için bir çözüm buldunuz mu? Ben de burada aynı sorunu yaşıyorum.
Nirmal

1
Yöntemlerim ve aşamam Lambda tarafından otomatik olarak oluşturuldu. Aslında CORS'u etkinleştirdim. OP ile aynı hatalar. Otomatik olarak üretilen şeyleri mahvettim, yeni bir API ve yöntemler yarattım, yeni bir aşamaya konuşlandırdım ve iyi çalıştı.
haşlanma

Yanıtlar:


118

Aynı problem bende de var. Bulmak için 10 saat kullandım.

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);
};

Benim de yaşadığım sorunu düzelttim. Cevabınız için teşekkür ederim!
Eric Brown

Sunucusuz kullanmıyorum, ancak bu sorunumu çözdü. Sanırım bu başlıkları gerçek kaynaktan aktarmanız gerekiyor.
Costa

2
Bilginize, burada sunulan örnekle ilgili bir sorun var. "Access-Control-Allow-Credentials" varsa: true, Access-Control-Allow-Origin için * joker karakterine * sahip olamazsınız. Bu kural tarayıcı tarafından uygulanmaktadır. Buraya ve buraya
Kevin

1
Bu çalışmıyor, Yine aynı hatayı gösteriyor İstek başlık alanı erişim-kontrol-izin verme kimlik bilgilerine ön kontrol yanıtında Access-Control-Allow-Headers tarafından izin verilmiyor.
mitesh7172

1
Merak edenler için, işte bundan bahseden resmi belgeler: docs.aws.amazon.com/apigateway/latest/developerguide/… > Lambda veya HTTP proxy entegrasyonları için, API Ağ Geçidinde gerekli> SEÇENEKLER yanıt başlıklarını yine de kurabilirsiniz. Ancak,> tümleştirme yanıtı proxy entegrasyonu için devre dışı bırakıldığından, Access-Control-Allow-Origin üstbilgilerini döndürmek için> arka uca güvenmeniz gerekir.
Leonid Usov

104

Hala bununla karşılaşan başka biri varsa - uygulamamdaki temel nedeni bulabildim.

API-Gateway'i özel Yetkilendiricilerle çalıştırıyorsanız - API-Gateway, sunucunuza ulaşmadan önce 401 veya 403'ü geri gönderir. Varsayılan olarak - API Ağ Geçidi, özel bir yetkilendiriciden 4xx döndürüldüğünde CORS için yapılandırılmaz.

Ayrıca - API Ağ Geçidi üzerinden çalışan bir istekten 0veya durum kodunu alıyorsanız 1, bu muhtemelen sizin sorununuzdur.

Düzeltmek için - API Ağ Geçidi yapılandırmasında - "Ağ Geçidi Yanıtları" na gidin, "Varsayılan 4XX" öğesini genişletin ve oraya bir CORS yapılandırma başlığı ekleyin. yani

Access-Control-Allow-Origin: '*'

Ağ geçidinizi yeniden konuşlandırdığınızdan emin olun - ve işte!


7
seni seviyorum. iki gündür bunun üzerinde ciddi bir şekilde çalışıyorum.
efong5

4
AWS CLI ile bunu isteyenler için kullanın: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
Özel Yetkilendiriciler kullanmıyorum ve isteğimde kötü JSON olduğu için buna hala ihtiyacım var - teşekkür ederim!
Force Hero

9
kendime not edin - daha sonra API'yi dağıtmayı unutmayın :)
danieln

2
Garip, bu benim için çalıştı, ancak yeniden konuşlandırmam gerekmedi. Daha önce yeniden dağıtmayı denedim. Neden benim için işe yaradığından emin değilim.
Michael

19

1) @riseres ve diğer bazı değişikliklerle aynı şeyi yapmam gerekiyordu. Bunlar benim yanıt başlıklarım:

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) Ve

Bu belgelere göre:

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

API Gateway yapılandırmasında lambda işlevleri için proxy kullandığınızda, post veya get yöntemlerinin ek başlıkları yoktur, yalnızca seçenekler vardır. Yanıtta manuel olarak yapmanız gerekir (sunucu veya lambda yanıtı).

3) Ve

Bunun yanı sıra, API ağ geçidi gönderi yöntemimde 'API Anahtarı Gerekli' seçeneğini devre dışı bırakmam gerekiyordu.


5
Evet, sanırım çoğumuz başlangıçta gözden kaçırdığımız ince şey, Lambda işlevi için API Ağ Geçidi entegrasyonunuzu "Lambda Proxy Entegrasyonunu Kullan" ile yapılandırdıktan sonra, sizin ve diğerlerinin belirttiği gibi yapmanız ve başlıkların eklendiğinden emin olmanız gerektiğidir. lambda'nızın yanıtında programlı olarak. Bir API Ağ Geçidinde "CORS Etkinleştirilerek" oluşturulan ve bir OPTIONS yanıtlayıcısı oluşturarak oluşturulan otomatik oluşturma öğeleri harikadır, ancak API içindeki Entegrasyon İsteğinde "Lambda Proxy entegrasyonunu kullan" ayarını yaparsanız sizi oraya götürmez. Ağ geçidi.

1
Bu benim için çalıştı ... kılavuzu doğru bir şekilde okuduktan sonra: Önemli Yukarıdaki talimatları bir proxy entegrasyonunda HERHANGİ bir yönteme uygularken, geçerli CORS başlıkları ayarlanmayacaktır. Bunun yerine, arka ucunuz Access-Control-Allow-Origin gibi geçerli CORS başlıklarını döndürmelidir. docs.aws.amazon.com/apigateway/latest/developerguide/…
BennyHilarious

14

Bu konuyla ilgili her şeyi boşuna denediyseniz, yaptığım yere varacaksınız. Görünüşe göre, Amazon'un mevcut CORS kurulum yönergeleri gayet iyi çalışıyor ... sadece yeniden dağıtmayı unutmadığınızdan emin olun ! CORS düzenleme sihirbazı, tüm güzel yeşil onay işaretleriyle bile, API'niz için canlı güncellemeler yapmaz. Belli olabilir, ama bu beni yarım günlüğüne şaşırttı.

görüntü açıklamasını buraya girin


Bu oydu. Kelimenin tam anlamıyla bunun üzerinde iki gün çalışıyorum. Ağ geçidini düzenledikten sonra mantığın en azından yeniden konuşlandırmayı istemediğinden emin değilsiniz.
Chris Christensen

@ChrisChristensen, anladığına sevindim - böyle problemlerde her zaman çok rahatlatıcı ama inanılmaz derecede yenen bir şeyler var
lase

2020'de geçerli olan cevap budur. Teşekkürler
Rahul Khanna

YENİDEN YÜKLEME YENİDEN YÜKLEME YENİDEN
YÜKLEME

11

Benim örnek çalışma var: Ben sadece eklenen 'Erişim Kontrol-Origin izin ver':, '*' içeride {}: başlıklarıyla oluşturulan Lambda'ya nodejs işlevinde. Ben yapılan bir Lambda oluşturulan API katmanına bir değişiklik.

İşte NodeJS'im:

'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 ) {
        ...
    }
};

İşte AJAX çağrım

$.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(); }
});

"../Latest/ .." yol parçasıyla bile Amazon'un pek çok belgesinin güncelliğini yitirmiş buldum. Yaklaşık bir hafta önce her şeyi hurdaya çıkardıktan sonra, CORS düğmesi aniden düzgün çalıştığını belirtti. API otomatik olarak "HERHANGİ" yöntemini oluşturdu ve CORS düğmesi "SEÇENEKLER" yöntemini otomatik olarak oluşturdu - API'ye hiçbir şey eklemedim. Yukarıdaki "GET" çalışıyor ve o zamandan beri API'ye dokunmadan da çalışan bir ajax "POST" ekledim.
MannyC

AWS konsolunu kullanarak yöntem yanıtına Access-Control-Allow-Origin'i nasıl ekleyeceğimi anlamaya çalışırken neredeyse iki saat harcadım, ancak bu benim için çalışan tek şeydi.
Shn_Android_Dev

8

Google çalışanları için:

İşte nedeni:

  • Basit istek veya GET/ POSThiçbir çerez olmadan ön kontrolü tetikleme
  • Eğer bir yol için CORS'yi yapılandırırken, API Gateway sadece yaratacak OPTIONSbu yol için bir yöntem, daha sonra göndermek Allow-Originkullanıcı aramaları sırasında sahte yanıtları kullanarak başlıkları OPTIONS, ama GET/ POSTalmazsınız Allow-Originotomatik
  • CORS modu açıkken basit istekler göndermeye çalışırsanız, bir hata alırsınız çünkü bu yanıtta Allow-Originbaşlık yoktur.
  • En iyi uygulamaya bağlı kalabilirsiniz, basit istekler kullanıcıya yanıt göndermeyi amaçlamaz, bunu "basit değil" yapmak için isteklerinizle birlikte kimlik doğrulama / tanımlama bilgisi gönderir ve ön kontrol tetiklenir
  • Yine de, aşağıdaki istek için CORS başlıklarını kendiniz göndermeniz gerekecektir. OPTIONS

Özetlersek:

  • OPTIONSAPI Gateway tarafından otomatik olarak yalnızca zararsız oluşturulur
  • OPTIONSbir yolda CORS olasılığını kontrol etmek için yalnızca bir tedbir olarak tarayıcı tarafından kullanılır
  • CORS'un kabul edilip edilmeyeceği gerçek yönteme bağlıdır, örneğin GET/POST
  • Yanıtınıza uygun başlıkları manuel olarak göndermelisiniz

6

Lambda işlevi yanıtıma yeni başlıklar ekledim ve bir cazibe gibi çalıştı

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

4

İçinde basit bir çözüm buldum

API Ağ Geçidi> API uç noktanızı seçin> Yöntemi seçin (benim durumumda bu POST idi)

Şimdi bir açılır ACTIONS> CORS'u Etkinleştir .. onu seçin.

Şimdi ACTIONS açılır menüsünü tekrar seçin> API'yi dağıtın (yeniden dağıtın)

görüntü açıklamasını buraya girin

İşe yaradı !


Bu yanıt neden reddedildi ama aşağıda benzer başka yanıtlar da var?
Dinesh Kumar

AWS tabanlı API ağ geçidi çağrısı için bu çözüm işe
yarar

3

Lambda yazarının başarısız olduğunu ve bilinmeyen bir nedenle bunun bir CORS hatasına çevrildiğini fark ettikten sonra benimkini çalıştırdım. Yazarım için basit bir düzeltme (ve ilk etapta eklemem gereken bazı yazar testleri) ve işe yaradı. Benim için API Ağ Geçidi eylemi 'CORS'yi Etkinleştir' gerekliydi. Bu, API'mde ihtiyaç duyduğum tüm üstbilgileri ve diğer ayarları ekledi.


ve yeniden konuşlandırın! :)
Robin C Samuel

3

Benim için, SONUNDA ÇALIŞTI'nın cevabı James Shapiro'nun Alex R'nin cevabındaki yorumuydu (en çok oy alan ikinci). Bu API Ağ Geçidi sorununa ilk etapta, bize ulaşın sayfasını işlemek ve bir e-posta göndermek için lambda kullanmak üzere S3'te barındırılan statik bir web sayfası almaya çalışarak girdim. Yalnızca [] Varsayılan 4XX'i işaretlemek hata mesajını düzeltti.

görüntü açıklamasını buraya girin


Bu menüyü nerede buluyorsunuz? Ben onu hiçbir yerde göremiyorum.
Nick H

@NickH, Ravi Ram'ın resmine bir göz atın. "İşlemler" altında "CORS'u Etkinleştir" adlı bir öğe olmalıdır ve bunu seçtiğinizde menü görünecektir.
Jason

2

İşlevinizi veya Kodunuzu Değiştirdikten Sonra Bu iki adımı izleyin.

Önce CORS'yi Etkinleştirin Sonra her seferinde API'yi Dağıtın .


Bunun için teşekkür ederim. Kaynakta "CORS'u Etkinleştir" i fark etmedim. Aklımı kaybetmeme neden oldu.
Shlomi Bazel

2

Her ikisi için CORS'yi etkinleştirdikten sonra kod Dağıtma POSTve OPTIONSbenim için çalıştı.


1
Katkınız için teşekkürler, ancak neden işinize yaradığını açıklayabilir misiniz? Yanıtınızı iyileştirmek için sizi şu kılavuzu okumaya davet ediyorum: "İyi bir yanıtı nasıl yazarım?" Burada: stackoverflow.com/help/how-to-answer
Guillaume Raymond

1

Koşuyorum aws-serverless-expressve benim durumumda düzenlemem gerekiyor simple-proxy-api.yaml.

CORS yapılandırılmadan önce https://example.com, sitemin adını değiştirdim ve üzerinden yeniden konuşlandırdım npm run setupve mevcut lambda / yığınımı güncelledi.

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

1

Benim durumumda, API Ağ Geçidi için Yetkilendirme yöntemi olarak AWS_IAM kullandığım için, uç noktaya ulaşmak için IAM rolü izinlerimi vermem gerekiyordu.


2
Adamım bu yorumu yaptığıma sevindim. Bu bana olmaya devam ediyor: D.
CamHart

Gelecekte tekrarlanan bir soruna kendi çözümümü bulmayı seviyorum.
Zac Grierson

0

Bu sorunun başka bir temel nedeni, HTTP / 1.1 ve HTTP / 2 arasındaki bir fark olabilir.

Belirti: Hepsi değil, bazı kullanıcılar Yazılımımızı kullanırken bir CORS hatası aldıklarını bildirdi.

Sorun:Access-Control-Allow-Origin başlığı eksikti bazen .

Bağlam: İstekleri işleme OPTIONSve Access-Control-Allow-Originbeyaz listedeki bir listeyi eşleştirme gibi karşılık gelen CORS başlıklarıyla yanıtlamaya adanmış bir Lambda'mız vardı Origin.

Çözüm: API Ağ Geçidi, tüm üstbilgileri HTTP / 2 çağrıları için küçük harfe dönüştürüyor gibi görünüyor, ancak HTTP / 1.1 için büyük harf kullanımını koruyor. Bu, erişimin event.headers.originbaşarısız olmasına neden oldu .

Bu sorunu da yaşayıp yaşamadığınızı kontrol edin:

API'nizin konumunda olduğunu https://api.example.comve ön ucunuzun konumunda olduğunu varsayarsak https://www.example.com. CURL kullanarak, HTTP / 2 kullanarak bir istekte bulunun:

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

Yanıt çıktısı başlığı içermelidir:

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

HTTP / 1.1 (veya küçük harfli bir Originbaşlık ile) kullanarak aynı adımı tekrarlayın :

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

Eğer Access-Control-Allow-Originbaşlık eksik, okumakta küçük harf duyarlılığı kontrol etmek isteyebilirsiniz Originbaşlığı.


0

Diğer yorumlara ek olarak, temeldeki entegrasyonunuzdan döndürülen durum ve bu durum için Access-Control-Allow-Origin başlığının döndürülüp döndürülmemesi dikkat edilmesi gereken bir şeydir.

'CORS'u Etkinleştir' işlemini yapmak yalnızca 200 statüsü oluşturur. Uç noktada başkaları varsa, örneğin 4xx ve 5xx, başlığı kendiniz eklemeniz gerekir.


-2

Benim durumumda, sadece getirme isteği URL'sini yanlış yazıyordum. Açık serverless.yml, ayarladığınız corsiçin 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}

ve sonra lambda işleyicisinde başlıkları gönderirsiniz, ancak ön uçta getirme isteğini yanlış yaparsanız, yanıtta bu başlığı alamayacaksınız ve bu hatayı alacaksınız. Bu nedenle, ön taraftaki istek URL'nizi iki kez kontrol edin.


-3

Python'da bunu aşağıdaki kodda olduğu gibi yapabilirsiniz:

{ "statusCode" : 200,
'headers': 
    {'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': "*"
     },
"body": json.dumps(
    {
    "temperature" : tempArray,
    "time": timeArray
    })
 }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.