HTTP'den HTTPS'e, www'dan www'suza: doğru yönlendirme

Her sitenin en az dört adresi vardır: http://, https://, www'lu ve www'suz. Bunlardan sadece biri yayında görünmeli, diğer üçü tek adımda ona yönlenmeli. Kulağa basit geliyor ama denetlediğim sitelerde en sık rastladığım teknik sorunlardan biri hâlâ bu: zincirleme yönlendirmeler, 302'ler ya da hiç yönlenmeyen bir varyasyon.

Sonuç olarak aynı sayfa birden fazla adreste açılıyor, linkler farklı varyasyonlara dağılıyor ve Google hangi adresin asıl adres olduğunu kendisi seçmek zorunda kalıyor.

Önce bir host seçin

www'lu ya da www'suz olmanın SEO açısından bir üstünlüğü yok. Önemli olan birini seçip her yerde tutarlı kullanmak. Seçim yaparken şunlara bakıyorum:

  • Site zaten uzun süredir bir varyasyonla yayındaysa ve backlink'lerin çoğu ona gidiyorsa, onu koruyun. Sırf tercih yüzünden değiştirmek gereksiz risk.
  • Yeni bir site kuruyorsanız ve özel bir sebep yoksa kısa olan www'suz host daha pratik.
  • Çerezleri alt alan adlarından ayırmak gibi altyapı sebepleriyle www'lu host tercih edilebilir. Büyük sitelerde bu gerçek bir gerekçe olabiliyor.

Bu yazıdaki örneklerde tercih edilen adres https://example.com (www'suz, HTTPS).

Hedef: her varyasyon tek adımda

Doğru kurulumda şu üç adres de tek bir 301 ile hedefe gitmeli:

İstekOlması gereken
http://example.com/sayfa301 → https://example.com/sayfa
http://www.example.com/sayfa301 → https://example.com/sayfa
https://www.example.com/sayfa301 → https://example.com/sayfa
https://example.com/sayfa200

Sık gördüğüm hatalı kurulum, iki ayrı kuralın arka arkaya çalışması: önce http://www → https://www, sonra https://www → https://example.com. Bu iki adımlı bir zincir. Google birkaç adımlık yönlendirmeyi takip ediyor ama her adım gecikme ekliyor, hata ihtimalini artırıyor ve kullanıcı için de yavaşlık demek. Tek adım her zaman daha iyi.

Apache (.htaccess)

mod_rewrite ile iki koşulu birleştirip tek kural yazmak mümkün. Koşullardan herhangi biri doğruysa, yani istek HTTP ile geldiyse ya da host www ile başlıyorsa, istek doğrudan son adrese gönderiliyor:

.htaccess
RewriteEngine On

# HTTPS değilse VEYA host www ile başlıyorsa
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]

# Tek adımda tercih edilen adrese 301 (yol ve sorgu dizesi korunur)
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L]

Bu kuralı .htaccess dosyasının en üstüne, CMS'in kendi kurallarından önce koyun. Aksi hâlde WordPress gibi sistemlerin kuralları önce çalışabilir.

Bir uyarı: site Cloudflare gibi bir proxy ya da yük dengeleyicinin arkasındaysa, sunucuya gelen istek HTTPS olsa bile %{HTTPS} değeri off görünebilir ve sonsuz döngü oluşur. Bu durumda proxy'nin gönderdiği X-Forwarded-Proto başlığını kontrol etmek ya da HTTPS yönlendirmesini proxy tarafında yapmak gerekiyor. Kuralı ekledikten sonra mutlaka test edin.

nginx

nginx'te yönlendirmeyi ayrı server blokları ile yapmak hem daha okunaklı hem de daha hızlı. Koşul (if) kullanmaya gerek yok:

example.com.conf
# 1) Bütün HTTP istekleri: www'lu ve www'suz
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

# 2) HTTPS www: sertifika www'yu da kapsamalı
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name www.example.com;
    ssl_certificate     /etc/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.com/privkey.pem;
    return 301 https://example.com$request_uri;
}

# 3) Asıl site
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com;
    ssl_certificate     /etc/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.com/privkey.pem;
    root /var/www/example.com;
}

İkinci blok genelde unutulan kısım. https://www.example.com adresinin yönlenebilmesi için sunucunun önce o host için geçerli bir sertifika sunması gerekiyor. Sertifika sadece example.com için alınmışsa tarayıcı yönlendirmeye ulaşmadan hata veriyor.

Kuralları kendi URL listenize göre oluşturmak için yönlendirme oluşturucu aracını kullanabilirsiniz.

curl ile test ve zincir kontrolü

Tarayıcı testi yanıltıcı olabilir, çünkü tarayıcılar 301'leri önbelleğe alıyor. Ben her zaman curl -I ile kontrol ediyorum:

