Berk Akademi
Ana Sayfa
ÖZEL KODLAMA DERSLERİ
Yazılım Özel Ders
Tüm birebir programlara genel bakış
Python Yazılım Kursu
Sıfırdan ileri seviyeye birebir Python
Java Yazılım Kursu
OOP odaklı birebir Java eğitimi
AP Computer Science Principles
AP CSP sınav hazırlığı
GRUP DERSLERİ
Python & Django Masterclass
SINIRLI KONTENJAN
Java & Spring Boot Masterclass
SINIRLI KONTENJAN
C# .NET Masterclass
SINIRLI KONTENJAN
VİDEO DERSLER
Sıfırdan Temel Python Kursu
Kendi Hızında Öğren
ÜCRETSİZ
Seviye Testi
Ücretsiz — Python, Java, algoritma seviye testleri
Kariyerini Keşfet
Sertifika Doğrula
Belge numarası ve soyad ile doğrulama

“Blocked by CORS Policy” Hatası: Nedenleri ve Backend Çözümü

blocked-by-cors-policy-hatasi-backend-cozumu
Bu yazıda neler var?
  1. “Blocked by CORS Policy” Hatası Kısaca Ne Anlama Gelir?
  2. CORS ve Same-Origin Policy Neden Gereklidir?
  3. CORS Hatası Hangi İstek Akışında Ortaya Çıkar?
  4. Backend’de CORS Header’ları Adım Adım Nasıl Ayarlanır?
  5. Geliştirme ve Production Ortamında CORS Nasıl Tasarlanır?
  6. CORS Sorunlarında Hızlı Teşhis Kontrol Listesi
  7. Sık Sorulan Sorular

“Blocked by CORS Policy” hatası, frontend uygulamanızın başka bir origin’de bulunan backend API’ye yaptığı isteğin tarayıcı güvenlik kurallarıyla eşleşmediğini gösterir. Sorunun çözümü çoğu zaman frontend kodunda hatayı bastırmak değil, backend’in doğru CORS yanıt header’larını göndermesini sağlamaktır.

Bu hata, backend’in kesinlikle çalışmadığı anlamına gelmez. İstek sunucuya ulaşmış, hatta sunucu doğru bir yanıt üretmiş olabilir; ancak gerekli izin header’ları bulunmadığı için tarayıcı bu yanıtı frontend JavaScript koduna açmayabilir. Teşhis ederken şu akışı izlemek gerekir: tarayıcı güvenlik kontrolü → gerekiyorsa OPTIONS isteği → gerçek istek → response header kontrolü → frontend erişimi.

“Blocked by CORS Policy” Hatası Kısaca Ne Anlama Gelir?

CORS, farklı origin’ler arasında yapılan tarayıcı isteklerinin hangi koşullarda okunabileceğini belirleyen mekanizmadır. Örneğin bir frontend uygulaması http://localhost:3000 adresinde, backend API ise http://localhost:5000 adresinde çalışıyorsa tarayıcı bu iki adresi farklı origin olarak değerlendirir.

Frontend JavaScript kodu API’ye istek gönderdiğinde tarayıcı, backend yanıtında kendisine izin verilip verilmediğini kontrol eder. Backend yanıtında uygun Access-Control-Allow-Origin header’ı yoksa veya gönderilen istek türü için gerekli diğer CORS header’ları bulunmuyorsa tarayıcı yanıtı JavaScript koduna kullandırmaz.

Bu nedenle konsolda şu tür mesajlarla karşılaşabilirsiniz:

  • Access to fetch at ... has been blocked by CORS policy
  • No 'Access-Control-Allow-Origin' header is present on the requested resource
  • Response to preflight request doesn't pass access control check
  • Request header field ... is not allowed by Access-Control-Allow-Headers

Bu mesajların ortak noktası, tarayıcının frontend koduna “Bu yanıtı güvenlik kuralları nedeniyle okuyamazsın.” demesidir. Bu, ağ bağlantısının kesinlikle kurulmadığını veya backend uygulamasının çöktüğünü tek başına kanıtlamaz.

Backend çalışıyor olsa bile neden hata görülebilir?

Bir API endpoint’ini doğrudan tarayıcı adres çubuğunda açtığınızda yanıt görebilirsiniz. Ancak bu durum, frontend JavaScript kodunun aynı yanıtı okuyabileceği anlamına gelmez. Adres çubuğundan yapılan gezinme ile JavaScript tarafından yapılan çapraz origin isteği, tarayıcı açısından aynı işlem değildir.

