Last-Modified — ماهیت، مکانیسم و پیکربندی هدر تاریخ تغییر

نویسنده: IT Sectr منتشر شده: 2026-03-09 زمان مطالعه: 9 دقیقه

Last-Modified — یک هدر پاسخ HTTP است که تاریخ و زمان آخرین تغییر منبع را در سرور مشخص می‌کند، و به مشتری اجازه می‌دهد از طریق If-Modified-Since درخواست‌های شرطی انجام دهد. اگر منبع از تاریخ مشخص‌شده تغییر نکرده باشد، سرور 304 Not Modified را بدون ارسال بدنه پاسخ برمی‌گرداند که به‌طور قابل‌توجهی در پنهای صرفه‌جویی می‌کند. به استناد به RFC 7232 (IETF, 2014)، درخواست‌های شرطی با Last-Modified زمان بارگیری صفحات را در بازدیدهای مجدد 30—60% کاهش می‌دهند. این هدر توسط اکثر سرورهای HTTP و پروکسی‌ها به‌طور خودکار پشتیبانی می‌شود.

نکات کلیدی

  • Last-Modified — هدر HTTP با تاریخ آخرین تغییر منبع برای درخواست‌های شرطی If-Modified-Since
  • 304 Not Modified — پاسخ سرور در صورت تغییر نکردن منبع؛ مشتری از نسخه‌ی ذخیره‌شده خود استفاده می‌کند
  • دقت تا ثانیه — محدودیت هدر: تغییرات در حدود یک ثانیه ممکن است مشاهده نشوند
  • کار مشترک با ETag — سرور هر دو هدر را برمی‌گرداند، مشتری هر دو درخواست شرطی را ارسال می‌کند
  • تولید خودکار — Nginx و Apache Last-Modified را برای محتوای ساکن از سیستم فایل تعیین می‌کنند

Last-Modified چیست؟

Last-Modified — یک هدر HTTP است که به گروه هدرهای درخواست‌های شرطی (conditional requests) تلق می‌شود. سرور آن را در پاسخ GET یا HEAD اضافه می‌کند و تاریخ و زمان آخرین تغییر منبع مورد درخواست را به فرمت HTTP-date مشخص می‌کند: Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT. مشتری (مرورگر، برنامهٔ موبایل، پروکسی) این تاریخ را همراه با منبع ذخیره‌شده نگه می‌دارد. در درخواست مجدد، مشتری هدر If-Modified-Since را با همان تاریخ ارسال می‌کند و سرور آن را با زمان فعلی تغییر منبع مقایسه می‌کند.

پروتکل درخواست‌های شرطی با Last-Modified در RFC 7232 تعریف شده است و توسط همهٔ سرورهای HTTP مدرن پشتیبانی می‌شود. فرمت تاریخ به‌طور سختگیرانه تعیین شده است — تنها GMT (Greenwich Mean Time) بدون مشخص کردن منطقه زمانی. سرور باید تاریخ را به یکی از سه فرمت ممکن بازگرداند: RFC 1123 (استاندارد)، RFC 850 (منسوخ) یا ANSI C asctime. در عمل، تقریباً همهٔ سرورها از فرمات RFC 1123 با طول ثابت 29 کاراکتر استفاده می‌کنند.

Last-Modified به دستهٔ مکانیسم‌های اعتبارسنجی ذخیره تلق می‌شود: آن به مشتری نمی‌گوید که آیا می‌توان پاسخ را ذخیره کرد، بلکه ابزاری برای بررسی اعتبار منبع از پیش ذخیره‌شده فراهم می‌کند. سیاست ذخیره‌سازی به‌طور جداگانه از طریق هدر Cache-Control مشخص می‌شود. بر اساس تحقیقات Akamai (2025)، پیکربندی مناسب Last-Modified همراه با Cache-Control بار سرورهای اصلی را برای محتوای ساکن تا 70% کاهش می‌دهد.

Last-Modified کی پدید آمد

هدر Last-Modified در HTTP/1.0 (RFC 1945, 1996) تعریف شد و یکی از اولین مکانیسم‌های مدیریت ذخیره در وب بود. تا ظهور ETag در HTTP/1.1، این تنها راه انجام درخواست‌های شرطی بود. با وجود سن، این هدر به دلیل سادگی‌اش همچنان مورد‌استفاده است — سرور نیازی به محاسبه هش محتوا ندارد، کافیست تایمستمپ فایل را از سیستم فایل یا فیلد updated_at را از پایگاه داده بخواند.

