HTTP durum kodları kopya kâğıdı: her kod açıklamasıyla (1xx-5xx)
DevTools’u açıyorsunuz, Network sekmesinin yarısı kıpkırmızı. Endpoint’iniz canlıda 502, lokalde 200 döndürüyor; Slack’ten bir iş arkadaşı az önce “bu 401 mi olmalı, 403 mü?” diye sordu. HTTP durum kodları basit görünür: üç hane, beş kova. Ama yanlış seçim bilgi sızdırır, SEO’yu bozar ve nöbet vardiyalarını çekilmez hâle getirir.
Bu rehber, sahada çalışan geliştiriciler için bir HTTP durum kodları kopya kâğıdıdır. Üç şey bulacaksınız: (1) gerçekten karşılaştığınız her kodu içeren hızlı referans tablosu, (2) en çok karıştırılan çiftler için karar matrisleri (301 vs 302, 401 vs 403, 404 vs 410, 502 vs 504) ve (3) curl, fetch ve Python requests ile durum kodlarını nasıl inceleyeceğinizi gösteren bir araç bölümü. Aşağıdaki her kod, güncel HTTP semantik standardı olan RFC 9110 ve IANA HTTP Status Code Registry temel alınarak hazırlandı.
Hızlı referans: tüm HTTP durum kodları bir bakışta
Canlı ortamda karşılaşacağınız kodlar aşağıda sınıflarına göre gruplandı. Bu tabloyu yer imlerinize ekleyin; yazının geri kalanı zor olanları açıklıyor.
| Kod | Adı | Ne zaman görürsünüz |
|---|---|---|
| 100 | Continue | Expect: 100-continue ile büyük bir POST gövdesi gönderirken |
| 101 | Switching Protocols | WebSocket el sıkışması, HTTP/2 yükseltmesi |
| 103 | Early Hints | Sunucu, asıl yanıttan önce Link header’ları iletir |
| 200 | OK | GET, PUT, PATCH için varsayılan başarı |
| 201 | Created | Kaynak yaratan POST (Location döner) |
| 202 | Accepted | Asenkron iş kuyruğa alındı, henüz tamamlanmadı |
| 204 | No Content | DELETE başarısı, gövde döndürmeyen PUT |
| 206 | Partial Content | Range isteği, video atlama, devam ettirilebilir indirme |
| 301 | Moved Permanently | Eski URL emekliye ayrıldı, arama motorları link gücünü aktarır |
| 302 | Found | Geçici yönlendirme, orijinal URL hâlâ kanonik |
| 303 | See Other | Form POST’undan sonra Post/Redirect/Get deseni |
| 304 | Not Modified | ETag veya If-Modified-Since eşleşen koşullu GET |
| 307 | Temporary Redirect | 302 gibi, ama method ve gövde korunur |
| 308 | Permanent Redirect | 301 gibi, ama method ve gövde korunur |
| 400 | Bad Request | Hatalı JSON, eksik zorunlu alan, şema başarısızlığı |
| 401 | Unauthorized | Kimlik bilgisi yok veya token süresi dolmuş |
| 403 | Forbidden | Kimlik doğrulandı ama izin yok |
| 404 | Not Found | Kaynak yok (veya saklıyorsunuz) |
| 405 | Method Not Allowed | Yalnızca GET kabul eden endpoint’e POST (Allow header’ı zorunlu) |
| 408 | Request Timeout | İstemci, isteği göndermeyi çok uzattı |
| 409 | Conflict | İyimser kilit hatası, yinelenen anahtar |
| 410 | Gone | Kaynak kalıcı silindi, geri gelmeyecek |
| 415 | Unsupported Media Type | Yanlış Content-Type, ör. JSON API’ye XML |
| 422 | Unprocessable Content | Söz dizimi geçerli, anlam geçersiz (doğrulama hatası) |
| 425 | Too Early | TLS 1.3 early-data tekrar saldırısı riski |
| 428 | Precondition Required | Sunucu, kayıp güncellemeyi önlemek için If-Match ister |
| 429 | Too Many Requests | Hız sınırlaması (Retry-After zorunlu) |
| 451 | Unavailable for Legal Reasons | DMCA, GDPR kaldırması, coğrafi engel |
| 500 | Internal Server Error | Kodunuzda yakalanmamış istisna |
| 501 | Not Implemented | Method veya özellik desteklenmiyor (REST’te nadir) |
| 502 | Bad Gateway | Yukarı akış geçersiz yanıt verdi |
| 503 | Service Unavailable | Bakım modu veya aşırı yük |
| 504 | Gateway Timeout | Yukarı akış zamanında yanıt vermedi |
| 507 | Insufficient Storage | WebDAV’da disk doldu |
| 508 | Loop Detected | WebDAV’da sonsuz yönlendirme veya özyineleme |
| 511 | Network Authentication Required | Otel/havalimanı WiFi’sinde captive portal |
Yazının geri kalanı her sınıfı karar matrisleri, anti-desenler ve yanlış seçimin SEO sonuçlarıyla açıklıyor.
HTTP durum kodları nasıl çalışır (3 haneli anatomi)
Neden üç hane?
HTTP durum kodları üç ondalık haneden oluşur, çünkü HTTP/0.9’un sabit genişlikli bir sinyale ihtiyacı vardı: ayrıştırıcının üzerinde hızlıca dallanabileceği kadar küçük, yeni kodlara yer bırakacak kadar büyük. Üç hane 900 olası değer verir (100–999); bu fazlasıyla yeterli. IANA kayıt defteri bugün bunların yalnızca 60 kadarını kullanıyor.
İlk hane sınıftır. İkinci ve üçüncü, o sınıfın içindeki belirli koddur. 418’i tanımayan bir istemci, kodu genel bir 4xx gibi ele almalıdır. RFC 9110 §15 bunu net biçimde belirtir: istemciler tanımadıkları kodları kendi sınıflarının x00’ı olarak işlemek zorundadır.
Beş kategori bir bakışta
| Sınıf | Anlamı | Gövde gerekli mi? | Varsayılan olarak önbelleklenir mi? |
|---|---|---|---|
1xx | Informational — geçici, devamı geliyor | Hayır | Hayır |
2xx | Success — istek anlaşıldı ve kabul edildi | Çoğu zaman | Method’a göre değişir |
3xx | Redirection — ek işlem gerekiyor | İsteğe bağlı | 301, 308 evet; 302, 307 hayır |
4xx | Client error — hata sizde, isteği düzeltin | Evet (açıklayın) | Genelde hayır |
5xx | Server error — hata bizde, yeniden denemek işe yarayabilir | Evet (açıklayın) | Hayır |
“Varsayılan olarak önbelleklenir mi?” sütunu önemli. CDN’ler ve tarayıcılar 301 ve 308 yanıtlarını agresifçe ve sonsuza kadar önbelleğe alır. Canlıda yanlış yönlendirme kodunu seçmek geri alınması güç bir karardır, çünkü kullanıcılar yönlendirmeyi kendi tarayıcılarında önbellekte tutar. Bu konuyu SEO bölümünde tekrar ele alacağız.
URL yapısının (yönlendirme kodlarının üzerinde çalıştığı yapı) ayrıntısına inmek isterseniz, URL kodlama ve çözme yüzde-kodlamasını, query string’leri ve bir URL’yi geçerli kılan bayt seviyesindeki boru hattını adım adım anlatıyor.
1xx — informational (gerçekten ne zaman görürsünüz)
Birçok geliştirici yıllarca doğrudan bir 1xx görmeden çalışır. Bunlar geçici yanıtlardır: sunucu, istemciye “hâlâ buradayım, devam et” diyor. Tarayıcı DevTools genellikle bunları gizler ve çoğu HTTP kütüphanesi bunları nihai yanıta katlayarak gösterir.
Aşağıdaki kodları doğrulamak istediğinizde MDN HTTP yanıt durum referansı kullanışlı bir çapraz referanstır.
100 Continue
İstemci, header’larında Expect: 100-continue gönderir ve büyük bir istek gövdesini iletmeden önce bekler. Sunucu gövdeyi kabul etmeye hazırsa 100 Continue ile yanıtlar; isteği zaten reddedecekse bir 4xx döner. Bu, büyük yüklemelerde bant genişliğinden tasarruf sağlar: sunucu eksik bir header yüzünden isteği reddedecekse 200 MB’ı göndermenin anlamı yok.
curl -v -H "Expect: 100-continue" \
-H "Content-Type: application/octet-stream" \
--data-binary @big-file.bin \
https://api.example.com/upload
Verbose çıktıda < HTTP/1.1 100 Continue görmüyorsanız, büyük olasılıkla istemciniz header’ı kırpıyor ya da sunucu bunu desteklemiyordur.
101 Switching Protocols
Bir HTTP bağlantısını WebSocket veya HTTP/2 bağlantısına dönüştüren el sıkışma. İstemci Upgrade: websocket gönderir, sunucu 101 Switching Protocols ile yanıtlar ve o andan itibaren bağlantı farklı bir protokolle konuşur. Bunu herhangi bir sohbet uygulamasının, canlı panonun veya ortak çalışma aracının Network sekmesinde göreceksiniz.
103 Early Hints
Yeni sayılabilecek bir kod (RFC 8297, 2017): sunucunun, asıl yanıt hazır olmadan önce preload ipuçları için Link header’ları göndermesine izin verir. Tarayıcı, sunucu hâlâ render ederken CSS ve JS’i indirmeye başlar. 2026 itibarıyla Cloudflare, Fastly ve Vercel 103’ü canlıda destekliyor; Chrome’da kullanımdan kaldırılan HTTP/2 server push’un modern alternatifidir.
HTTP/1.1 103 Early Hints
Link: </styles.css>; rel=preload; as=style
Link: </app.js>; rel=preload; as=script
HTTP/1.1 200 OK
Content-Type: text/html
...
Anti-desen kontrolü. Beklediğiniz hâlde istemciniz 1xx kodlarını hiç görmüyorsa, sorun genellikle bir ters proxy’dir. Eski nginx sürümleri Expect: 100-continue ve 103 Early Hints başlıklarını kırpar. Sunucunun bozuk olduğunu varsaymadan önce proxy yapılandırmanızı kontrol edin.
2xx — success (sadece 200’ün ötesinde)
Her şey için 200 OK döndürmek, REST API’lerinde en yaygın kod kokusudur. 2xx ailesi, istemcileri akıllılaştıran ve önbellekleri verimli kılan anlamsal bilgi taşır.
200 OK
Varsayılan. GET kaynağı döner, PUT güncellenmiş kaynağı döner (veya 204), PATCH yamalanmış kaynağı döner. Daha özgül bir kod kullanmak için belirli bir nedeniniz yoksa 200 kullanın.
201 Created
Yeni bir kaynak yaratan POST, 201 ile birlikte yeni kaynağı işaret eden bir Location header’ı dönmelidir. RESTful istemciler, az önce yarattıkları şeyin kanonik URL’sini bu şekilde keşfeder.
HTTP/1.1 201 Created
Location: /api/users/42
Content-Type: application/json
{"id": 42, "name": "Ada Lovelace"}
202 Accepted
Sunucu isteği kabul etti ama işlemeyi bitirmedi. Asenkron işler için kullanın: istemci poll yapmalı, bir webhook’a abone olmalı veya status endpoint’ini kontrol etmelidir. Gövdede bir job ID ile birlikte kullanın.
204 No Content
Başarı, gövde yok. DELETE için yaygındır (kaynak gitti, ne döneceksiniz?) ve istemcinin yeni durumu zaten bildiği PUT işlemleri için. Bir form gönderimi 204 döndürürse tarayıcılar mevcut sayfayı değiştirmez; single-page uygulamalardaki “gönder ve unut” işlemleri için kullanışlıdır.
206 Partial Content
Range istekleri için döner: istemci Range: bytes=1000-2000 header’ı ile 1000-2000 baytlarını istemiştir ve sunucu yalnızca o dilimle yanıt verir. Video akışı, devam ettirilebilir indirmeler ve HTTP tabanlı dosya senkronizasyonu hep 206’ya dayanır.
Karar: POST için 200 vs 201 vs 204
| Senaryo | Kod | Gövde |
|---|---|---|
| POST yeni bir kaynak yaratıyor | 201 Created | Yeni kaynak (veya yalnızca ID) + Location |
| POST asenkron iş tetikliyor, sonuç hazır değil | 202 Accepted | Job ID, poll URL |
POST kaynaksız bir eylem (ör. /login) | 200 OK | Eylem sonucu (token, durum) |
| POST başarılı ama yanıt boş | 204 No Content | (yok) |
200 ile 201 arasında karar veremiyorsanız şunu sorun: “Sunucu, artık kendi URL’sine sahip yeni bir kaynak mı yarattı?” Cevap evetse 201. Hayırsa 200.
3xx — redirection (301 vs 302 vs 307 vs 308)
Yönlendirmeler en çok yanlış kullanılan sınıftır. 301, 302, 307 ve 308 arasındaki farklar üç bağımsız soruya iner: taşınma kalıcı mı, method korunuyor mu ve yanıt önbelleklenebilir mi.
301 Moved Permanently
Kaynak taşındı ve geri gelmeyecek. Arama motorları link gücünü yeni URL’ye aktarır. Tarayıcılar ve CDN’ler 301 yanıtını süresiz önbelleğe alır. /old’u 301 ile /new’a yönlendirip sonra fikrinizi değiştirirseniz, önbelleklenmiş yönlendirmesi olan kullanıcılar sonsuza kadar (ya da önbelleklerini temizleyene kadar) /new’a gitmeye devam eder.
Tarayıcılar tarihsel olarak 301’de istek method’unu yeniden yazabilir (POST → GET); bunu düzeltmek için HTTP/1.1, 308’i tanıttı.
302 Found
Geçici yönlendirme. Orijinal URL hâlâ kanoniktir; arama motorları orijinali indekslemeye devam etmelidir. A/B test yönlendirmesi, bakım sayfaları veya “devam etmek için giriş yapın” akışları için kullanın.
301 gibi, tarayıcılar 302’de POST’u tarihsel olarak GET’e yeniden yazardı. Bir POST’u yönlendirip POST olarak tutmak istiyorsanız, bunun yerine 307 kullanın.
303 See Other
Method’u her zaman GET’e yeniden yazar. Post/Redirect/Get deseni: form /submit’e POST eder, sunucu Location: /thank-you ile 303 döner, tarayıcı GET /thank-you yapar. Teşekkür sayfasını yenilemek formu yeniden göndermez. 303 tam olarak bunun için tasarlandı.
304 Not Modified
Koşullu yanıt. İstemci If-None-Match: "abc123" (veya If-Modified-Since) gönderir, sunucu kaynağın değişip değişmediğini kontrol eder ve değişmediyse gövdesiz 304 döner. Tarayıcı önbelleklenmiş kopyasını kullanır. Her CDN ve önbellek katmanının sitenizi hızlı tutma yöntemi budur.
307 Temporary Redirect
302 gibi, ama method değişmemelidir. POST, POST kalır, gövde korunur. GET olmayan bir istekte geçici yönlendirme istediğinizde bunu kullanın.
308 Permanent Redirect
301 gibi, ama method değişmemelidir. POST/PUT kabul eden API’lerde kalıcı yönlendirmeler için modern ve daha güvenli seçim.
Karar matrisi: hangi yönlendirme kodu?
| Kalıcı (sonsuza kadar önbellekle) | Geçici (önbellekleme) | |
|---|---|---|
| Method GET’e değişebilir | 301 Moved Permanently | 302 Found |
| Method aynı kalmalı | 308 Permanent Redirect | 307 Temporary Redirect |
Özel durum: özellikle POST → GET istiyorsanız (Post/Redirect/Get deseni), 303 See Other kullanın.
Tarayıcı navigasyonlu HTML sayfaları için 301 ve 302 genellikle uygundur, çünkü GET, GET olarak kalır. API’ler ve formlar için, sürpriz method yeniden yazımlarından kaçınmak adına 308 ve 307’yi tercih edin.
4xx — client errors (doğrusunu seçmek)
4xx, istemcinin bir şeyi yanlış yaptığı anlamına gelir. 4xx sözcük dağarcığınız ne kadar zenginse, API’nizi kullanmak o kadar kolay olur: istemciler hata metinlerini ayrıştırmak yerine kod üzerinde dallanabilir.
400 Bad Request
Genel söz dizimi hatası. Hatalı JSON, yapısal düzeyde eksik zorunlu alan, sunucunun ayrıştıramadığı istek. İstek ayrıştırılıyor ama iş doğrulaması başarısız oluyorsa 422’yi tercih edin.
401 Unauthorized vs 403 Forbidden
HTTP’de en çok karıştırılan çift. Ayrım, gördüğünüz anda basittir:
401 Unauthorized: istek geçerli kimlik doğrulamadan yoksun. Sunucu kim olduğunuzu bilmiyor. Kimlik bilgilerini yeniden göndermek (veya token’ı yenilemek) sorunu çözebilir. Yanıt, RFC 9110 §15.5.2 uyarınca birWWW-Authenticateheader’ı içermek zorundadır.403 Forbidden: sunucu kim olduğunuzu biliyor ve yine de reddediyor. İsteği yeniden göndermek işe yaramaz. Farklı kimlik bilgilerine veya farklı izinlere ihtiyacınız var.
| Gördüğünüz | Doğru olan |
|---|---|
WWW-Authenticate: Bearer ile 401 | Token yok, süresi dolmuş veya geçersiz |
Başarılı girişten sonra 403 | Giriş yapılmış ama bu kullanıcı bu kaynağa erişemez |
Başarılı girişten sonra 401 | Bug: büyük olasılıkla 403 istiyorsunuz |
Anti-desen: 403-as-404. Bazı siteler, kimliği doğrulanmamış bir kullanıcı /admin/dashboard’u istediğinde 403 döner. Bu, /admin/dashboard’un varlığını sızdırır. GitHub bu sorunu, üyesi olmadığınız özel depolar için 404 döndürerek çözer; kaynak sizin perspektifinizden “yok”. Bu, bir bug değil, bilinçli bir bilgi gizleme tercihidir.
404 Not Found vs 410 Gone
İkisi de “bu kaynak burada değil” der. Fark, kalıcılık ve SEO’dadır.
404 Not Found: var olabilir, olmayabilir, geri gelebilir. Arama motorları kontrol etmeye devam eder.410 Gone: buradaydı, kasten kaldırıldı, geri gelmeyecek. Arama motorları indeksten çok daha hızlı düşürür.
Bir ürün sayfasını silip Google’ın indeksinden hemen çıkarmak istiyorsanız doğru çağrı 410’dur. Bir URL yalnızca geçici olarak bozuksa 404 yeterlidir.
405 Method Not Allowed
URL var ama bu method’u kabul etmiyor. Yanıt, desteklenen method’ları listeleyen bir Allow header’ı içermek zorundadır.
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
{"error": "POST is not allowed on this endpoint"}
Allow header’ını unutmak, elle yazılmış REST API’lerinde en yaygın sözleşme ihlalidir.
408 Request Timeout
İstemci bir isteği göndermeye başladı ve sonra sustu. Sunucu pes etti. 504 Gateway Timeout’tan farklıdır; o yukarı akışla ilgilidir, 408 ise “siz, istemci olarak, çok uzattınız” demektir.
409 Conflict
İstek, mevcut durumla çelişiyor. En yaygın kullanım: iyimser kilitleme. İstemci If-Match: "etag-v3" gönderir ve sunucunun mevcut ETag’i "etag-v4"’tür, dolayısıyla güncelleme 409 ile reddedilir.
410 Gone
Yukarıya bakın: kalıcı silme. Yumuşak silinmiş kayıtları arama indekslerinden çıkarmak için kullanışlıdır.
415 Unsupported Media Type
İstemci, sunucunun anlamadığı bir gövde gönderdi. Yalnızca JSON kabul eden bir API’ye XML POST etmek 415 döner. Yanıt, kabul edilebilir tipleri ima etmelidir.
422 Unprocessable Content
İstek sorunsuz ayrıştırılır, ancak anlamsal doğrulamadan geçemez. RFC 9110, 2022’de bunu WebDAV’dan çekirdek spesifikasyona taşıdı. Doğrulama hataları için 422 kullanın:
{
"error": "validation_failed",
"details": [
{"field": "email", "message": "must be a valid email"},
{"field": "age", "message": "must be at least 13"}
]
}
API’niz 400 ile 422 arasında karar veremiyorsa kural şudur: “ben bunu ayrıştıramıyorum bile” için 400, “ayrıştırdım ama anlamlı değil” için 422.
425 Too Early
Sunucu, TLS 1.3 early-data tekrarı olabilecek bir isteği işleme riskini almak istemediğinde gönderilir. Çoğunlukla CDN’ler ve ters proxy’lerle ilgilidir.
428 Precondition Required
Sunucu, kayıp güncelleme problemini önlemek için If-Match veya If-Unmodified-Since göndermenizde ısrar eder. Ortak çalışmalı düzenleme API’lerinde kullanılır.
429 Too Many Requests
Hız sınırlandı. Yanıt, iyi davranan istemcilerin geri çekilebilmesi için Retry-After (saniye olarak veya HTTP tarihi olarak) içermek zorundadır.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
{"error": "rate_limited", "limit": 100, "window": "1m"}
451 Unavailable for Legal Reasons
Numara, Ray Bradbury’nin “Fahrenheit 451” romanına bir göndermedir, ama kullanım amacı kurgu değildir: DMCA kaldırmaları, GDPR unutulma hakkı talepleri ve ülke düzeyinde coğrafi engellerin tümü 451’i haklı çıkarır. Yanıt, RFC 7725 uyarınca engeli zorunlu kılan yasal otoriteyi işaret eden bir Link header’ı içermelidir.
418 I’m a Teapot (paskalya yumurtası)
Gerçek bir kod. RFC 2324 (1 Nisan 1998 şakası) ve IETF, fazla sayıda ürün şaka olsun diye uyguladığı için bunu kayıtlardan çıkarmadı. Gerçek bir API’de 418 göndermeyin; çoğu ters proxy ve yük dengeleyici onu yanlış işler.
Karar matrisi: hangi 4xx?
| Durum | Kod |
|---|---|
| Gövde hatalı veya ayrıştırılamıyor | 400 |
| Kimlik doğrulama yok / token süresi dolmuş | 401 |
| Kimlik doğrulandı ama izin yok | 403 |
| URL yok (veya saklıyorsunuz) | 404 |
| URL vardı, kasten kaldırıldı | 410 |
| Yanlış HTTP method’u | 405 (Allow ile) |
Yanlış Content-Type | 415 |
| İyimser kilit çakışması | 409 |
| Doğrulama hatası (ayrıştırılır, doğrulanmaz) | 422 |
| Hız sınırlandı | 429 (Retry-After ile) |
| Yasal nedenlerle engellendi | 451 |
5xx — server errors (gerçekte bozulan ne)
5xx “hata bizde” demektir. Nöbetteki mühendisleri en çok ilgilendiren, sabah 3’te onları uyandıran 5xx’tir; çünkü kod, önce hangi katmanı incelemeniz gerektiğini söyler.
500 Internal Server Error
Tüm yakalayıcı. Neredeyse her zaman, framework’ün varsayılan handler’ına kadar yükselen yakalanmamış bir istisnadır. Size sebep hakkında hiçbir şey söylemez; burada yapılandırılmış log’lamanın durum kodundan daha önemli olmasının nedeni budur.
501 Not Implemented
Sunucu method’u hiç desteklemiyor. 405’ten farklıdır (bu method bu URL için izinli değil); 501 “bu sunucunun PROPFIND’ın ne demek olduğu hakkında hiçbir fikri yok” demektir. REST API’lerinde nadir.
502 Bad Gateway
Bir ters proxy veya yük dengeleyici, yukarı akıştan geçersiz bir yanıt aldı. Yukarı akış cevap verdi ama çöp şeklinde: yanlış protokol, hatalı header’lar, yanıt ortasında düşen bağlantı. CDN’inizden 502 görüyorsanız, origin muhtemelen çöküyor veya kesilmiş gövdeler döndürüyordur.
503 Service Unavailable
Sunucu şu anda kasıtlı olarak istek karşılamıyor. Bunu bakım pencereleri veya zarif aşırı yük yanıtları için kullanın. Retry-After içermelidir.
504 Gateway Timeout
Ters proxy yukarı akışı bekledi ve yukarı akış zamanında hiç yanıt vermedi. Yukarı akış yavaş veya takılı; yukarı akışın çöple yanıt verdiği 502’den farklıdır.
502 vs 504: nöbet teşhisi
| Gördüğünüz | İlk kontrol edilecek şey |
|---|---|
502 Bad Gateway | Yukarı akış geçersiz veriyle yanıtlıyor; origin log’larını çökmeler, hatalı yanıtlar, protokol uyumsuzlukları için kontrol edin |
504 Gateway Timeout | Yukarı akış asılı; origin CPU’sunu, DB sorgularını, aşağı akış API çağrılarını ve proxy’nin proxy_read_timeout ayarını kontrol edin |
Yaygın bir karışıklık: 60 saniye süren bir veritabanı sorgusu, proxy’niz 30 saniyede zaman aşımına uğruyorsa 504, uygulama sunucusu 90 saniyede zaman aşımına uğrayıp istisna fırlatıyorsa 500 olarak yüzeye çıkar. Aynı kök neden, farklı kod, farklı log satırı; panolarınızı her ikisini de yüzeye çıkaracak şekilde eğitin.
507 Insufficient Storage
WebDAV’a özgü. Sunucuda disk dolu. Bunu WebDAV olmayan bir API’den görüyorsanız, biri anlamı çarpıtıyor demektir.
508 Loop Detected
WebDAV PROPFIND operasyonlarında sonsuz özyineleme. Çok nadir.
511 Network Authentication Required
Captive portal kodu: bir otel veya havalimanındaki WiFi, tarayıcınıza “önce portalda giriş yapmanız gerekiyor” demek için 511 gönderir. Yanıt, portal sayfasına bir Location içerir.
Sorun giderme matrisi: önce hangi katman kontrol edilir
| Kod | App | Proxy | DB | Network |
|---|---|---|---|---|
500 | Evet | — | Belki (yakalanmamış DB hatası) | — |
502 | — | Evet (yukarı akış hatalı) | — | Belki (TCP reset) |
503 | Evet (bakım bayrağı) | Evet (rate-limit reddi) | — | — |
504 | Evet (yavaş handler) | Evet (timeout konfigürasyonu) | Evet (yavaş sorgu) | Evet (DNS, paket kaybı) |
Yaygın HTTP durum kodu anti-desenleri
Bu beş hata, üretimde gördüğümüz kötü kodun çoğunu açıklar.
1. Hataları 200 OK ile sarmak
HTTP/1.1 200 OK
{"success": false, "error": "user_not_found"}
Her izleme aracı, CDN ve önbellek artık isteğin başarılı olduğunu sanıyor. Yeniden deneme mantığı çuvallar. Durum kodu farkındalıklı yük dengeleyiciler kötü trafiği “sağlıklı” backend’lere yönlendirir. Bu desen JSON-RPC’den geldi ve GraphQL tarafından devralındı; GraphQL bunu yapıyor, çünkü kısmi başarılar alan başına hata raporlama gerektiriyor, bu adil. REST’in böyle bir mazereti yok: istemci hataları için 4xx, sunucu hataları için 5xx kullanın ve yapılandırılmış ayrıntıyı gövdeye koyun.
2. 401 ile 403’ü karıştırmak
401 ve 403’ünüz tutarlı değilse, saldırganlar API’nizi araştırarak hangi kaynakların var olduğunu keşfedebilir. Bir politika seçin: ya “bunu göremezsin” için 404 döndürün (GitHub’ın özel depolar için yaklaşımı) ya da tutarlı şekilde 403 döndürün. Tutarsızlık bilgi sızdırır.
3. 403’ü 404’ün arkasına saklamak
Bazen doğru, çoğu zaman bir bug. GitHub’ın özel depolar için 404 döndürmesi bilinçli; deponun varlığı başlı başına hassas. Ancak API’niz “bu kullanıcı hesabı askıya alındı” için 404 döndürürse, meşru kullanıcılar artık kullanıcı adını yanlış mı yazdıklarını yoksa askıya mı alındıklarını anlayamaz. Politikanızı açıkça belgeleyin ve tutarlı şekilde uygulayın.
4. 500’ü varsayılan yakalayıcı olarak kullanmak
Framework’ler bunu kolaylaştırıyor, sorun da burada. Yakalanmamış her istisna 500’e dönüşür ve uyarı sisteminiz “veritabanı çöktü” ile “kullanıcı hatalı bir UUID gönderdi” arasındaki farkı ayırt edemez. Doğrulama hatalarını yakalayıp 400 veya 422 fırlatın. ORM’inizden gelen NotFound’u yakalayıp 404 fırlatın. 500’ü gerçekten beklenmeyen başarısızlıklara saklayın; fırlattığınızda da ilişkilendirebilmek için bir request ID log’layın.
5. Uzun yönlendirme zincirleri
Her sıçrama bir round trip’e mal olur. /old → /intermediate → /canonical durumunda, bu en kötü durumda iki ek DNS aramasına ve iki ek TCP el sıkışmasına denk gelir. Google, 3 sıçramadan uzun zincirler için tarama önceliğini düşürür ve tarayıcılar döngüleri önlemek için yönlendirme zincirlerini yaklaşık 20 ile sınırlandırır. Zincirleri kaynağında daraltın: CDN konfigürasyonunuzda veya uygulamanızın yönlendirme haritasında.
HTTP durum kodları ve SEO
Arama motorları durum kodlarını, bir URL’yi tutmak, düşürmek veya aktarmak konusunda yetkili sinyaller olarak değerlendirir. Yanlış seçin, sıralamanız değişir.
301 vs 302 (link gücü)
301 Moved Permanently PageRank’i aktarır: Google, eskiyi işaret eden tüm sinyallerin yeni URL’yi kanonik hedef olarak kabul eder. 302 Found link gücünü aktarmaz (veya Google’ın sezgilerine bağlı olarak yavaş aktarır). Bir URL’yi sonsuza kadar yeniden adlandırdıysanız 301 kullanın. Bir konuğu /login’e yönlendiriyorsanız 302 kullanın.
404 vs 410 vs Soft 404
Google üç “eksik” durumu birbirinden ayırır:
404 Not Found: Google düzenli olarak yeniden kontrol eder ve URL’yi bir süre indekste tutar.410 Gone: Google URL’yi çok daha hızlı düşürür, çoğunlukla tek bir tarama döngüsü içinde.- Soft 404: Google’ın
200 OKdöndüren ama “bulunamadı” mesajı görüntüleyen sayfalar için kullandığı terim. Google bunu içerik desenlerinden tespit eder ve yine de404gibi davranır, ama siz bir tarama isteğini boşa harcamış ve muhtemelen gerçek içeriğinizi sulandırmış olursunuz.
Bayatlamış bir indeksi temizliyorsanız, kalıcı olarak kaldırılan URL’ler için gerçek 410’lar döndürün.
5xx ve tarama bütçesi
Google’ın tarayıcısı, bir site sürekli 5xx döndürdüğünde hızını düşürür. Search Console’un Crawl Stats raporu bunu gösterir: uzun süreli 5xx hata artışı tarama bütçenizi günlerce düşürebilir, bu da yeni sayfaların indekslenmesinin uzun sürmesi anlamına gelir. 5xx oranlarına yalnızca güvenilirlik metriği olarak değil, SEO metriği olarak da bakın.
Aslında bozuk olan 200 OK
Bir hata sayfasıyla 200 OK döndürmek (soft-404 anti-deseni) SEO için en kötü durumdur. Google hata mesajını indeksler, hiçbir şey için sıralar ve yavaş yavaş sayfanın bozuk olduğunu anlar. Tek sayfa uygulamanız özenli bir hata UI’sı render etse bile, daima sunucudan doğru durum kodunu döndürün.
HTTP durum kodları nasıl incelenir (araçlar)
Göremediğiniz şeyi düzeltemezsiniz. Çalışan her geliştirici bunlardan en az üçünde akıcı olmalı.
Tarayıcı DevTools Network paneli
Chrome, Firefox ve Safari’nin hepsi Network sekmesinde bir Status sütunu gösterir. Görünmüyorsa, sütun başlığına sağ tıklayıp Status Text’i ekleyin. Faydalı ipuçları:
- Preserve log: gezintiler arasında girdileri tutarak tüm yönlendirme zincirini görmenizi sağlar.
- Filter by status: yalnızca sunucu hatalarını görmek için
status-code:5xx(Chrome) yazın. - Replay XHR: herhangi bir isteğe sağ tıklayın → Replay XHR ile sayfayı yeniden yüklemeden tekrar çalıştırın.
Yönlendirmeler için, her sıçramayı ve her adımdaki durum kodunu görmek üzere isteği genişletin.
curl (evrensel cevap)
curl her şeyi gösterir. Hata ayıklamanın büyük kısmını çözen üç desen:
# Just the status code
curl -o /dev/null -s -w "%{http_code}\n" https://api.example.com/users/1
# Headers only (HEAD request, follow redirects)
curl -I -L https://example.com
# Full verbose with request and response headers
curl -v https://api.example.com/users/1
Query string’lerde özel karakterler içeren test URL’leri oluştururken, kodlamayı curl’ün halletmesi için --data-urlencode kullanın ya da kabloya hangi baytların gerçekten gideceğini doğrulamak üzere URL’yi URL kodlayıcı ve çözücü aracımıza yapıştırın.
# curl encodes the query value for you
curl -G "https://api.example.com/search" \
--data-urlencode "q=hello world & friends"
# Sends: GET /search?q=hello%20world%20%26%20friends
JavaScript fetch
Response.status özelliği tam sayı kodu içerir. Response.ok, herhangi bir 2xx için true olur.
const res = await fetch('https://api.example.com/users/1');
console.log(res.status); // 200
console.log(res.statusText); // "OK"
console.log(res.ok); // true
if (!res.ok) {
if (res.status === 401) {
// refresh token and retry
} else if (res.status === 429) {
const retryAfter = Number(res.headers.get('Retry-After')) || 1;
await new Promise(r => setTimeout(r, retryAfter * 1000));
} else if (res.status >= 500) {
throw new Error(`Server error: ${res.status}`);
}
}
axios’ta aynı mantık interceptor’larda yaşar:
import axios from 'axios';
axios.interceptors.response.use(
response => response,
error => {
const status = error.response?.status;
if (status === 401) {
// redirect to login
}
return Promise.reject(error);
}
);
Python requests
import requests
r = requests.get('https://api.example.com/users/1')
print(r.status_code) # 200
print(r.reason) # 'OK'
# Raises requests.exceptions.HTTPError for 4xx/5xx
r.raise_for_status()
# Manual handling
if r.status_code == 429:
retry_after = int(r.headers.get('Retry-After', '1'))
time.sleep(retry_after)
elif 500 <= r.status_code < 600:
raise RuntimeError(f'Server error: {r.status_code}')
raise_for_status(), “4xx/5xx’te yüksek sesle başarısız ol” için Python deyimidir. status_code üzerinde dallanmak yerine hatalarda istisna istediğiniz betiklerde kullanın.
Postman ve Bruno
Her ikisi de bir test betiğinin içinde durum kodları üzerinde assert yapmanıza izin verir:
// Postman/Bruno test script
pm.test("Status is 201", () => {
pm.response.to.have.status(201);
});
pm.test("Has Location header", () => {
pm.expect(pm.response.headers.get('Location')).to.match(/^\/users\/\d+$/);
});
Sözleşme ihlallerini canlıya çıkmadan yakalamak için bunları CI’da staging’e karşı çalıştırın.
SSS
401 ile 403 arasındaki fark nedir?
401 Unauthorized, sunucunun kim olduğunuzu bilmediği anlamına gelir; kimlik bilgileriniz eksik, süresi dolmuş veya geçersizdir. 403 Forbidden, sunucunun kim olduğunuzu bildiği ama yine de reddettiği anlamına gelir. Farklı kimlik bilgileri göndermek sorunu çözebilirse 401 kullanın. Çözmeyecekse 403 kullanın.
301’i mi 302’yi mi ne zaman kullanmalıyım?
Taşınma kalıcıysa 301 kullanın: eski URL bir daha gelmeyecek ve link gücünü arama motorlarının yeni URL’ye aktarmasını istiyorsunuz. Orijinal URL’nin hâlâ kanonik olduğu geçici yönlendirmeler (giriş akışları, A/B testi, bakım sayfaları) için 302 kullanın. API’ler için, istek method’unu koruduğu için 308 ve 307’yi tercih edin.
502 Bad Gateway hatası ne anlama gelir?
502, bir ters proxy veya yük dengeleyicinin yukarı akış sunucudan geçersiz bir yanıt aldığı anlamına gelir. Yukarı akış cevap verdi ama çöp şeklinde: yanlış protokol, hatalı header’lar veya düşen bir bağlantı. Yukarı akışın hiç yanıt vermediği 504 Gateway Timeout’tan farklıdır. İlk bakılacak yer: çökmeler veya kesilmiş yanıtlar için origin sunucu log’ları.
”Soft 404” nedir?
“Soft 404”, 200 OK döndüren ama aslında “bulunamadı” mesajı gösteren bir sayfadır. Google bunları sezgisel olarak tespit eder ve yine de 404 gibi davranır. Tarama bütçesini boşa harcar ve gerçek içeriğinizi sulandırabilirler. Tek sayfa uygulamanız özenli bir hata UI’sı render etse bile, daima sunucudan gerçek 404 veya 410 durum kodları döndürün.
400 yerine 422’yi ne zaman kullanmalıyım?
400 Bad Request kullanımı: sunucu isteği ayrıştıramıyorsa, yani hatalı JSON, eksik yapısal alanlar, söz dizimi hataları varsa. 422 Unprocessable Content kullanımı: istek sorunsuz ayrıştırılıyor ama iş doğrulamasından geçmiyorsa, yani geçersiz e-posta biçimi, aralık dışı değer, anlamsal olarak tutarsız alanlar varsa. Kısacası: söz dizimi için 400, anlam için 422.
429 Too Many Requests’e nasıl yanıt vermeliyim?
Retry-After header’ını okuyun (saniye sayısı veya HTTP tarihi) ve yeniden denemeden önce en az o kadar geri çekilin. Retry-After eksikse, 1 saniye civarında başlayıp jitter’lı üstel geri çekilme kullanın. Asla anında yeniden denemeyin; banlanma yöntemi tam da budur.
1xx informational kodları 2026’da hâlâ kullanılıyor mu?
Evet, ama çoğu uygulama kodu için görünmezdir. 100 Continue ve 101 Switching Protocols, temel HTTP/1.1 özellikleridir. 103 Early Hints, asıl yanıttan önce preload ipuçları iletmek için Cloudflare, Fastly ve Vercel tarafından giderek daha çok kullanılıyor; Largest Contentful Paint’i ölçülebilir biçimde iyileştiriyor. Çoğu HTTP kütüphanesi 1xx’i nihai yanıta katlar, dolayısıyla bunları genellikle yalnızca DevTools’ta veya curl -v ile görürsünüz.
418 “I’m a teapot” gerçek bir durum kodu mu?
Evet. RFC 2324, 1998’den kalma bir 1 Nisan şakasıydı, ama yeterince ürün bunu uyguladığı için IETF onu RFC 7168’de kayıtlarda tuttu. 418’i canlıda göndermeyin; birçok ters proxy ve yük dengeleyici bunu doğru işlemez ve şaka dışında gerçek bir amaca hizmet etmez.