Örneğin backend şu yanıtı üretiyor olabilir:

{
  "message": "İstek başarıyla işlendi"
}

Fakat yanıt header’ları içinde frontend origin’ine izin veren bir tanım yoksa tarayıcı bu JSON verisini fetch veya Axios kullanan JavaScript koduna teslim etmeyebilir. Geliştiricinin Network sekmesinde isteği görmesi, isteğin frontend tarafından okunabildiği anlamına gelmez.

Bu ayrım, CORS hatası çözerken en önemli teşhis noktalarından biridir:

  • Sunucu hatası: Backend isteği işleyememiş olabilir; 4xx veya 5xx yanıt dönebilir.
  • Ağ hatası: Alan adı çözümlenemeyebilir, port kapalı olabilir veya sunucuya ulaşılamayabilir.
  • CORS hatası: Sunucu yanıt vermiş olsa bile tarayıcı yanıtın frontend kodu tarafından okunmasına izin vermeyebilir.

Pratik CORS teşhis akışı

“Blocked by CORS Policy” mesajını gördüğünüzde doğrudan frontend tarafında değişiklik yapmak yerine aşağıdaki sırayla ilerleyin:

  1. İsteğin hangi frontend origin’inden gönderildiğini belirleyin. Protokol, alan adı ve port bilgisini birlikte kontrol edin.
  2. Tarayıcının Developer Tools bölümünde Network sekmesini açın ve başarısız isteği bulun.
  3. İstekten önce bir OPTIONS isteği gönderilip gönderilmediğini kontrol edin.
  4. Backend yanıt header’larında Access-Control-Allow-Origin değerini arayın.
  5. İstek özel header, yöntem veya kimlik bilgisi kullanıyorsa ilgili CORS izinlerinin de tanımlı olup olmadığını inceleyin.
  6. Backend’in doğrudan verdiği durum kodu ile tarayıcının frontend’e gösterdiği hatayı birbirinden ayırın.

Özellikle OPTIONS isteğinin başarısız olması, gerçek GET, POST, PUT veya DELETE isteğine geçilmeden önce tarayıcının izin kontrolünde durduğunu gösterebilir. Bu durumda yalnızca gerçek endpoint’in yanıtını incelemek yeterli olmaz; preflight yanıtının header’ları da kontrol edilmelidir.

CORS ve Same-Origin Policy Neden Gereklidir?

CORS ve Same-Origin Policy Neden Gereklidir?

CORS’u anlamak için önce origin kavramını bilmek gerekir. Bir web adresinin origin’i üç temel bileşenden oluşur:

  • Protokol: http veya https
  • Alan adı: example.com, localhost gibi host bilgisi
  • Port: 80, 443, 3000, 5000 gibi bağlantı noktası

Bu üç bileşenden biri değiştiğinde origin de değişir. Örneğin http://localhost:3000 ile http://localhost:5000 aynı bilgisayarda ve aynı alan adı üzerinde çalışsa bile portları farklı olduğu için farklı origin kabul edilir.

Adres çifti Origin durumu Neden
http://localhost:3000 ve http://localhost:5000 Farklı origin Port farklı
http://site.com ve https://site.com Farklı origin Protokol farklı
https://app.site.com ve https://api.site.com Farklı origin Alan adı farklı
https://site.com ve https://site.com Aynı origin Protokol, alan adı ve port aynı

Same-origin policy neyi korur?

Same-origin policy, bir web sayfasında çalışan JavaScript kodunun başka bir origin’deki kaynakları kontrolsüz biçimde okuyamamasını amaçlayan tarayıcı güvenlik yaklaşımıdır. Aksi durumda kötü niyetli bir web sayfası, tarayıcınızda açık bulunan başka servislerin yanıtlarını okumaya çalışabilir ve kullanıcı adına erişilen verileri ele geçirebilir.

Örneğin başka bir sitede oturumunuz açıkken ziyaret ettiğiniz farklı bir web sayfasının, bu oturuma ait bilgileri taşıyan istekler gönderip yanıtları okuyabilmesi ciddi bir güvenlik riski oluşturur. Same-origin policy, tarayıcının bu tür çapraz origin okumalarını varsayılan olarak sınırlandırmasına yardımcı olur.