Last-Modified چگونه کار می‌کند؟

چرخهٔ کامل شامل سه مرحله است. در اولین درخواست، سرور منبع را با هدر Last-Modified و وضعیت HTTP 200 OK بازمی‌گرداند. مشتری پاسخ را همراه با تاریخ ذخیره می‌کند. در درخواست مجدد، مشتری هدر If-Modified-Since را با تاریخ ذخیره‌شده ارسال می‌کند. سرور این تاریخ را با زمان فعلی تغییر منبع مقایسه می‌کند. اگر منبع تغییر نکرده باشد — 304 Not Modified با بدنهٔ خالی بازگردانده می‌شود. اگر تغییر کرده باشد — 200 OK با داده‌های جدید و Last-Modified جدید.

http
// درخواست اول — سرور منبع را با تاریخ بازمی‌گرداند
HTTP/1.1 200 OK
Content-Type: application/json
Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT

[{"id": 1, "name": "Alice"}]

// درخواست مجدد — مشتری تاریخ ذخیره‌شده را ارسال می‌کند
GET /api/users HTTP/1.1
Host: example.com
If-Modified-Since: Wed, 02 Jul 2025 14:30:00 GMT

// پاسخ — داده‌ها تغییر نکرده‌اند
HTTP/1.1 304 Not Modified

برای برنامه‌های موبایل، Last-Modified خصوصاً در هنگام همگام‌سازی داده مفید است. برنامه تاریخ آخرین به‌روزرسانی موفق را ذخیره می‌کند و آن را در If-Modified-Since به سرور ارسال می‌کند. اگر داده‌ها بیشتر شده یا تغییر کرده باشند — سرور مجموعهٔ کامل را بازمی‌گرداند. در غیر این صورت — 304، و برنامه از نسخهٔ محلی استفاده می‌کند. OkHttp و URLSession این مکانیسم را از طریق سیستم‌های ذخیره سازی داخلی خود به‌طور خودکار پشتیبانی می‌کنند.

سرور چگونه تاریخ را تعیین می‌کند

برای فایل‌های ساکن، Nginx و Apache تاریخ را از ویژگی‌های سیستم فایل — mtime (زمان تغییر) دریافت می‌کنند. برای محتوای دینامیک، کد سرور باید Last-Modified را بر اساس منطق کسب‌وکار به‌طور صریح تعیین کند: فیلد updated_at از پایگاه داده، تاریخ آخرین commit در Git، تایمستمپ ساخت آرتفاکت. اگر Last-Modified به‌طور صریح تعیین نشده باشد، سرور اصلاً هدر را بازنمی‌گرداند و مشتری نمی‌تواند بر اساس تاریخ درخواست‌های شرطی انجام دهد.

Last-Modified در مقابل ETag

Last-Modified و ETag وظیفهٔ مشابهی دارند — به مشتری امکان بررسی اعتبار ذخیره را می‌دهند — اما تفاوت‌های اساسی دارند. Last-Modified از نشانگر زمان استفاده می‌کند، ETag از یک شناسهٔ یکتا نسخه. هر رویکرد سناریوهای خاصی دارد که در آن‌ها کارامدتر است، و توصیهٔ مشخصات HTTP استفاده از هر دو هدر به صورت مشترک است.

معیارLast-ModifiedETag
ماهیتتاریخ آخرین تغییرشناسهٔ یکتا نسخه
دقتتا ثانیهتا بیت (هش)
پیچیدگی پیاده‌سازیپایین — خودکار از سیستم فایلمتوسط — نیاز به محاسبهٔ هش
سرورهای خوشه‌ایمشکل: mtime می‌تواند در گره‌ها متفاوت باشدپایدار در صورت داده‌های یکسان در گره‌ها
پشتیبانی از محدودهتأثیری بر Range requests نداردنیاز به ETag قوی برای محدوده‌ها
توصیهبرای محتوای ساکن و APIهای سادهبرای API‌هایی که بررسی دقیق مهم است

مزیت اصلی Last-Modified سادگی است. سرور نیازی به محاسبه هش محتوا ندارد که در منابع CPU در هر درخواست صرفه‌جویی می‌کند. برای پروژه‌های با بار سنگین که فایل‌های ساکن یا داده‌های با نشانگر زمانی مشخص تحویل می‌دهند، Last-Modified گزینهٔ بهینه باقی می‌ماند. ETag اما دقت مطلق را فراهم می‌کند — تغییر یک حرف در پاسخ JSON منجر به تغییر ETag می‌شود، اما ممکن است تاریخ را تغییر ندهد (اگر فایل با همان نسخه بازنویسی شده باشد).

