- Konu sahibi
- #1
JavaScript’te CORS hatası, tarayıcının bir web sayfasının farklı bir kaynakta bulunan API’ye erişmesine izin vermemesiyle oluşur. Çözüm, JavaScript kodunu zorlayarak tarayıcı güvenliğini aşmak değil, API sunucusunun isteği gönderen kaynağa uygun CORS yanıt başlıklarını döndürmesini sağlamaktır. Geliştirme ortamında istemci adresini sunucuda izin verilen kaynak olarak tanımlayın; üretimde ise yalnızca gerçekten kullanacağınız alan adlarına izin verin.
Tarayıcı geliştirici araçlarında Network veya Console bölümünü açıp başarısız isteği inceleyin. Hata genellikle şu anlama gelir: API yanıtında
Kaynak; protokol, alan adı ve portun birlikte oluşturduğu adrestir. Örneğin
CORS hatası yalnızca tarayıcıdaki çapraz kaynak erişimini sınırlar. İsteği Postman veya cURL ile gönderebilmeniz, tarayıcıdaki JavaScript kodunun da erişebileceğini kanıtlamaz; bu araçlar aynı tarayıcı güvenlik politikasını uygulamaz.
API sizin kontrolünüzdeyse, sunucunun istemcinin gerçek kaynağını kabul etmesini sağlayın. Örneğin istemci
Bu örnekte tarayıcıdaki uygulama
Sunucuyu yeniden başlatıp isteği tekrar gönderdiğinizde yanıt tarayıcıya ulaşırsa CORS sorunu çözülmüştür. Network bölümünde API yanıtının
CORS ayarının yeri kullandığınız sunucu teknolojisine göre değişir. Amaç her durumda aynıdır: İstek kaynağını, HTTP yöntemini ve gerekiyorsa özel başlıkları sunucunun kabul etmesini sağlamak.
İstemci
Oturum çerezi gönderilecekse istemci isteğinde kimlik bilgilerini açıkça belirtin:
Sunucu da
JavaScript içinde
Tarayıcı eklentisiyle CORS denetimini kapatmak da yalnızca kendi bilgisayarınızdaki geçici geliştirme testi için kullanılabilir. Kullanıcıların tarayıcı ayarını değiştirmesini gerektiren bir uygulama yayımlanamaz. Üretim çözümü API sunucusunda veya kendi sunucunuzdaki güvenilir bir ara katmanda yapılmalıdır.
API size ait değilse ve karşı taraf CORS izni vermiyorsa, doğrudan tarayıcıdan istek göndermek yerine sunucu tarafında bir proxy kullanabilirsiniz. Tarayıcı kendi sunucunuza istek gönderir; kendi sunucunuz da API’ye sunucu-sunucu bağlantısı kurup gerekli veriyi döndürür. Proxy, erişim yetkisini veya API anahtarını kullanıcıya açmamalı; gelen adresleri sınırsız biçimde başka sunuculara aktaran açık bir yönlendiriciye dönüştürülmemelidir.
Son kontrol sırasında şu ayrımı yapın:
Önce hatanın nerede oluştuğunu belirleyin
Tarayıcı geliştirici araçlarında Network veya Console bölümünü açıp başarısız isteği inceleyin. Hata genellikle şu anlama gelir: API yanıtında
Access-Control-Allow-Origin başlığı yoktur, değeri mevcut sayfanın kaynağıyla eşleşmiyordur ya da tarayıcı önce yaptığı ön kontrol isteğine (OPTIONS) beklenen yanıtı alamıyordur.Kaynak; protokol, alan adı ve portun birlikte oluşturduğu adrestir. Örneğin
http://localhost:3000 ile http://localhost:5173 farklı kaynaklardır. Bu nedenle API localhost:8000 üzerinde çalışsa bile, istemcinin çalıştığı port için ayrıca izin gerekebilir.CORS hatası yalnızca tarayıcıdaki çapraz kaynak erişimini sınırlar. İsteği Postman veya cURL ile gönderebilmeniz, tarayıcıdaki JavaScript kodunun da erişebileceğini kanıtlamaz; bu araçlar aynı tarayıcı güvenlik politikasını uygulamaz.
Çözüm sunucuda yapılır
API sizin kontrolünüzdeyse, sunucunun istemcinin gerçek kaynağını kabul etmesini sağlayın. Örneğin istemci
http://localhost:3000 adresinde, API ise Node.js ve Express üzerinde çalışıyorsa CORS ara yazılımını sunucuya ekleyebilirsiniz:
JavaScript:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({
origin: 'http://localhost:3000',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
app.get('/api/veriler', (req, res) => {
res.json({ mesaj: 'İstek kabul edildi' });
});
app.listen(8000, () => {
console.log('API 8000 portunda çalışıyor');
});
Bu örnekte tarayıcıdaki uygulama
http://localhost:3000 adresinden http://localhost:8000/api/veriler adresine istek gönderebilir. İstemci kodu şöyle olabilir:
JavaScript:
fetch('http://localhost:8000/api/veriler')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP hatası: ${response.status}`);
}
return response.json();
})
.then(veri => console.log(veri))
.catch(hata => console.error(hata));
Sunucuyu yeniden başlatıp isteği tekrar gönderdiğinizde yanıt tarayıcıya ulaşırsa CORS sorunu çözülmüştür. Network bölümünde API yanıtının
Access-Control-Allow-Origin: http://localhost:3000 başlığını içerdiğini de kontrol edebilirsiniz. Bu başlığın görünmesi tek başına API’nin doğru veri döndürdüğünü kanıtlamaz; yalnızca tarayıcının yanıtı istemci koduna açmasına izin verildiğini gösterir.Kullanılan teknolojiye göre temel ayar
CORS ayarının yeri kullandığınız sunucu teknolojisine göre değişir. Amaç her durumda aynıdır: İstek kaynağını, HTTP yöntemini ve gerekiyorsa özel başlıkları sunucunun kabul etmesini sağlamak.
| Durum | Sunucuda yapılacak işlem | Dikkat edilecek nokta |
|---|---|---|
| Basit GET isteği | Yanıta uygun Access-Control-Allow-Origin başlığı eklenir | Değer, sayfanın gerçek kaynağıyla eşleşmelidir |
| POST, PUT veya DELETE isteği | Kullanılan yöntemler CORS yapılandırmasına eklenir | Sunucu yöntemi gerçekten işliyor olmalıdır |
| Authorization veya özel Content-Type | İzin verilen başlıklara eklenir | Ön kontrol OPTIONS isteği de yanıtlanmalıdır |
| Çerez veya oturum bilgisi | İstemci ve sunucuda kimlik bilgisi gönderimi etkinleştirilir | Allow-Origin değeri yıldız (*) olamaz |
Authorization gibi özel bir başlık gönderiyorsa tarayıcı çoğu durumda önce OPTIONS isteği yapar. Sunucu bu isteğe başarılı bir HTTP durum kodu ve gerekli CORS başlıklarıyla yanıt vermelidir. OPTIONS isteği 404, 405 veya 500 dönüyorsa asıl GET ya da POST isteği çalışmadan engellenebilir.Çerez ve kimlik doğrulama kullanılıyorsa
Oturum çerezi gönderilecekse istemci isteğinde kimlik bilgilerini açıkça belirtin:
JavaScript:
fetch('https://api.ornek.com/profil', {
credentials: 'include'
});
Sunucu da
Access-Control-Allow-Credentials: true göndermelidir. Bu durumda Access-Control-Allow-Origin: * kullanılamaz; sunucu belirli istemci kaynağını açıkça belirtmelidir. Çerezlerin SameSite, Secure ve alan adı ayarları da ayrıca uygun olmalıdır. CORS başlıkları doğru olsa bile çerez politikası uygun değilse oturum bilgisi gönderilmeyebilir.Çalışmayan yaklaşımlar ve doğru sonraki adım
JavaScript içinde
mode: 'no-cors' kullanmak genel bir çözüm değildir. İstek gönderilebilir ancak yanıt çoğunlukla opak olur; JavaScript yanıt gövdesini ve normal HTTP bilgilerini okuyamaz. Bu seçenek, API verisini uygulama içinde kullanabilmeniz için CORS sorununu çözmez.Tarayıcı eklentisiyle CORS denetimini kapatmak da yalnızca kendi bilgisayarınızdaki geçici geliştirme testi için kullanılabilir. Kullanıcıların tarayıcı ayarını değiştirmesini gerektiren bir uygulama yayımlanamaz. Üretim çözümü API sunucusunda veya kendi sunucunuzdaki güvenilir bir ara katmanda yapılmalıdır.
API size ait değilse ve karşı taraf CORS izni vermiyorsa, doğrudan tarayıcıdan istek göndermek yerine sunucu tarafında bir proxy kullanabilirsiniz. Tarayıcı kendi sunucunuza istek gönderir; kendi sunucunuz da API’ye sunucu-sunucu bağlantısı kurup gerekli veriyi döndürür. Proxy, erişim yetkisini veya API anahtarını kullanıcıya açmamalı; gelen adresleri sınırsız biçimde başka sunuculara aktaran açık bir yönlendiriciye dönüştürülmemelidir.
Son kontrol sırasında şu ayrımı yapın:
- Yanıtta CORS başlığı yoksa veya kaynak eşleşmiyorsa sunucunun izin verilen kaynak ayarını düzeltin.
- OPTIONS isteği başarısızsa preflight yönlendirmesini, HTTP yöntemlerini ve özel başlık izinlerini kontrol edin.
- CORS başlıkları doğru olduğu hâlde 401 veya 403 alıyorsanız sorun artık CORS değil, kimlik doğrulama ya da yetkilendirmedir.
- Sunucu 500 döndürüyorsa önce sunucu hatasını çözün; CORS mesajı asıl uygulama hatasını gizliyor olabilir.
- İstek başarılı görünüyor fakat çerez gitmiyorsa credentials ve çerez politikalarını birlikte inceleyin.
localhost kaynağını bırakıp gerçek istemci alan adını açıkça tanımlayın. Geliştirme kolaylığı için tüm kaynaklara * izni vermek, özellikle kimlik doğrulamalı API’lerde güvenli bir üretim yapılandırması değildir.