Bu politika, farklı origin’lerin hiçbir şekilde iletişim kuramayacağı anlamına gelmez. Görseller, stil dosyaları, bazı gömülü kaynaklar veya sunucu tarafı iletişim gibi farklı senaryolar kendi kurallarına sahip olabilir. Ancak frontend JavaScript kodunun başka bir origin’den gelen API yanıtını okuyabilmesi için tarayıcının CORS kontrolünden geçmesi gerekir.

CORS kısıtlamayı tamamen kaldırmaz

CORS, same-origin policy’yi tamamen devre dışı bırakan bir yöntem değildir. Daha doğru ifadeyle CORS, sunucunun tarayıcıya hangi origin’lerden gelen isteklerin okunabileceğini bildirdiği bir izin mekanizmasıdır.

Backend, yanıtında belirli bir frontend origin’ine izin verebilir. Bu izin, genellikle Access-Control-Allow-Origin header’ı ile ifade edilir. Tarayıcı, yanıtı değerlendirirken bu header’daki değeri isteği gönderen origin ile karşılaştırır. Değerler uyuşmuyorsa veya gerekli header hiç yoksa frontend kodu yanıtı okuyamaz.

Bu nedenle CORS çözümünün doğru yeri çoğu senaryoda backend yapılandırmasıdır. Frontend’de kullanılan mode: "no-cors" gibi yaklaşımlar, uygulamanın JSON yanıtını normal biçimde okumasını sağlamaz. Benzer şekilde tarayıcı eklentileriyle güvenlik kontrolünü geçici olarak devre dışı bırakmak, gerçek kullanıcıların karşılaşacağı problemi çözmez ve güvenli bir production yaklaşımı değildir.

Özetle, “Blocked by CORS Policy” hatası bir izin uyuşmazlığıdır. Önce isteğin hangi origin’den çıktığını, ardından tarayıcının OPTIONS veya gerçek istek sırasında hangi yanıt header’larını aldığını kontrol etmek gerekir. Bu temel ayrım anlaşıldığında, sorun rastgele frontend değişiklikleriyle değil, ölçülebilir bir istek-yanıt akışı üzerinden teşhis edilebilir.

CORS Hatası Hangi İstek Akışında Ortaya Çıkar?

“Blocked by CORS Policy” hatasını anlamanın en kolay yolu, frontend ve backend’in farklı origin’lerde çalıştığı basit bir senaryoya bakmaktır. Örneğin frontend uygulamanız http://localhost:3000 adresinde, backend API’niz ise http://localhost:5000 adresinde çalışıyor olabilir. Port numaraları farklı olduğu için tarayıcı bu iki adresi farklı origin olarak değerlendirir.

Frontend, backend’e istek gönderdiğinde sunucuya ulaşmak tek başına yeterli değildir. Tarayıcı, backend yanıtında kendisine bu origin’den gelen isteğe izin verildiğini gösteren CORS header’larını arar. Gerekli header’lar yoksa backend isteği işlemiş olsa bile frontend JavaScript kodu yanıtı okuyamaz ve konsolda CORS hatası görülür.

Basit istek ile preflight gerektiren istek arasındaki fark

Her cross-origin istekten önce mutlaka OPTIONS isteği gönderilmez. Bazı istekler tarayıcının “basit istek” olarak değerlendirdiği sınırlı kurallara uyuyorsa doğrudan backend’e gönderilebilir. Örneğin yalnızca standart bir GET isteği göndermek ve özel bir request header kullanmamak çoğu durumda bu kategoriye yakındır.

Ancak istek daha fazla izin gerektiriyorsa tarayıcı önce bir preflight isteği gönderir. Preflight, gerçek GET veya POST isteğinden önce backend’e “Bu origin’den, bu HTTP metoduyla ve bu header’larla istek göndermeme izin veriyor musun?” sorusunun yöneltilmesidir.

Preflight gerektirme ihtimalini artıran başlıca unsurlar şunlardır:

  • PUT, PATCH veya DELETE gibi HTTP metotlarının kullanılması,
  • Authorization gibi özel request header’larının gönderilmesi,
  • JSON veri göndermek için Content-Type: application/json kullanılması,
  • Tarayıcının basit istek kapsamı dışında değerlendirdiği başka header veya istek özelliklerinin bulunması.

Örneğin frontend’den şu tür bir istek gönderdiğinizi düşünelim:

fetch("http://localhost:5000/api/data", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer token"
  },
  body: JSON.stringify({ name: "Berk" })
});

Bu istekte hem JSON içerik türü hem de özel bir Authorization header’ı bulunduğu için tarayıcı, gerçek POST isteğinden önce backend’e bir OPTIONS isteği gönderebilir.