استفادهٔ مشترک

مشخصات توصیه می‌کند هر دو هدر به صورت همزمان بازگردانده شوند. سرور هم Last-Modified و هم ETag را در پاسخ 200 OK قرار می‌دهد. مشتری هر دو هدر شرطی را — If-Modified-Since و If-None-Match ارسال می‌کند. سرور ابتدا ETag (اولویت دارد) و سپس Last-Modified را بررسی می‌کند. اگر حداقل یکی تغییر را نشان دهد — پاسخ کامل بازگردانده می‌شود. این حداکثر انعطاف‌پذیری را فراهم می‌کند: ETag دقت را و Last-Modified بررسی پیش‌فرز را برای مشتریانی که ETag را پشتیبانی نمی‌کنند تامین می‌کند.

پیکربندی Last-Modified در سرور

پیکربندی Last-Modified به نوع سرور بستگی دارد. برای Nginx و Apache، Last-Modified برای فایل‌های ساکن به‌طور خودکار بر اساس mtime ایجاد می‌شود. برای برنامه‌های دینامیک، هدر در کد سرور تنظیم می‌شود. بیایید تنظیمات را در پلتفرم‌های محبوب بررسی کنیم.

javascript
// Express.js — تنظیم Last-Modified
app.get("/api/users", async (req, res) => {
    const updatedAt = await getLastUpdate()
    const ifModifiedSince = req.get("If-Modified-Since")

    // بررسی If-Modified-Since
    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، سرور تاریخ آخرین به‌روزرسانی داده را از پایگاه داده دریافت می‌کند، If-Modified-Since را از مشتری بررسی می‌کند و در صورت اعتبار ذخیره 304 را بازمی‌گرداند. اگر داده‌ها تغییر کرده باشد — Last-Modified جدید تعیین و پاسخ کامل بازگردانده می‌شود. toUTCString() تاریخ را به فرمات HTTP مورد نیاز تبدیل می‌کند. در محیط تولید، اضافه کردن ذخیره updatedAt در Redis برای جلوگیری از اجرای پرسان به پایگاه داده در هر درخواست ارزشمند است.

Nginx: تنظیم Last-Modified

Nginx به‌طور خودکار Last-Modified را برای فایل‌های ساکن بر اساس زمان آخرین تغییر فایل تنظیم می‌کند. غیرفعال سازی یا تغییر رفتار از طریق دستور etag (غیرفعال سازی ETag) یا ماژول ngx_http_headers_module امکان‌پذیر است. برای درخواست‌های پروکسی به backend، Last-Modified بدون تغییر از پاسخ upstream منتقل می‌شود. مهم: اگر backend Last-Modified را بازنگرداند، Nginx آن را برای پاسخ‌های دینامیک به‌طور خودکار اضافه نمی‌کند.

محدودیت‌ها و چالش‌ها

Last-Modified چندین محدودیت شناخته شده دارد. اصلی‌ترین دقت تا ثانیه است. اگر منبع دو بار در طول یک ثانیه تغییر کرده باشد، مشتری ممکن است نسخهٔ جدید را از دست بدهد. در عمل، این سناریو نادر است، اما برای به‌روزرسانی‌های با فرکانس بالا (فهرست نمودها، چت‌ها) ETag توصیه می‌شود. محدودیت دوم مشکل خوشه‌ای کردن است: در سرورهای مختلف، فایل ممکن است به دلیل کپی یا استقرار mtime متفاوتی داشته باشد، که منجر به ناهماهنگی Last-Modified می‌شود.

محدودیت سوم — پردازش If-Modified-Since با دقت تا ثانیه می‌تواند در پرسان‌های مکرر به سرور منجر به درخواست‌های ضائع شود. اگر مشتری هر 500 میلی‌ثانیه If-Modified-Since ارسال کند، سرور هر بار 200 OK را بازمی‌گرداند، زیرا تاریخ تغییر نکرده، اما منبع در واقع به‌روز شده است. راه حل استفادهٔ ترکیبی با ETag است: ETag تغییر در طول ثانیه را تشخیص می‌دهد و Last-Modified به عنوان پشتیبان باقی می‌ماند.

چهارمین مشکل — Last-Modified نسخه‌های مختلف یک منبع با تاریخ یکسان را تفکیک نمی‌دهد. اگر فایل از پشتیبان بازگردانده شده باشد و mtime آن با اصلی مطابقت داشته باشد، مشتری متوجه تغییر محتوا نمی‌شود. ETag این مشکل را حل می‌کند: هش محتوا قاطعاً با هر تغییر داده‌ها، بدون توجه به نشانگر زمانی، تغییر می‌کند. برای داده‌های حساس همیشه از هر دو هدر استفاده کنید.

  • دقت تا ثانیه — تغییرات طول یک ثانیه را تشخیص نمی‌دهد; برای به‌روزرسانی‌های پرفرکانس از ETag استفاده کنید
  • خوشه‌ای کردن — mtime می‌تواند در سرورهای مختلف متفاوت باشد; از طریق NTP همگام سازی کنید یا از ETag استفاده کنید
  • Race condition — اگر منبع پس از ارسال If-Modified-Since ولی قبل از بررسی در سرور تغییر کند
  • تفسیر نادرست پروکسی — برخی پروکسی‌ها ممکن است Last-Modified را در ذخیره‌سازی تغییر دهند; HTTPS این مشکل را حل می‌کند

سوالات متداول

چه فرمات تاریخی در Last-Modified استفاده می‌شود؟

تنها GMT (Greenwich Mean Time) در فرمات RFC 1123: روز هفته، تاریخ، ماه، سال، ساعت:دقیقه:ثانیه. مثال: Wed, 02 Jul 2025 14:30:00 GMT. منطقه زمانی همیشه GMT است، سایر فرمات‌ها مجاز نیستند.

آیا Last-Modified می‌تواند در آینده باشد؟

از نظر فنی بله، اما این RFC 7232 را نقض می‌کند. اگر سرور تاریخی در آینده را بازگرداند، مشتریان تا رسیدن آن تاریخ منبع را به‌روز نمی‌کنند. چنین پیکربندی اشتباه محسوب می‌شود — تاریخ باید در گذشته یا حال باشد.

آیا Last-Modified با درخواست‌های POST کار می‌کند؟

خیر، درخواست‌های شرطی If-Modified-Since تنها با GET و HEAD کار می‌کنند. درخواست‌های POST ذخیره نمی‌شوند و از اعتبارسنجی بر اساس تاریخ استفاده نمی‌کنند. برای بررسی اعتبار داده‌ها در POST از ETag یا مکانیسم‌های سفارشی استفاده کنید.

Last-Modified چگونه با Cache-Control تعامل می‌کند؟

Cache-Control سیاست ذخیره‌سازی (حداکثر زمان نگهداری، کسانی که می‌توانند ذخیره کنند) را مشخص می‌کند، و Last-Modified مکانیسم اعتبارسنجی ذخیرهٔ منسوخ است. پس از پایان max-age، مشتری If-Modified-Since را برای بررسی اعتبار ارسال می‌کند.

اگر Last-Modified با به‌روزرسانی داده‌ها تغییر نکند چه کنیم؟

بررسی کنید که سرور هدر را از منبع اصلی — پایگاه داده، سیستم فایل یا API تنظیم می‌کند. برای پاسخ‌های دینامیک، مطمئن شوید که res.setHeader(«Last-Modified», ...) را در کد پردازشگر به‌طور صریح فراخوانی می‌کنید.

نتیجه‌گیری

  • Last-Modified — هدر HTTP با تاریخ آخرین تغییر منبع برای درخواست‌های شرطی 304
  • سادگی پیاده‌سازی — برای محتوای ساکن (mtime فایل) خودکار کار می‌کند و برای API به کد حداقل نیاز دارد
  • دقت تا ثانیه — محدودیت اصلی; برای تغییرات پرفرکانس از ETag استفاده کنید
  • ETag دقیق‌تر، Last-Modified ساده‌تر — ترکیب بهینه: هر دو هدر با هم
  • فرمات تاریخ HTTP — تنها GMT، RFC 1123، طول ثابت 29 کاراکتر
  • خوشه‌ای کردن — نیاز به همگام‌سازی زمان (NTP) یا استفاده از ETag به عنوان مکانیسم اصلی
  • توصیه — همیشه Last-Modified را برای API اضافه کنید و از طریق Nginx/Apache برای محتوای ساکن فعال کنید

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید