Kurumsal Yazılım
CORS hatası nasıl çözülür? Adım adım rehber

Kısa yanıt
CORS hatası, tarayıcının farklı bir alan adına (origin) gönderdiği bir isteğin yanıtını, sunucu buna açıkça izin vermediği için JavaScript koduna göstermemesidir; bu bir bağlantı kopması değil, tarayıcının aynı-köken güvenlik politikasının bilinçli bir uyarısıdır. Çözüm hemen hemen her zaman frontend tarafında değil, API’yi sunan backend’de doğru Access-Control-Allow-Origin başlığını döndürmektir.
CORS hatası neden oluşur ve mantığı nedir?
Tarayıcılar, varsayılan olarak bir sayfadaki JavaScript kodunun başka bir origin’e (farklı şema, alan adı veya port) istek göndermesine izin verir, ancak bu isteğin yanıtını okumasına izin vermez; bu kural aynı-köken politikası (same-origin policy) olarak bilinir. CORS (Cross-Origin Resource Sharing), sunucunun “bu origin’den gelen isteklerin yanıtımı okumasına izin veriyorum” demesini sağlayan bir mekanizmadır. Sunucu bu izni özel HTTP başlıklarıyla vermezse, tarayıcı isteği engellemez ama yanıtı kodunuzdan gizler ve konsola CORS hatası basar.
Bu ayrım pratikte çok önemlidir: istek sunucuya genellikle ulaşır, sunucu da yanıtı üretir; sorun ağ katmanında değil, tarayıcının yanıtı size göstermeyi reddetmesindedir. Bu yüzden bir CORS hatasıyla karşılaşan geliştiricilerin ilk refleksi genellikle “sunucum çalışmıyor” olur, ama gerçek neden hemen hemen her zaman eksik veya yanlış yapılandırılmış bir CORS başlığıdır. Frontend’deki fetch veya axios çağrısını değiştirmek, kodu sunucudan ayrı bir origin’de barındırdığınız sürece bu hatayı çözmez.
CORS hatası özellikle şu senaryolarda sık görülür: frontend localhost:3000’de çalışırken API localhost:8000’de veya farklı bir alan adında barındırıldığında; bir mobil uygulamanın web görünümü ayrı bir domain üzerinden API çağırdığında; ya da bir WordPress sitesinin headless bir frontend’e (Next.js, React gibi) REST API üzerinden veri sağladığında. Port numarası farklı olsa bile tarayıcı bunu ayrı bir origin sayar; http://site.com ile https://site.com da birbirinden farklı origin’dir.
Tarayıcı konsolunda hangi mesajları görürsünüz?
| Mesaj | Tipik neden | İlk çözüm |
|---|---|---|
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource |
Sunucu hiç CORS başlığı döndürmüyor | Backend’e doğru Access-Control-Allow-Origin başlığını ekleyin |
Response to preflight request doesn't pass access control check |
OPTIONS (preflight) isteğine doğru yanıt verilmiyor | Sunucunun OPTIONS’u 200/204 ve doğru başlıklarla yanıtlamasını sağlayın |
...must not be the wildcard '*' when the request's credentials mode is 'include' |
credentials: 'include' ile wildcard origin birlikte kullanılıyor |
Wildcard yerine isteğin geldiği origin’i açıkça döndürün |
No 'Access-Control-Allow-Headers' header is present |
İstekte özel bir başlık (ör. Authorization) var ama sunucu izin vermiyor |
İlgili başlığı Access-Control-Allow-Headers listesine ekleyin |
net::ERR_FAILED (CORS mesajı hiç görünmüyor) |
İstek sunucuya hiç ulaşmadı (DNS, SSL, yanlış port) | Önce bunun CORS değil bağlantı hatası olduğunu doğrulayın |
CORS hatası nasıl çözülür?
1. Hatanın gerçekten CORS olduğunu doğrulayın
Tarayıcının geliştirici araçlarında Network sekmesini açın ve ilgili isteğe bakın. İstek kırmızı görünüyor ve durum kodu hiç yoksa (örneğin (failed)), sorun büyük olasılıkla CORS değil; DNS, SSL sertifikası veya yanlış bir adres/port olabilir. İstek gerçekten sunucuya ulaşıp bir yanıt almışsa ama konsolda CORS ibaresi geçen kırmızı bir mesaj varsa, probleminiz kesinlikle CORS yapılandırmasıdır ve çözüm sunucu tarafındadır.
2. Backend’de doğru Access-Control-Allow-Origin başlığını ekleyin
Node.js/Express kullanan bir API için en basit çözüm cors paketini eklemektir:
Const cors = require('cors');
App.use(cors({ origin: 'https://siteniz.com' }));
Nginx gibi bir ters proxy kullanıyorsanız başlığı sunucu seviyesinde de ekleyebilirsiniz:
Add_header 'Access-Control-Allow-Origin' 'https://siteniz.com' always;
Üretim ortamında origin’i * yerine gerçek alan adınızla sınırlı tutmak, hem güvenlik hem de credentials kullanan isteklerin çalışması için gereklidir.
3. Preflight (OPTIONS) isteğini doğru yanıtlayın
PUT, DELETE, özel başlıklar veya application/json gövdesi taşıyan istekler “basit olmayan” istek sayılır ve tarayıcı önce otomatik bir OPTIONS isteği gönderir. Sunucunuz bu isteğe Access-Control-Allow-Methods ve Access-Control-Allow-Headers başlıklarıyla, genellikle 200 veya 204 durum koduyla yanıt vermelidir; aksi halde tarayıcı asıl isteği hiç göndermeden konsola preflight hatası basar. Bu adım, API’nizi Postman’de test ettiğinizde her şeyin doğru görünmesine ama tarayıcıda hata vermesine neden olan en yaygın sebeptir, çünkü Postman preflight isteği göndermez.
4. Credentials (çerez/oturum) kullanıyorsanız wildcard’dan kaçının
İstekte credentials: 'include' kullanıyorsanız (çerez tabanlı oturum, HttpOnly cookie gibi), sunucunun Access-Control-Allow-Origin başlığında * döndürmesi tarayıcı tarafından geçersiz sayılır; başlıkta isteğin geldiği gerçek origin’in açıkça yazılması ve Access-Control-Allow-Credentials: true başlığının eklenmesi gerekir. Bu ikisini birlikte unutmak, oturum tabanlı API’lerde en sık rastlanan CORS hatasıdır.
Geliştirme ortamında hızlı çözüm: proxy kullanmak
Yerel geliştirme sırasında backend’i değiştirme yetkiniz yoksa veya henüz hazır değilse, frontend tarafında bir geliştirme proxy’si kullanmak pratik bir ara çözümdür. Vite’ta vite.config.js içindeki server.proxy ayarı, webpack’te devServer.proxy ayarı, tarayıcı isteklerini kendi origin’inizden gönderiyormuş gibi gösterip arka planda gerçek API’ye yönlendirir; bu sayede tarayıcı CORS kontrolü yapmaz. Bu çözüm yalnızca geliştirme ortamı içindir; üretimde gerçek çözüm her zaman sunucudaki CORS başlıklarını doğru yapılandırmaktır.
WordPress ve headless projelerde CORS hatası
Bir WordPress sitesini REST API üzerinden ayrı bir frontend’e (Next.js, React, mobil uygulama) veri sağlayan headless bir mimaride kullandığınızda, WordPress çekirdeği varsayılan olarak her origin’e CORS izni vermez. Çözüm, temanın functions.php dosyasında veya küçük bir eklentide rest_api_init kancasına bağlanıp ilgili isteklerde Access-Control-Allow-Origin başlığını elle eklemektir; bazı hosting ortamlarında bu başlığı .htaccess veya sunucu yapılandırmasından eklemek daha güvenilir sonuç verir. Bu konuda WordPress’in kendi hata senaryolarını WordPress veritabanı bağlantısı kurulamadı hatası rehberimizde de ele alıyoruz; CORS, veritabanı hatasından farklı olarak sunucu tamamen çalışırken ortaya çıkan bir yetkilendirme meselesidir.
Güvenlik açısından yapılmaması gerekenler
CORS hatasıyla karşılaşan bazı geliştiriciler, soruna gerçekten bakmadan Access-Control-Allow-Origin: * ile tüm origin’lere izin vermeyi veya tarayıcıda CORS kontrolünü devre dışı bırakan bir eklenti kullanmayı tercih eder. İlki, kimlik doğrulaması gerektiren veya hassas veri döndüren bir API’de güvenlik açığına dönüşebilir; API’niz hangi sitelerin ona istek atabileceğini kontrol edemez hale gelir. İkincisi ise yalnızca sizin tarayıcınızda sorunu gizler, gerçek kullanıcıların tarayıcısında hata devam eder; bu yüzden üretimde asla gerçek bir çözüm sayılmamalıdır.
Sık yapılan hatalar
En yaygın hata, hatayı okumadan frontend kodunu değiştirmeye çalışmaktır; CORS başlıkları sunucu tarafında eklenir, istemci kodunda değil. İkinci sık hata, geliştirme ortamındaki geçici bir proxy veya tarayıcı eklentisi çözümünü üretime taşımaktır. Üçüncüsü, credentials kullanan bir API’de wildcard origin denemektir; bu kombinasyon tarayıcı tarafından doğrudan reddedilir ve hiçbir zaman çalışmaz. Son olarak, preflight isteğini unutup yalnızca asıl isteğe CORS başlığı eklemek de sorunu yarım çözer.
Kontrol listesi
Network sekmesinde isteğin sunucuya gerçekten ulaşıp ulaşmadığını kontrol ederek başlayın. Konsoldaki mesajın hangi başlıktan (origin, headers, credentials) bahsettiğini tam olarak okuyun. Backend’in Access-Control-Allow-Origin başlığını doğru origin ile döndürdüğünü doğrulayın. Basit olmayan isteklerde OPTIONS yanıtının doğru metot ve başlıklarla geldiğini test edin. Credentials kullanıyorsanız wildcard yerine açık origin ve Access-Control-Allow-Credentials: true kullandığınızı teyit edin.
Sonraki adım
CORS hatası, tarayıcının sizi korumaya çalıştığının bir göstergesidir ve doğru başlıklarla genellikle dakikalar içinde çözülür; kritik olan, sorunu frontend’de değil backend’de aramaktır. Şirketinizin API entegrasyonlarını, headless mimarilerini veya mevcut sistemlerle veri alışverişini profesyonel bir altyapıya oturtmak isterseniz, grup şirketimiz Web Tasarım Ofisi bu tür teknik entegrasyon projelerinde uçtan uca destek sağlıyor.
Benzer bağlantı ve dağıtım sorunlarını çözüme kavuşturan ekip desteği için özel yazılım hizmetimizi inceleyebilir ya da bizimle iletişime geçebilirsiniz. Kod gönderimi sırasında karşılaşabileceğiniz farklı bir teknik pürüzü ise git push rejected hatası nasıl çözülür rehberimizde ele alıyoruz.
Kaynaklar
- MDN Web Docs, Cross-Origin Resource Sharing (CORS), CORS mekanizmasının ve ilgili HTTP başlıklarının resmî teknik açıklaması
Sıkça sorulan sorular
CORS hatası tam olarak ne anlama gelir?
Tarayıcınızın, farklı bir alan adına (origin) yaptığı isteğin yanıtını okumasına izin verilmediği anlamına gelir. İstek genellikle sunucuya ulaşır ve sunucu yanıt da üretir; engellenen şey ağ trafiği değil, tarayıcının o yanıtı JavaScript koduna göstermesidir.
Access-Control-Allow-Origin: * kullanmak güvenli mi?
Herkese açık, kimlik doğrulaması gerektirmeyen bir API için genellikle sorun yaratmaz. Ancak istek çerez veya oturum bilgisi taşıyorsa (credentials: 'include'), tarayıcı wildcard origin'i kabul etmez ve isteği doğrudan reddeder; bu durumda origin'i açıkça belirtmeniz gerekir.
Preflight (OPTIONS) isteği nedir, neden CORS hatasına yol açar?
Tarayıcı, basit olmayan isteklerden (özel başlık taşıyan, PUT/DELETE kullanan veya JSON gövdesi gönderen istekler) önce sunucuya otomatik bir OPTIONS isteği gönderir. Sunucu bu isteğe doğru başlıklarla yanıt vermezse tarayıcı asıl isteği hiç göndermez ve konsolda preflight hatası görürsünüz.
CORS hatası yalnızca tarayıcıda mı görülür?
Evet. CORS tamamen tarayıcı tarafında uygulanan bir güvenlik mekanizmasıdır; Postman, cURL veya sunucudan sunucuya yapılan bir istek CORS kısıtlamasına tabi değildir. Bu yüzden bir API'nin Postman'de çalışıp tarayıcıda çalışmaması CORS hatasının en tipik belirtisidir.
WordPress REST API'de CORS hatası nasıl çözülür?
Genellikle tema veya eklenti içindeki rest_api_init kacasına bağlanıp ilgili isteklerde Access-Control-Allow-Origin başlığını elle eklemek gerekir; sunucu seviyesinde .htaccess veya Nginx üzerinden de aynı başlık eklenebilir. Çözüm sitede değil, sunucu veya hosting yapılandırmasındadır.