Preflight OPTIONS isteği nasıl çalışır?

Tarayıcı preflight sırasında genellikle şu bilgileri header olarak iletir:

  • Origin: İsteği başlatan frontend adresi,
  • Access-Control-Request-Method: Gerçek istekte kullanılacak HTTP metodu,
  • Access-Control-Request-Headers: Gerçek istekte gönderilecek özel header’lar.

Backend’in bu OPTIONS isteğine başarılı bir yanıt vermesi ve izinleri açıkça belirtmesi gerekir. Yanıtta en azından senaryoya uygun şekilde şu header’lar bulunabilir:

  • Access-Control-Allow-Origin: İzin verilen frontend origin’i,
  • Access-Control-Allow-Methods: İzin verilen HTTP metotları,
  • Access-Control-Allow-Headers: İzin verilen request header’ları.

Örneğin frontend http://localhost:3000 adresinden geliyorsa backend, izin verilen origin olarak bu adresi döndürebilir. Tarayıcı preflight yanıtını uygun bulursa gerçek POST isteğini gönderir. Preflight yanıtı eksik veya hatalıysa gerçek istek hiç gönderilmeyebilir.

Bu nedenle Network panelinde yalnızca başarısız görünen POST isteğine bakmak yeterli değildir. Önce aynı endpoint için gönderilmiş bir OPTIONS isteği olup olmadığını kontrol etmek gerekir. OPTIONS isteği kırmızı görünüyorsa sorun çoğunlukla backend’in preflight yanıtında, izin verilen metotlarda veya header listesindedir.

Backend’de CORS Header’ları Adım Adım Nasıl Ayarlanır?

Backend’de CORS Header’ları Adım Adım Nasıl Ayarlanır?

CORS çözümü frontend’de hatayı gizlemekten değil, backend’in tarayıcıya doğru izinleri bildirmesinden geçer. Framework değişse de temel mantık aynıdır: backend, hangi origin’in hangi metotlarla ve hangi header’larla API’ye erişebileceğini response header’ları üzerinden belirtir.

Aşağıdaki akış, http://localhost:3000 adresindeki frontend’in http://localhost:5000/api/data endpoint’ine eriştiği bir senaryoda izlenebilir:

  1. Tarayıcı konsolunu ve Network panelini inceleyin. Hata mesajında hangi URL’nin engellendiğini, isteğin hangi origin’den çıktığını ve varsa OPTIONS isteğinin durumunu kontrol edin. Gerçek isteğin mi, yoksa preflight isteğinin mi başarısız olduğunu ayırmadan rastgele header eklemek sorunu uzatabilir.
  2. Frontend origin’ini tam olarak belirleyin. Origin yalnızca alan adından oluşmaz; protokol ve port da önemlidir. http://localhost:3000, http://localhost:5000 ile aynı origin değildir. Ayrıca http ve https arasındaki fark da dikkate alınmalıdır.
  3. Access-Control-Allow-Origin header’ını ekleyin. Backend, izin verilen frontend adresini response içinde döndürmelidir. Geliştirme ortamında izin verilen origin http://localhost:3000 olabilir. Production ortamında ise gerçek frontend adresi açıkça tanımlanmalıdır.
  4. Gerekli metot ve header izinlerini tanımlayın. İstek POST, PUT veya başka bir metot kullanıyorsa Access-Control-Allow-Methods içinde bu metoda izin verilmelidir. Frontend Authorization veya Content-Type gibi header’lar gönderiyorsa bunlar Access-Control-Allow-Headers içinde karşılanmalıdır.
  5. OPTIONS yanıtını kontrol edin. Backend, preflight isteğine uygun bir başarı durum koduyla yanıt vermeli ve gerekli CORS header’larını bu yanıta da eklemelidir. OPTIONS isteğinin uygulama içindeki normal veri işleme akışına girmesi gerekmez; görevi, tarayıcıya erişim iznini bildirmektir.
  6. Gerçek GET veya POST yanıtını da inceleyin. Sadece OPTIONS yanıtına header eklemek yeterli değildir. Tarayıcının frontend koduna göstereceği gerçek API yanıtında da uygun Access-Control-Allow-Origin header’ı bulunmalıdır. Aksi durumda preflight başarılı olsa bile gerçek yanıt tarayıcı tarafından engellenebilir.

