Last-Modified, sunucudaki bir kaynağın son değiştirilme tarihini ve saatini belirten bir HTTP yanıt başlığıdır ve istemcinin If-Modified-Since aracılığıyla koşullu istekler yapmasına olanak tanır. Belirtilen tarihten bu yana kaynak değişmemişse, sunucu yanıt gövdesini göndermeden 304 Not Modified döndürür ve bu da bant genişliğinden önemli ölçüde tasarruf sağlar. RFC 7232 (IETF, 2014)'ye göre, Last-Modified ile koşullu istekler, tekrarlanan ziyaretlerde sayfa yükleme süresini %30-60 oranında azaltır. Başlık, çoğu HTTP sunucusu ve proxy tarafından otomatik olarak desteklenir.
Önemli Noktalar
Last-Modified, koşullu istek başlıkları grubuna ait bir HTTP başlığıdır. Sunucu, GET veya HEAD yanıtına bunu ekleyerek istenen kaynağın son değişiklik tarihini ve saatini HTTP-date biçiminde belirtir: Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT. İstemci (tarayıcı, mobil uygulama, proxy) bu tarihi önbelleğe alınmış kaynakla birlikte saklar. Tekrarlanan bir istekte, istemci aynı tarihle If-Modified-Since başlığını gönderir ve sunucu bunu kaynağın mevcut değişiklik zamanıyla karşılaştırır.
Last-Modified ile koşullu istek protokolü RFC 7232'de tanımlanmıştır ve tüm modern HTTP sunucuları tarafından desteklenir. Tarih biçimi sıkı bir şekilde düzenlenmiştir — yalnızca saat dilimi belirtilmeden GMT (Greenwich Mean Time). Sunucu, tarihi üç olası biçimde döndürmelidir: RFC 1123 (standart), RFC 850 (eski) veya ANSI C asctime. Pratikte, neredeyse tüm sunucular 29 karakter sabit uzunluklu RFC 1123 biçimini kullanır.
Last-Modified, önbellek doğrulama mekanizmaları kategorisine aittir: istemciye yanıtın önbelleğe alınıp alınamayacağını söylemez, bunun yerine zaten önbelleğe alınmış bir kaynağın güncelliğini kontrol etmek için bir araç sağlar. Önbellek politikası, Cache-Control başlığı aracılığıyla ayrı ayrı belirlenir. Akamai (2025) tarafından yapılan bir araştırmaya göre, Last-Modified'ın Cache-Control ile doğru yapılandırılması, statik içerik için kaynak sunucu yükünü %70'e kadar azaltır.
Last-Modified başlığı, HTTP/1.0'da (RFC 1945, 1996) tanımlanmış ve web'deki ilk önbellek yönetim mekanizmalarından biri olmuştur. HTTP/1.1'de ETag ortaya çıkmadan önce, koşullu istekler yapmanın tek yoluydu. Yaşına rağmen, başlık basitliği sayesinde güncelliğini korumaktadır — sunucunun içerik hash'i hesaplaması gerekmez, yalnızca dosya sisteminden dosya zaman damgasını veya veritabanından updated_at alanını okuması yeterlidir.
Tam döngü üç aşamadan oluşur. İlk istekte, sunucu kaynağı Last-Modified başlığı ve HTTP durumu 200 OK ile döndürür. İstemci, yanıtı tarihle birlikte önbelleğe alır. Tekrarlanan bir istekte, istemci kaydedilen tarihle If-Modified-Since başlığını gönderir. Sunucu bu tarihi kaynağın mevcut değişiklik zamanıyla karşılaştırır. Kaynak değişmemişse — boş gövdeyle 304 Not Modified döndürür. Değişmişse — yeni veriler ve yeni bir Last-Modified ile 200 OK döndürür.
// İlk istek — sunucu kaynağı tarihle birlikte döndürür
HTTP/1.1 200 OK
Content-Type: application/json
Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT
[{"id": 1, "name": "Alice"}]
// Tekrarlanan istek — istemci kaydedilen tarihi gönderir
GET /api/users HTTP/1.1
Host: example.com
If-Modified-Since: Wed, 02 Jul 2025 14:30:00 GMT
// Yanıt — veriler değişmedi
HTTP/1.1 304 Not Modified
Mobil uygulamalar için Last-Modified, veri senkronizasyonunda özellikle kullanışlıdır. Uygulama, son başarılı güncellemenin tarihini kaydeder ve If-Modified-Since ile sunucuya gönderir. Daha fazla veri varsa veya veriler değişmişse — sunucu tam seti döndürür. Yoksa — 304 ve uygulama yerel kopyayı kullanır. OkHttp ve URLSession, yerleşik önbellek sistemleri aracılığıyla bu mekanizmayı otomatik olarak destekler.
Statik dosyalar için Nginx ve Apache, tarihi dosya sistemi özniteliklerinden — mtime (değişiklik zamanı) — alır. Dinamik içerik için, sunucu kodu iş mantığına dayalı olarak Last-Modified'ı açıkça ayarlamalıdır: veritabanından updated_at alanı, Git'teki son commit tarihi, yapıt zaman damgası. Last-Modified açıkça ayarlanmazsa, sunucu başlığı hiç göndermeyebilir ve istemci, tarihe göre koşullu istekler yapamaz.
Last-Modified ve ETag benzer bir görevi — istemcinin önbellek güncelliğini kontrol etmesine izin vermek — yerine getirir, ancak temel farklılıkları vardır. Last-Modified bir zaman damgası kullanırken, ETag benzersiz bir sürüm tanımlayıcısı kullanır. Her yaklaşımın daha etkili olduğu senaryolar vardır ve HTTP şartnamesi her iki başlığın birlikte kullanılmasını önerir.
| Kriter | Last-Modified | ETag |
|---|---|---|
| Öz | Son değişiklik tarihi | Benzersiz sürüm tanımlayıcısı |
| Hassasiyet | Saniyeye kadar | Bite kadar (hash) |
| Uygulama karmaşıklığı | Düşük — dosya sisteminden otomatik | Orta — hash hesaplaması gerektirir |
| Küme sunucular | Sorun: mtime düğümler arasında farklılık gösterebilir | Düğümler arası aynı veride kararlı |
| Aralık desteği | Range isteklerini etkilemez | Aralıklar için güçlü ETag gerektirir |
| Öneri | Statik dosyalar ve basit API'ler için | Hassas kontrolün önemli olduğu API'ler için |
Last-Modified'in ana avantajı basitliğidir. Sunucu içerik hash'i hesaplamak zorunda değildir, bu da her istekte CPU kaynaklarından tasarruf sağlar. Statik dosyalar veya net zaman damgalarına sahip veriler sunan yüksek trafikli projeler için Last-Modified en uygun seçim olmaya devam eder. Öte yandan ETag, mutlak hassasiyet sağlar — bir JSON yanıtındaki tek bir harfi değiştirmek ETag'i değiştirir, ancak tarihi değiştirmeyebilir (dosya aynı sürümle üzerine yazılmışsa).
Şartname, her iki başlığın aynı anda döndürülmesini önerir. Sunucu, 200 OK yanıtına hem Last-Modified hem de ETag'i dahil eder. İstemci her iki koşullu başlığı — If-Modified-Since ve If-None-Match — gönderir. Sunucu önce ETag'i (önceliklidir), ardından Last-Modified'i kontrol eder. En az biri bir değişiklik sinyali veriyorsa — tam yanıt döndürülür. Bu, maksimum esneklik sağlar: ETag hassasiyeti garanti eder, Last-Modified ise ETag'i desteklemeyen istemciler için yedek kontrol sağlar.
Last-Modified yapılandırması sunucu türüne bağlıdır. Nginx ve Apache için Last-Modified, statik dosyalar için mtime'a göre otomatik olarak ayarlanır. Dinamik uygulamalar için başlığın sunucu kodunda ayarlanması gerekir. Popüler platformlardaki yapılandırmaya bakalım.
// Express.js — Last-Modified ayarlama
app.get("/api/users", async (req, res) => {
const updatedAt = await getLastUpdate()
const ifModifiedSince = req.get("If-Modified-Since")
// If-Modified-Since kontrolü
if (ifModifiedSince && new Date(ifModifiedSince)
>= updatedAt) {
return res.status(304).end()
}
const users = await getUsers()
res.set("Last-Modified", updatedAt.toUTCString())
res.json(users)
})
Express.js örneğinde, sunucu veritabanından son veri güncelleme tarihini alır, istemciden If-Modified-Since'i kontrol eder ve önbellek hala tazeyse 304 döndürür. Veriler değişmişse — yeni bir Last-Modified ayarlar ve tam yanıtı döndürür. toUTCString() tarihi gerekli HTTP biçimine dönüştürür. Üretim ortamında, her istekte veritabanı sorgusunu önlemek için updatedAt'i Redis'te önbelleğe almak iyi olur.
Nginx, dosyanın son değişiklik zamanına göre statik dosyalar için Last-Modified'ı otomatik olarak ayarlar. etag yönergesi (ETag'i devre dışı bırakma) veya ngx_http_headers_module modülü aracılığıyla bu davranış devre dışı bırakılabilir veya değiştirilebilir. Backend'e yapılan proxy isteklerinde, Last-Modified upstream yanıtından değişmeden iletilir. Önemli: backend Last-Modified döndürmezse, Nginx dinamik yanıtlar için otomatik olarak eklemez.
Last-Modified'in bilinen birkaç sınırlaması vardır. Başlıcası saniye hassasiyetidir. Bir kaynak bir saniye içinde iki kez değişirse, istemci yeni sürümü kaçırabilir. Pratikte bu nadir bir senaryodur, ancak yüksek frekanslı güncellemeler (ticker beslemeleri, sohbetler) için ETag önerilir. İkinci sınırlama kümeleme sorunudur: farklı sunucularda, kopyalama veya dağıtım nedeniyle bir dosyanın mtime'ı farklı olabilir ve bu da Last-Modified'ı tutarsız hale getirir.
Üçüncü sınırlama — If-Modified-Since'in saniye hassasiyetiyle işlenmesi, sunucuyu sık sık yoklarken gereksiz isteklere yol açabilir. İstemci her 500 ms'de bir If-Modified-Since gönderirse, sunucu tarih değişmediği için her seferinde 200 OK döndürür, ancak kaynak aslında zaten güncellenmiştir. Çözüm, ETag ile kombinasyon kullanmaktır: ETag bir saniye içindeki değişikliği yakalayacak, Last-Modified ise yedek olarak kalacaktır.
Dördüncü sorun — Last-Modified, aynı tarihe sahip aynı kaynağın farklı sürümlerini ayırt etmez. Bir dosya yedekten geri yüklenir ve mtime'ı orijinaliyle eşleşirse, istemci içeriğin değiştiğini fark etmez. ETag bu sorunu çözer: içerik hash'i, zaman damgasından bağımsız olarak, verideki herhangi bir değişiklikte kesin olarak değişir. Kritik veriler için her zaman her iki başlığı da kullanın.
Sıkça Sorulan Sorular
Yalnızca RFC 1123 biçiminde GMT (Greenwich Mean Time): haftanın günü, gün, ay, yıl, saat:dakika:saniye. Örnek: Wed, 02 Jul 2025 14:30:00 GMT. Saat dilimi her zaman GMT'dir, diğer biçimlere izin verilmez.
Teknik olarak evet, ancak bu RFC 7232'yi ihlal eder. Sunucu gelecekteki bir tarihi döndürürse, istemciler o tarih gelene kadar kaynağı güncellemez. Böyle bir yapılandırma hata olarak kabul edilir — tarih geçmişte veya şimdiki zamanda olmalıdır.
Hayır, If-Modified-Since koşullu istekleri yalnızca GET ve HEAD ile çalışır. POST istekleri önbelleğe alınmaz ve tarih bazlı doğrulama kullanmaz. POST'ta güncellik kontrolleri için ETag veya özel mekanizmalar kullanın.
Cache-Control önbellek politikasını (maksimum depolama süresi, kimin önbelleğe alabileceğini) tanımlarken, Last-Modified süresi dolmuş önbellek için bir doğrulama mekanizmasıdır. max-age süresi dolduğunda, istemci güncelliği kontrol etmek için If-Modified-Since gönderir.
Sunucunun başlığı doğru kaynaktan — veritabanı, dosya sistemi veya API — ayarladığını kontrol edin. Dinamik yanıtlar için, işleyici kodunda açıkça res.setHeader(“Last-Modified”, ...) çağrısı yaptığınızdan emin olun.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun