HP Alm'nin REST API'sinden bazı verileri almaya çalışıyorum. Küçük bir curl betiği ile oldukça iyi çalışıyor - verilerimi alıyorum.
Şimdi bunu JavaScript, fetch ve ES6 (aşağı yukarı) ile yapmak daha büyük bir sorun gibi görünüyor. Bu hata mesajını almaya devam ediyorum:
Fetch API
yüklenemiyor. Preflight isteğine yanıt gelmiyor erişim kontrolünü geçemiyor: Hiçbir 'Erişim Kontrolü-İzin Ver-Kaynak' başlığı yok istenen kaynak üzerinde mevcut. Köken 'http://127.0.0.1:3000' şudur bu nedenle erişim izni verilmemiştir. Yanıt HTTP durum kodu 501'e sahipti. Eğer opak bir yanıt ihtiyaçlarınızı karşılıyorsa, isteğin modunu şu şekilde ayarlayın Kaynağı CORS devre dışı bırakılmış olarak almak için > 'no-cors'.
Bunun, bu verileri localhost'umdan almaya çalışmamdan kaynaklandığını ve çözümün CORS kullanmak olması gerektiğini anlıyorum. Şimdi bunu gerçekten yaptığımı düşündüm, ama bir şekilde ya başlıkta yazdıklarımı görmezden geliyor ya da sorun başka bir şey mi?
Peki, bir uygulama sorunu var mı? Yanlış mı yapıyorum? Ne yazık ki sunucu kayıtlarını kontrol edemiyorum. Burada gerçekten biraz sıkışmış durumdayım.
function performSignIn() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
headers.append('GET', 'POST', 'OPTIONS');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(sign_in, {
//mode: 'no-cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
Chrome kullanıyorum. Chrome CORS Eklentisini kullanmayı da denedim, ancak o zaman başka bir hata mesajı alıyorum:
Yanıttaki 'Access-Control-Allow-Origin' başlığının değeri istek'kimlik bilgileri modu olduğunda '*' joker karakteri olmamalıdır 'şunları içerir'. Köken 'http://127.0.0.1:3000' bu nedenle izin verilmez erişim. tarafından başlatılan isteklerin kimlik bilgileri modu XMLHttpRequest, withCredentials niteliği tarafından kontrol edilir.
Bu cevap çok geniş bir alanı kapsamaktadır, bu nedenle üç bölüme ayrılmıştır:
*"Access-Control-Allow-Origin başlığı yok " sorunlarını aşmak için bir CORS proxy'si nasıl kullanılır**
Ön uç JavaScript kodunuzun istek gönderdiği sunucuyu kontrol etmiyorsanız ve bu sunucudan gelen yanıtla ilgili sorun yalnızca gerekli Access-Control-Allow-Origin
başlığının olmamasıysa, isteği bir CORS proxy aracılığıyla yaparak yine de işlerin yürümesini sağlayabilirsiniz. Bunun nasıl çalıştığını göstermek için, önce CORS proxy kullanmayan bazı kodları burada bulabilirsiniz:
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Catchbloğunun oraya çarpmasının nedeni, tarayıcının bu kodun
https://example.comadresinden geri gelen yanıta erişmesini engellemesidir. Tarayıcının bunu yapmasının nedeni, yanıtın
Access-Control-Allow-Origin` yanıt başlığından yoksun olmasıdır.
Şimdi, burada tam olarak aynı örnek var ama sadece bir CORS proxy eklenmiş:
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Not: Eğer https
https://example.com
adresine yönlendirir.https://example.com
adresinden alır.Access-Control-Allow-Origin
başlığını ekler.Access-Control-Allow-Origin
yanıt başlığını içeren bu yanıt tarayıcının gördüğü yanıttır.
https://github.com/Rob--W/cors-anywhere/.<br> adresindeki kodu kullanarak kendi proxy'nizi kolayca çalıştırabilirsiniz;
Ayrıca kendi proxy'nizi Heroku'ya sadece 2-3 dakika içinde 5 komutla kolayca dağıtabilirsiniz:git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
https://cors-anywhere.herokuapp.com' eklemek yerine, kendi örneğinizin URL'sini ekleyin; örneğin, https://cryptic-headland-94862.herokuapp.com/https://example.com. **https<nolink>://cors-anywhere.herokuapp.com adresini kullanmaya çalıştığınızda kapalı olduğunu görürseniz** (ki bazen olur), o zaman bir Heroku hesabı almayı düşünün (henüz almadıysanız) ve Heroku'da kendi CORS Anywhere sunucunuzu dağıtmak için yukarıdaki adımları uygulamak üzere 2 veya 3 dakikanızı ayırın. İster kendi sunucunuzu çalıştırın, ister https://cors-anywhere.herokuapp.com veya başka bir açık proxy kullanın, bu çözüm, istek tarayıcıları CORS ön kontrol
OPTIONSisteği yapmaya tetikleyen bir istek olsa bile çalışacaktır - çünkü bu durumda proxy, ön kontrolün başarılı olması için gereken
Access-Control-Allow-Headersve
Access-Control-Allow-Methods` başlıklarını da geri gönderir. CORS ön uçuşundan nasıl kaçınılır
Sorudaki kod, bir Authorization
başlığı gönderdiği için bir CORS ön kontrolünü tetikler.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Bu olmasa bile, Content-Type: application/json
başlığı da ön kontrolü tetikleyecektir.
"Ön kontrol" ne anlama gelir: tarayıcı sorudaki koddaki POST
u denemeden önce, sunucunun Authorization
ve Content-Type: application/json
başlıklarını içeren çapraz kaynaklı bir POST
almayı kabul edip etmediğini belirlemek için sunucuya bir OPTIONS
isteği gönderir.
Küçük bir curl betiği ile oldukça iyi çalışıyor - verilerimi alıyorum. curl
ile düzgün bir şekilde test etmek için, tarayıcının gönderdiği preflight
OPTIONS` isteğini taklit etmeniz gerekir:
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
...https://the.sign_in.url
yerine gerçek sign_in
URL'niz ne ise o yazılır.
Tarayıcının bu OPTIONS
isteğinden görmesi gereken yanıt aşağıdaki gibi başlıklar içermelidir:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
Eğer OPTIONS' yanıtı bu başlıkları içermiyorsa, tarayıcı burada duracak ve
POST' isteğini göndermeyi asla denemeyecektir. Ayrıca, yanıt için HTTP durum kodu 2xx (genellikle 200 veya 204) olmalıdır. Eğer başka bir durum kodu ise, tarayıcı orada duracaktır.
Sorudaki sunucu OPTIONS' isteğine 501 durum koduyla yanıt veriyor, bu da görünüşe göre
OPTIONS' istekleri için destek uygulamadığını belirtmeye çalıştığı anlamına geliyor. Diğer sunucular bu durumda genellikle 405 "Method not allowed" durum koduyla yanıt verir.
Dolayısıyla, sunucu OPTIONS
isteğine 405 veya 501 ya da 200 veya 204 dışında bir yanıt verirse veya bu gerekli yanıt başlıklarıyla yanıt vermezse, ön uç JavaScript kodunuzdan doğrudan bu sunucuya POST
istekleri yapamazsınız.
Sorudaki durum için bir ön kontrol tetiklemekten kaçınmanın yolu şöyle olacaktır:
Yetkilendirme
istek başlığı gerektirmiyorsa, bunun yerine (örneğin) POST
isteğinin gövdesine veya bir sorgu parametresi olarak gömülü kimlik doğrulama verilerine güveniyorsaPOST
gövdesinin bir Content-Type: application/json
medya türüne sahip olmasını gerektirmiyorsa, bunun yerine POST
gövdesini değeri JSON verisi olan json
(veya başka bir şey) adlı bir parametre ile application/x-www-form-urlencoded
olarak kabul ediyorsa*"Access-Control-Allow-Origin başlığı joker karakter olmamalıdır " sorunları nasıl düzeltilir**
Başka bir hata mesajı alıyorum:
Yanıttaki 'Access-Control-Allow-Origin' başlığının değeri istek'kimlik bilgileri modu olduğunda '' joker karakteri olmamalıdır 'şunları içerir'. Köken 'http://127.0.0.1:3000' bu nedenle izin verilmez erişim. tarafından başlatılan isteklerin kimlik bilgileri modu XMLHttpRequest withCredentials niteliği tarafından kontrol edilir. Kimlik bilgilerini içeren bir istek için,
Access-Control-Allow-Origin
yanıt üstbilgisinin değeri `ise, tarayıcılar ön uç JavaScript kodunuzun yanıta erişmesine izin vermez. Bunun yerine, bu durumda değer ön uç kodunuzun kaynağı olan
http://127.0.0.1:3000ile tam olarak eşleşmelidir. MDN HTTP erişim denetimi (CORS) makalesinde [*Credentialed requests and wildcards*][1] bölümüne bakın. İsteği gönderdiğiniz sunucuyu kontrol ediyorsanız, bu durumla başa çıkmanın yaygın bir yolu, sunucuyu
Originistek başlığının değerini alacak ve bunu
Access-Control-Allow-Origin` yanıt başlığının değerine geri yansıtacak/yansıtacak şekilde yapılandırmaktır. Örneğin, nginx ile:
add_header Access-Control-Allow-Origin $http_origin
Chrome kullanıyorum. Ayrıca şu Chrome CORS Eklentisini kullanmayı da denedim Chrome CORS eklentisi görünüşe göre basit bir şekilde
Access-Control-Allow-Origin' enjekte ediyor: *
başlığını tarayıcının gördüğü yanıta enjekte ediyor. Eğer eklenti daha akıllı olsaydı, yaptığı şey bu sahteAccess-Control-Allow-Origin
yanıt başlığının değerini ön uç JavaScript kodunuzun gerçek kaynağı olanhttp://127.0.0.1:3000
olarak ayarlamak olurdu. Bu yüzden test için bile olsa bu eklentiyi kullanmaktan kaçının. Bu sadece dikkat dağıtıcıdır. Tarayıcı filtrelemesi olmadan sunucudan aldığınız yanıtları test etmek istiyorsanız, yukarıdaki gibicurl -H
kullanmanız daha iyi olacaktır.Sorudaki
fetch(...)
isteği için ön uç JavaScript koduna gelince:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Şu çizgileri kaldırın. Erişim Kontrolü İzin Ver- başlıkları yanıt* başlıklarıdır. Bunları asla bir istek içinde göndermek istemezsiniz. Bunun tek etkisi bir tarayıcıyı ön kontrol yapması için tetiklemek olacaktır.
Bu hata, port numarası da dahil olmak üzere istemci URL'si ve sunucu URL'si eşleşmediğinde ortaya çıkar. Bu durumda, çapraz kaynak paylaşımı olan CORS için hizmetinizi etkinleştirmeniz gerekir.
Bir Spring REST hizmeti barındırıyorsanız, bunu Spring Framework'te CORS desteği blog yazısında bulabilirsiniz.
Node.js sunucusu kullanarak bir hizmet barındırıyorsanız
Node.js sunucusunu durdurun.
npm install cors --save
Aşağıdaki satırları server.js dosyanıza ekleyin
var cors = require('cors')
app.use(cors()) // Bunu değişken bildiriminden sonra kullanın