Aşağıdaki örnek, herhangi bir web framework’ünün özelliklerini öğretmek amacı taşımaz. Yalnızca standart Python kütüphanesiyle hem gerçek API yanıtına hem de OPTIONS yanıtına CORS header’larının nasıl eklenebileceğini gösterir:

from http.server import BaseHTTPRequestHandler, HTTPServer

class Handler(BaseHTTPRequestHandler):
    def cors(self):
        self.send_header("Access-Control-Allow-Origin", "http://localhost:3000")
        self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
        self.send_header("Access-Control-Allow-Headers", "Content-Type, Authorization")

    def do_OPTIONS(self):
        self.send_response(204)
        self.cors()
        self.end_headers()

    def do_GET(self):
        self.send_response(200)
        self.cors()
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(b'{"status": "ok"}')

HTTPServer(("localhost", 5000), Handler).serve_forever()

Bu sunucu çalıştırıldığında frontend, http://localhost:3000 origin’inden gelen istekler için izin header’larını görebilir. Tarayıcı bir preflight gönderirse 204 yanıtı alır; gerçek GET isteğinde ise JSON yanıtıyla birlikte yine Access-Control-Allow-Origin header’ı döner.

Gerçek projelerde aynı mantık Flask, FastAPI, Spring veya başka bir backend teknolojisinde ilgili middleware ya da response yapılandırmasıyla uygulanabilir. Burada önemli olan kullanılan framework değil, OPTIONS ve gerçek API yanıtlarının birlikte doğru header’ları taşımasıdır. Backend temellerini sistematik biçimde öğrenmek isteyenler için Python backend temellerine odaklanan özel ders bu tür HTTP akışlarını kod üzerinden anlamayı kolaylaştırabilir.

Her origin için yıldız kullanmak neden dikkat gerektirir?

Access-Control-Allow-Origin: * geliştirme sırasında hızlı bir deneme gibi görünebilir; ancak bu değer tüm origin’lere izin anlamına gelir. API herkese açık olmayan veriler döndürüyor, kullanıcı oturumu kullanıyor veya kimlik doğrulama bilgileri taşıyorsa bu yaklaşım güvenlik sınırlarını gereksiz biçimde genişletebilir.

Özellikle cookie veya kimlik doğrulama bilgileriyle çalışan yapılarda yalnızca * kullanmak beklenen davranışı sağlamayabilir. İzin verilecek frontend adreslerini açıkça belirlemek, gereksiz origin’leri kapsam dışında bırakmak ve production ayarlarını geliştirme ayarlarından ayırmak daha güvenli bir tasarımdır.

Benzer şekilde frontend tarafında tarayıcı güvenliğini devre dışı bırakmaya, hatayı görmezden gelmeye veya proxy ile sorunu kalıcı olarak saklamaya çalışmak gerçek backend yapılandırma hatasını çözmez. Bu yöntemler yalnızca kontrollü yerel testlerde geçici teşhis amacıyla değerlendirilebilir; kullanıcıların eriştiği uygulamada CORS izinleri backend tarafından doğru şekilde yönetilmelidir.

Geliştirme ve Production Ortamında CORS Nasıl Tasarlanır?

CORS ayarları geliştirme ve production ortamında aynı mantıkla çalışsa da izin verilen origin değerleri farklı olmalıdır. Geliştirme sırasında frontend uygulaması çoğunlukla http://localhost:3000, backend ise http://localhost:5000 gibi farklı portlarda çalışır. Production ortamında ise izin, gerçek frontend alan adıyla açıkça tanımlanmalıdır.

Buradaki temel amaç, backend API’sini herkesin kullanımına açmak değil, gerçekten bu API’ye erişmesi gereken frontend origin’lerine izin vermektir. Bu nedenle CORS tasarımında “çalışıyor mu?” sorusunun yanında “hangi origin’e, hangi yöntemle ve hangi kimlik doğrulama bilgileriyle erişim veriyorum?” sorusu da sorulmalıdır.

Geliştirme ortamında belirli localhost origin’lerine izin verin

Frontend ve backend farklı portlarda çalışıyorsa tarayıcı bunları farklı origin olarak değerlendirir. Örneğin:

  • Frontend: http://localhost:3000
  • Backend: http://localhost:5000

Bu iki adres aynı bilgisayarda bulunsa bile portları farklı olduğu için origin’leri aynı değildir. Backend yanıtında frontend’in tam origin’i olan http://localhost:3000 açıkça izin verilen değer olarak bulunmalıdır.

