Merhaba arkadaşlar, bugün başımı çok ağrıtan bir sorundan bahsedeceğim. Projeme Google Fonts veya başka bir CDN'den font eklediğimde, bazı kullanıcılardan "font yüklenemedi" şikayetleri gelmeye başladı. Tarayıcı konsoluna baktığımda ise karşımda koca bir CORS policy hatası duruyordu. Bu hatayı ilk gördüğümde "CDN zaten herkese açık, nasıl CORS hatası alırım ki?" diye düşünmüştüm. Meğerse konu sandığımdan biraz daha derinmiş.
Hatayı İlk Keşfedişim
Sorun genellikle şu şekilde ortaya çıkıyor: Siteniz `
` üzerinde çalışıyor ama fontlar `
` adresinden geliyor. Modern tarayıcılar, güvenlik nedeniyle, farklı bir kaynaktan (origin) font, script veya veri talep edildiğinde, o kaynağın "Access-Control-Allow-Origin" header'ını kontrol ediyor. Eğer bu header, sizin sitenizin origin'ini (`
`) içermiyor veya `` (yıldız) ile tüm origin'lere izin vermiyorsa, tarayıcı bu fontu veya scripti engelliyor ve konsola şuna benzer bir hata düşüyor:
Sorunun Temel Nedeni ve CDN Tarafındaki Ayarlar
Aslında sorunun kökeni, fontu veya scripti servis eden CDN sunucusunun yapılandırmasında yatıyor. Doğru CORS header'larını göndermek CDN sağlayıcısının veya sunucu yapılandırmasının sorumluluğunda. Örneğin, bir Apache sunucusunda `.htaccess` dosyasına şu kuralları eklemek gerekebilir:
Ya da daha güvenli bir yaklaşım olarak, sadece belirli domain'lere izin vermek isteyebilirsiniz:
Önemli Not: `` (yıldız) kullanmak, kaynağınızın tüm internet tarafından erişilebilir olması anlamına gelir. Bu, her ne kadar fontlar için genelde sorun olmasa da, hassas veriler için asla önerilmez.
Geliştirici Olarak Bizim Yapabileceklerimiz
Peki ya kullandığımız CDN üzerinde bu ayarlara erişimimiz yoksa? İşte benim başvurduğum birkaç pratik çözüm:
1. Fontları Kendi Sunucuma Host Etmek: Bu en garantili yöntem. Google Fonts'tan indirdiğiniz font dosyalarını projenizin içine atıp, CSS'teki `@font-face` tanımını kendi domain'inize işaret edecek şekilde güncelliyorsunuz. Böylece tüm kaynaklar aynı origin'den gelmiş oluyor ve CORS diye bir derdiniz kalmıyor.
2. Proxy Kullanmak (Gelişmiş Senaryolar İçin): Eğer font/script CDN'ini değiştirme şansınız yoksa, kendi backend'inizde basit bir proxy endpoint'i oluşturabilirsiniz. Frontend'iniz, font isteğini kendi sunucunuza yapar, sunucunuz da CDN'den bu fontu çekip kullanıcıya iletir. Böylece tarayıcı için kaynak aynı origin'den gelmiş gibi görünür. İşte basit bir Node.js (Express) örneği:
Sonuç olarak, bu CORS meselesi güvenlik odaklı bir tarayıcı politikası ve çoğu zaman sorun, kullandığımız harici kaynağın doğru şekilde yapılandırılmamış olmasından kaynaklanıyor. Ben genelde kontrolüm altında olması için fontları projeye dahil etmeyi tercih ediyorum. Hem performans açısından da optimizasyon şansım oluyor.
Peki ya siz? Harici CDN'lerden font/script kullanırken benzer CORS hatalarıyla karşılaştınız mı? Çözüm için hangi yöntemi tercih ediyorsunuz? Yoksa daha farklı ve temiz bir çözümünüz var mı? Yorumlarda paylaşalım!
Sorun genellikle şu şekilde ortaya çıkıyor: Siteniz `
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
JavaScript:
Access to font at 'https://cdn.fontprovider.com/font.woff2' from origin 'https://sitem.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Aslında sorunun kökeni, fontu veya scripti servis eden CDN sunucusunun yapılandırmasında yatıyor. Doğru CORS header'larını göndermek CDN sağlayıcısının veya sunucu yapılandırmasının sorumluluğunda. Örneğin, bir Apache sunucusunda `.htaccess` dosyasına şu kuralları eklemek gerekebilir:
Kod:
<FilesMatch "\.(ttf|otf|eot|woff|woff2)$">
Header set Access-Control-Allow-Origin ""
</FilesMatch>
Ya da daha güvenli bir yaklaşım olarak, sadece belirli domain'lere izin vermek isteyebilirsiniz:
Kod:
Header set Access-Control-Allow-Origin "https://sitem.com"
Önemli Not: `` (yıldız) kullanmak, kaynağınızın tüm internet tarafından erişilebilir olması anlamına gelir. Bu, her ne kadar fontlar için genelde sorun olmasa da, hassas veriler için asla önerilmez.
Peki ya kullandığımız CDN üzerinde bu ayarlara erişimimiz yoksa? İşte benim başvurduğum birkaç pratik çözüm:
1. Fontları Kendi Sunucuma Host Etmek: Bu en garantili yöntem. Google Fonts'tan indirdiğiniz font dosyalarını projenizin içine atıp, CSS'teki `@font-face` tanımını kendi domain'inize işaret edecek şekilde güncelliyorsunuz. Böylece tüm kaynaklar aynı origin'den gelmiş oluyor ve CORS diye bir derdiniz kalmıyor.
2. Proxy Kullanmak (Gelişmiş Senaryolar İçin): Eğer font/script CDN'ini değiştirme şansınız yoksa, kendi backend'inizde basit bir proxy endpoint'i oluşturabilirsiniz. Frontend'iniz, font isteğini kendi sunucunuza yapar, sunucunuz da CDN'den bu fontu çekip kullanıcıya iletir. Böylece tarayıcı için kaynak aynı origin'den gelmiş gibi görünür. İşte basit bir Node.js (Express) örneği:
JavaScript:
const express = require('express');
const fetch = require('node-fetch'); // veya axios
const app = express();
app.get('/proxy-font', async (req, res) => {
try {
const fontUrl = 'https://cdn.fontprovider.com/font.woff2';
const response = await fetch(fontUrl);
const fontBuffer = await response.buffer();
// CDN'den gelen CORS header'larını da iletebilirsiniz veya kendiniz set edebilirsiniz.
res.set('Access-Control-Allow-Origin', 'https://sitem.com');
res.set('Content-Type', 'font/woff2');
res.send(fontBuffer);
} catch (error) {
res.status(500).send('Font yüklenemedi');
}
});
app.listen(3000);
Sonuç olarak, bu CORS meselesi güvenlik odaklı bir tarayıcı politikası ve çoğu zaman sorun, kullandığımız harici kaynağın doğru şekilde yapılandırılmamış olmasından kaynaklanıyor. Ben genelde kontrolüm altında olması için fontları projeye dahil etmeyi tercih ediyorum. Hem performans açısından da optimizasyon şansım oluyor.
Peki ya siz? Harici CDN'lerden font/script kullanırken benzer CORS hatalarıyla karşılaştınız mı? Çözüm için hangi yöntemi tercih ediyorsunuz? Yoksa daha farklı ve temiz bir çözümünüz var mı? Yorumlarda paylaşalım!