curl -sI http://www.example.com/sayfa | grep -iE '^(HTTP|location)'

Çıktıda 301 ve location: https://example.com/sayfa görmeniz gerekiyor. Dört varyasyonun hepsini birden ve kaç adım sürdüğünü görmek için küçük bir döngü işe yarıyor:

yonlendirme-kontrol.sh
#!/usr/bin/env bash
# Dört varyasyonu test eder: adım sayısı, son kod ve son adres
yol="/sayfa"
for host in http://example.com http://www.example.com \
            https://www.example.com https://example.com; do
  curl -s -o /dev/null -L \
    -w "%{num_redirects} adım  %{http_code}  %{url_effective}  <- $host$yol\n" \
    "$host$yol"
done

Beklenen sonuç: ilk üç satırda 1 adım, sonuncuda 0 adım, hepsinde 200 ve aynı son adres. 2 adım gördüğünüz satır bir zincir demek. Sadece ana sayfayı değil, alt sayfaları ve sonunda / olan ve olmayan adresleri de test edin; zincirler çoğu zaman sondaki eğik çizgi kuralıyla www kuralının üst üste binmesinden çıkıyor.

HSTS

HTTPS'e tam geçtiğinizden eminseniz Strict-Transport-Security başlığını ekleyin. Bu başlık, tarayıcıya siteyi belirli bir süre boyunca sadece HTTPS ile açmasını söylüyor ve ilk ziyaretten sonraki HTTP → HTTPS yönlendirmesini tarayıcı tarafında gereksiz hale getiriyor.

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Ben önce kısa bir max-age ile başlayıp her şey sorunsuzsa süreyi uzatıyorum. includeSubDomains eklemeden önce HTTPS desteklemeyen bir alt alan adınız olmadığından emin olun.

Preload konusunda daha dikkatli olun. preload ekleyip domaini hstspreload.org üzerinden tarayıcıların listesine gönderdiğinizde, domain tarayıcıların içine gömülüyor ve listeden çıkmak uzun sürüyor. Listenin başvuru koşulları da ayrıca var; yazıyı yazdığım sırada HTTP isteklerinin önce aynı host üzerinde HTTPS'e yönlenmesini istiyordu, bu da www varyasyonu için tek adım kuralıyla çelişebiliyor. Başvurmadan önce koşulları sitede güncel hâliyle okuyun. Başlıklarınızın durumunu güvenlik başlıkları aracıyla kontrol edebilirsiniz.

Karışık içerik (mixed content)

HTTPS sayfada http:// ile yüklenen görsel, script ya da stil dosyası, karışık içerik uyarısına yol açıyor. Tarayıcılar HTTP script'lerini engelliyor, görselleri ise ya yükseltmeye çalışıyor ya da engelliyor. Sonuç bozuk görünen sayfalar ve güvenlik kilidinin kaybolması.

Veritabanında toplu arama-değiştirme ile http://example.com geçen yerleri güncelleyin ve Chrome DevTools'un Console sekmesinde "Mixed Content" uyarılarını arayın.

Sinyalleri tutarlı hale getirin

Yönlendirme tek başına yeterli değil. Google canonical seçerken yönlendirmelerin yanında başka sinyallere de bakıyor ve bu sinyaller birbiriyle çelişirse seçim sizin istediğiniz adres olmayabilir.

  • Bütün rel="canonical" etiketleri https://example.com ile başlıyor.
  • XML sitemap'lerde sadece tercih edilen host var.
  • İç linkler doğrudan son adrese gidiyor, yönlendirmeden geçmiyor.
  • hreflang ve Open Graph URL'leri güncellendi.
  • Search Console'da Alan adı (Domain) mülkü var; bütün protokol ve host varyasyonlarını tek mülkte görüyorsunuz.

Canonical etiketinin bir ipucu olduğunu, kesin bir talimat olmadığını hatırlatayım. Yönlendirme, canonical, sitemap ve iç linkler aynı adresi gösterdiğinde Google'ın başka bir seçim yapması için sebep kalmıyor.

Özetle

Bir host seçin, dört varyasyonun hepsini tek adımlı 301 ile ona gönderin ve bunu curl ile doğrulayın. Ardından HSTS ekleyin ama preload için acele etmeyin. Son olarak canonical, sitemap ve iç linkleri aynı adrese hizalayın. Bu işi bir kez doğru yaptığınızda üzerine yıllarca düşünmeniz gerekmiyor; site taşımalarında ise site taşıma kontrol listesi içindeki yönlendirme adımlarıyla birlikte tekrar gözden geçirin.

Comments / questions

If you have a question about any topic or wish to contact me: Telegram or send an email to [email protected] Thanks!

Related pages