Burada protokol, alan adı ve port birlikte değerlendirilir. http://localhost:3000 ile http://localhost:5173 aynı origin değildir. Benzer şekilde http://localhost:3000 ve https://localhost:3000 da farklı kabul edilir.

Geliştirme ayarlarında yalnızca gerçekten kullandığınız frontend adreslerini tanımlamak daha sağlıklıdır. Birden fazla geliştirici ortamı varsa izin listesinde kontrollü biçimde birden fazla origin bulunabilir; ancak bu liste rastgele veya sınırsız hâle getirilmemelidir.

Production ortamında gerçek frontend alan adını yazın

Uygulama yayınlandığında localhost adresleri yerine gerçek frontend alan adı kullanılır. Örneğin frontend https://uygulama.example.com adresinde çalışıyorsa backend, CORS yanıtında bu origin’i açıkça belirtmelidir.

Development ve production ayarlarının birbirine karıştırılması sık görülen bir problemdir. Geliştirme ortamında çalışan localhost izni production’da bırakılırsa gereksiz bir erişim alanı oluşabilir. Tersine, production alan adı geliştirme ayarlarına eklenmezse yerel testlerde beklenmeyen CORS hataları görülebilir.

Bu nedenle CORS ayarlarını ortam değişkenleri veya ayrı yapılandırma dosyaları üzerinden yönetmek daha düzenli bir yaklaşımdır. Genel akış şu şekilde düşünülebilir:

  • Geliştirmede: http://localhost:3000 gibi belirli yerel origin.
  • Test ortamında: test frontend’inin gerçek adresi.
  • Production’da: yalnızca yayınlanan frontend alan adı.

Asıl önemli nokta, backend’in gelen Origin bilgisini kontrol ederek yalnızca izin verilen origin’lere uygun CORS yanıtı vermesidir. Bu kontrol, frontend koduna eklenen bir ayar değil, API sunucusunun sorumluluğudur.

Kimlik doğrulama ve cookie kullanırken origin’i açıkça belirtin

API isteklerinde cookie tabanlı oturum, refresh token veya başka kimlik doğrulama bilgileri kullanılıyorsa CORS ayarı daha dikkatli yapılmalıdır. Bu durumda backend yanıtında Access-Control-Allow-Credentials: true kullanılması gerekebilir. Frontend tarafında da isteğin credential bilgileriyle gönderilmesine izin veren uygun istek ayarı bulunmalıdır.

Credential içeren isteklerde Access-Control-Allow-Origin: * kullanımı uygun değildir. Tarayıcı, kimlik bilgileriyle birlikte wildcard origin değerini güvenli bir izin olarak kabul etmez. Bu nedenle izin verilen frontend origin’i açıkça yazılmalı ve credential politikasıyla birlikte değerlendirilmelidir.

Örneğin cookie kullanan bir uygulamada mantık şu şekilde olmalıdır:

  • Origin, belirli frontend adresiyle eşleşmelidir.
  • Access-Control-Allow-Credentials ayarı kullanılan kimlik doğrulama modeline uygun olmalıdır.
  • Cookie’nin güvenlik özellikleri ayrıca doğru yapılandırılmalıdır.
  • Preflight yanıtı da gerekli CORS başlıklarını taşımalıdır.

CORS, tek başına kimlik doğrulama sistemi değildir. Bir origin’e CORS izni vermek, o origin’den gelen her kullanıcının otomatik olarak yetkili olduğu anlamına gelmez. Kullanıcının kimliği ve yetkileri backend tarafından ayrıca kontrol edilmelidir. CORS yalnızca tarayıcının farklı origin’ler arasındaki yanıt okuma politikasını düzenler.

Yanlış CORS çözümlerinden kaçının

CORS hatası görüldüğünde hızlı bir çözüm aramak normaldir; ancak bazı yaklaşımlar sorunu çözmek yerine yalnızca gizler veya güvenlik riskini büyütür.

  • Frontend’de hatayı JavaScript ile susturmaya çalışmak: Tarayıcı yanıtı güvenlik nedeniyle uygulamaya teslim etmiyorsa frontend kodu bu engeli kaldıramaz. Hata mesajını gizlemek, isteğin gerçekten başarılı olduğu anlamına gelmez.
  • Tarayıcı eklentisiyle sorunu gizlemek: CORS’u devre dışı bırakan eklentiler yalnızca kendi bilgisayarınızdaki test akışını etkileyebilir. Gerçek kullanıcıların tarayıcılarında backend yapılandırma hatası devam eder.
  • Yalnızca gerçek isteği ayarlayıp OPTIONS yanıtını unutmak: JSON POST, Authorization başlığı veya bazı HTTP metotları öncesinde gönderilen preflight isteği ayrıca yanıtlanmalıdır. OPTIONS başarısızsa asıl istek tarayıcı tarafından gönderilmeyebilir.
  • * değerini kalıcı production çözümü sanmak: Her origin’e izin vermek, özellikle kullanıcı hesabı, cookie veya yetkili veriler söz konusu olduğunda erişim kapsamını gereksiz biçimde genişletebilir.

