Bir frontend uygulaması farklı bir domaindeki API'ye istek gönderdiğinde tarayıcıda kırmızı renkte beliren "Access to XMLHttpRequest has been blocked by CORS policy" hatası, web geliştiricilerin en sık karşılaştığı sorunlardan biridir. Bu hatanın arkasında CORS — yani Cross-Origin Resource Sharing mekanizması yatar. Peki CORS tam olarak ne işe yarar ve nasıl çalışır?
Same-Origin Policy Nedir?
CORS'u anlamak için önce tarayıcıların uyguladığı Same-Origin Policy (Aynı Köken Politikası) kavramını bilmek gerekir. Bu politikaya göre bir web sayfası, yalnızca aynı origin'den (protokol + domain + port) gelen kaynaklara erişebilir.
Örneğin https://sitescripti.com adresindeki bir sayfa:
https://sitescripti.com/api/data→ İzin verilir (aynı origin)https://api.baskadomain.com/data→ Engellenir (farklı origin)http://sitescripti.com/api→ Engellenir (farklı protokol)https://sitescripti.com:3001/api→ Engellenir (farklı port)
Same-Origin Policy, kullanıcıları kötü niyetli sitelerin başka sitelere istek göndermesinden korur. Ancak günümüzde frontend ve backend genellikle farklı domainlerde barınır — işte tam bu noktada CORS devreye girer.
CORS Nasıl Çalışır?
CORS, sunucunun belirli HTTP başlıkları aracılığıyla "Bu origin'den gelen isteklere izin veriyorum" demesini sağlayan bir mekanizmadır. Tarayıcı bu başlıkları kontrol eder ve isteklerin geçip geçmeyeceğine karar verir.
Temel CORS Başlıkları
Sunucu tarafında ayarlanması gereken başlıca başlıklar şunlardır:
Access-Control-Allow-Origin: https://sitescripti.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
- Access-Control-Allow-Origin: Hangi origin'lerin erişebileceğini belirtir.
*tüm originlere izin verir ancak credentials ile birlikte kullanılamaz. - Access-Control-Allow-Methods: İzin verilen HTTP metotlarını listeler.
- Access-Control-Allow-Headers: İstemcinin gönderebileceği özel başlıkları tanımlar.
- Access-Control-Allow-Credentials: Cookie ve kimlik bilgilerinin gönderilip gönderilemeyeceğini belirler.
- Access-Control-Max-Age: Preflight yanıtının kaç saniye önbelleğe alınacağını belirtir.
Preflight İstekleri (OPTIONS)
Bazı istekler gönderilmeden önce tarayıcı bir preflight isteği yapar. Bu, OPTIONS metoduyla gönderilen otomatik bir istektir ve sunucuya "Bu isteğe izin veriyor musun?" diye sorar.
Preflight isteği şu durumlarda tetiklenir:
- HTTP metodu
GET,HEADveyaPOSTdışında ise (örn.PUT,DELETE) Content-Typebaşlığıapplication/jsongibi standart dışı bir değere sahipse- Özel başlıklar (
Authorization,X-Custom-Headervb.) gönderiliyorsa
// Preflight isteği örneği
OPTIONS /api/users HTTP/1.1
Origin: https://sitescripti.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization
// Sunucu yanıtı
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://sitescripti.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Basit İstekler (Simple Requests)
Aşağıdaki koşulları sağlayan istekler "basit istek" sayılır ve preflight gerektirmez:
- Metot:
GET,HEADveyaPOST - Yalnızca standart başlıklar:
Accept,Accept-Language,Content-Language,Content-Type(yalnızcaapplication/x-www-form-urlencoded,multipart/form-data,text/plain)
Yaygın CORS Hataları ve Çözümleri
1. "No 'Access-Control-Allow-Origin' header"
Sunucu yanıtında Access-Control-Allow-Origin başlığı eksik. Sunucu yapılandırmanıza bu başlığı eklemeniz gerekir.
// Express.js örneği
const cors = require('cors');
app.use(cors({
origin: 'https://sitescripti.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true
}));
2. Wildcard ile Credentials Çakışması
Access-Control-Allow-Origin: * ile Access-Control-Allow-Credentials: true birlikte kullanılamaz. Belirli bir origin belirtmeniz gerekir.
3. Preflight OPTIONS İsteğinin Başarısız Olması
Sunucunuzun OPTIONS metoduna doğru yanıt verdiğinden emin olun. Birçok framework bu metodu varsayılan olarak işlemez — açıkça yapılandırmanız gerekir.
4. Eksik Başlıklar
İstemcinin gönderdiği başlıklar Access-Control-Allow-Headers listesinde yoksa istek reddedilir. Authorization başlığı en sık unutulanlardan biridir.
Farklı Ortamlarda CORS Yapılandırması
// Node.js / Express
app.use(cors({ origin: 'https://sitescripti.com' }));
// Nginx
add_header Access-Control-Allow-Origin "https://sitescripti.com";
// Apache (.htaccess)
Header set Access-Control-Allow-Origin "https://sitescripti.com"
// Django
CORS_ALLOWED_ORIGINS = ["https://sitescripti.com"]
Güvenlik Tavsiyeleri
- Üretim ortamında
*kullanmaktan kaçının — yalnızca güvendiğiniz originleri listeleyin. credentials: trueayarını yalnızca gerçekten gerektiğinde etkinleştirin.- CORS, sunucu tarafı güvenliğin yerini almaz — her zaman ek kimlik doğrulama ve yetkilendirme kontrolleri uygulayın.
- Preflight önbellekleme (
Max-Age) ile gereksiz OPTIONS isteklerini azaltın.
API'nizdeki CORS yapılandırmasını test etmek mi istiyorsunuz? SiteScripti'nin CORS Test aracıyla herhangi bir URL'nin CORS başlıklarını anında kontrol edebilirsiniz.
Bu konuyla ilgili araçlarımızı da deneyin: cURL Builder, JSON Formatter, Güvenlik Başlıkları Analiz