Pratik bir tasarım kuralı olarak, geliştirmede kontrollü localhost adresleri; production’da ise gerçek frontend alan adı kullanılmalıdır. İzin verilen HTTP metotları, özel başlıklar ve credential davranışı da aynı yapılandırmanın parçası olarak ele alınmalıdır.

CORS Sorunlarında Hızlı Teşhis Kontrol Listesi

CORS hatasını çözmenin en hızlı yolu, doğrudan rastgele dosyaları değiştirmek yerine isteğin hangi aşamada durduğunu bulmaktır. Sorun çoğu zaman backend kodunun tamamen bozulmasından değil, tarayıcının güvenlik kontrolünün belirli bir yanıtı uygun bulmamasından kaynaklanır.

  1. Origin bilgisini tam olarak kontrol edin. Frontend’in protokolünü, alan adını ve portunu birlikte değerlendirin. http://localhost:3000 ile http://localhost:5173 farklı origin’lerdir. Backend’de izin verilen değer, tarayıcının gönderdiği origin ile birebir eşleşmelidir.

  2. İsteğin gerçekten hangi URL’ye gittiğini doğrulayın. Frontend kodunda beklediğiniz backend adresi yerine farklı bir port, alan adı, proxy yolu veya eski bir ortam değişkeni kullanılıyor olabilir. Network sekmesindeki Request URL alanını kontrol edin.

  3. Network sekmesinde OPTIONS isteği var mı bakın. JSON gönderimi, Authorization başlığı veya izin gerektiren bazı metotlar öncesinde tarayıcı bir preflight OPTIONS isteği gönderebilir. Bu isteği görüyorsanız teşhis yalnızca POST veya GET yanıtına bakılarak tamamlanmamalıdır.

  4. OPTIONS yanıtının durum kodunu inceleyin. OPTIONS isteği sunucuya ulaşıyor mu, yönlendirme alıyor mu veya hata koduyla mı dönüyor kontrol edin. Preflight yanıtlanmadığında tarayıcı asıl isteği göndermeyebilir.

  5. Access-Control-Allow-Origin değerini karşılaştırın. Yanıttaki değer frontend’in gerçek origin’iyle eşleşmelidir. Sondaki slash, protokol farkı veya port farkı gibi küçük ayrıntılar eşleşmeyi bozabilir.

  6. HTTP metodunu kontrol edin. Frontend POST, PUT, PATCH veya DELETE gönderirken backend’in Access-Control-Allow-Methods yanıtında bu metodun bulunup bulunmadığına bakın.

  7. Özel başlıkları inceleyin. Authorization, Content-Type veya uygulamaya özgü başka bir başlık kullanılıyorsa preflight yanıtında Access-Control-Allow-Headers ayarıyla izin verilmesi gerekebilir. İstek başlığında bulunan değer ile backend’de izin verilen başlık listesini karşılaştırın.

  8. Redirect ve proxy katmanlarını kontrol edin. İstek backend’e ulaşmadan önce reverse proxy, gateway, CDN veya sunucu yönlendirmesi üzerinden geçiyorsa CORS başlıkları bu katmanlardan birinde düşebilir. HTTP’den HTTPS’e veya bir API yolundan başka bir yola yönlendirme olup olmadığını Network sekmesinden inceleyin.

  9. Hata yanıtlarında da CORS başlıklarının bulunduğundan emin olun. Backend başarılı yanıtlara CORS başlıklarını ekliyor, ancak 401, 403, 404 veya 500 yanıtlarında eklemiyorsa frontend yine CORS hatası görebilir. Bu durumda gerçek backend hatası tarayıcı tarafından okunamaz hâle gelir.

  10. Credential kullanımını ayrıca değerlendirin. Cookie veya oturum bilgisi gönderiliyorsa wildcard origin, credential ayarı ve cookie politikası birlikte kontrol edilmelidir. Sadece Access-Control-Allow-Origin başlığını değiştirmek yeterli olmayabilir.

Pratik senaryo: localhost:3000’den localhost:5000’e JSON POST

Frontend’in http://localhost:3000 adresinde, backend’in ise http://localhost:5000 adresinde çalıştığını ve frontend’in JSON gövdeli bir POST isteği gönderdiğini düşünün. Bu durumda önce Network sekmesinde OPTIONS isteğini, ardından POST isteğini inceleyin.

İlk olarak OPTIONS yanıtında frontend origin’iyle uyumlu Access-Control-Allow-Origin değerini ve kullanılan metoda uygun Access-Control-Allow-Methods bilgisini arayın. İstek özel başlık taşıyorsa Access-Control-Allow-Headers değerini de kontrol edin.

Ardından POST yanıtını inceleyin. Başarılı yanıtın yanı sıra hata yanıtında da tarayıcının okuyabileceği uygun CORS izinleri bulunmalıdır. OPTIONS başarılı, POST başarısızsa sorun artık yalnızca CORS olmayabilir; backend’in döndürdüğü HTTP durum kodu, istek gövdesi ve doğrulama kuralları ayrıca incelenmelidir.

Beklenen sonuç, hem OPTIONS hem de POST yanıtında frontend origin’iyle uyumlu izinlerin görülmesidir. Bu akış, “hangi dosyayı değiştirmeliyim?” sorusundan önce “izin hangi aşamada eksik?” sorusunu sormanızı sağlar.

Sık Sorulan Sorular

CORS hatası frontend’den mi kaynaklanır, yoksa backend’in mi düzeltmesi gerekir?

Hata tarayıcı konsolunda görünse de temel izin çoğunlukla backend yanıtında düzenlenir. Frontend hangi URL’ye, hangi metotla ve hangi başlıklarla istek gönderdiğini doğru yapılandırmalıdır; ancak tarayıcının yanıtı okuyabilmesi için gerekli CORS header’larını API sunucusu göndermelidir.

Access-Control-Allow-Origin header’ı neden frontend koduna değil backend yanıtına eklenir?

Bu header, tarayıcıya “bu yanıt hangi origin tarafından okunabilir?” bilgisini verir. Kararı veren taraf tarayıcı, izni bildiren taraf ise yanıtı üreten backend’dir. Frontend’in kendi koduna aynı header’ı eklemesi, sunucudan gelen yanıtın güvenlik politikasını değiştirmez.

Preflight OPTIONS isteği neden gönderilir ve yanıtlanmazsa ne olur?

Tarayıcı, bazı istekleri göndermeden önce backend’in bu metot ve başlıklara izin verip vermediğini kontrol etmek için OPTIONS isteği gönderir. Backend bu isteği doğru yanıtlamazsa tarayıcı güvenlik gereği asıl POST, PUT veya benzeri isteği göndermeyebilir ya da dönen yanıtı frontend’e teslim etmez.

Access-Control-Allow-Origin değerinde * kullanmak güvenli midir?

Wildcard kullanımı herkese açık ve kimlik bilgisi gerektirmeyen bazı senaryolarda teknik olarak çalışabilir; ancak bunu genel ve kalıcı bir production çözümü olarak görmek doğru değildir. Cookie, oturum veya yetkili kullanıcı verileri söz konusuysa frontend origin’i açıkça belirtilmeli ve credential ayarlarıyla uyumlu yapılandırma kullanılmalıdır.

CORS header’ları doğru olduğu halde hata devam ediyorsa hangi kontroller yapılmalıdır?

İsteğin gerçek URL’sini, protokol-alan adı-port eşleşmesini, OPTIONS durum kodunu, izin verilen HTTP metotlarını ve özel başlıkları kontrol edin. Ayrıca redirect, reverse proxy, gateway ve CDN katmanlarının header’ları düşürmediğinden; 401, 403 veya 500 gibi hata yanıtlarında da CORS bilgilerinin döndüğünden emin olun.

CORS sorunlarında düzenli bir istek akışını takip etmek, hatayı gizlemeye çalışmaktan daha güvenilir ve güvenli bir çözümdür.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin — Yazılım Geliştirici ve Eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; bugün öğrencinin seviyesine ve hedefine göre şekillenen sürdürülebilir öğrenme sistemleri tasarlıyor. 500'den fazla kişiye ezber değil, düşünerek kod yazmayı öğretti — Berk Akademi'de izlemeye değil üretmeye dayalı öğrenme kültürünü o kuruyor.

WhatsApp Hemen Ara