Открыть сервис

HTTP-заголовок Last-Modified

Last-Modified — это HTTP-заголовок ответа (response header) и запроса (request header), который указывает дату и время последнего изменения ресурса (например, веб-страницы, файла, изображения) на сервере. Относится к группе заголовков условных запросов и кэширования, определён в спецификации HTTP/1.1 (RFC 7232). Используется для управления кэшированием, проверки актуальности контента и оптимизации загрузки данных.

Формат и синтаксис

Значение заголовка Last-Modified представляет собой дату и время в формате, определённом в RFC 7231 (исторически — RFC 1123). Формат строго фиксирован и не допускает вариаций:

`` Last-Modified: <день-недели>, <день> <месяц> <год> <часы>:<минуты>:<секунды> GMT ``

Пример:

`` Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT ``

Ключевые особенности:

  • День недели (например, Mon, Tue, Wed) — обязателен, но не несёт функциональной нагрузки.
  • Месяц указывается трёхбуквенным сокращением на английском языке (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec).
  • Время всегда указывается в часовом поясе GMT (Greenwich Mean Time), эквивалентном UTC. Использование других часовых поясов не допускается.
  • Секунды обязательны, даже если значение равно 00.

В заголовке запроса (например, в If-Modified-Since) используется тот же формат даты.

Применение в HTTP-запросах и ответах

В ответе сервера

Сервер включает заголовок Last-Modified в ответ на GET- или HEAD-запрос, чтобы сообщить клиенту (браузеру, прокси-серверу, поисковому роботу) момент последнего изменения запрашиваемого ресурса. Это позволяет клиенту в будущем делать условные запросы.

В запросе клиента

Клиент может использовать два заголовка, основанных на Last-Modified:

  • If-Modified-Since — клиент отправляет значение, полученное ранее от сервера. Сервер сравнивает эту дату с фактической датой последнего изменения ресурса. Если ресурс не изменялся (дата совпадает или серверная дата раньше), сервер возвращает статус 304 Not Modified без тела ответа. Если ресурс изменился — возвращает полный ответ с кодом 200 OK.
  • If-Unmodified-Since — обратный механизм: сервер выполняет запрос только если ресурс не изменялся после указанной даты. Используется для оптимистичной блокировки при загрузке файлов (например, метод PUT).

Роль в кэшировании

Заголовок Last-Modified является одним из основных механизмов управления кэшированием в HTTP. Он позволяет:

  • Браузерам и прокси-серверам проверять актуальность кэшированных копий без повторной загрузки всего содержимого.
  • Снижать нагрузку на сервер и сеть, так как ответ 304 Not Modified не содержит тела и передаётся быстрее.
  • Поисковым системам (например, Яндекс, Google) определять частоту обновления страниц для корректировки индексации.

Однако в современных веб-приложениях Last-Modified часто дополняется или заменяется заголовком ETag (Entity Tag), который предоставляет более точный контроль версионирования (например, на основе хеша содержимого). Last-Modified имеет разрешение в 1 секунду, что может быть недостаточно для часто обновляемых ресурсов.

Ограничения и проблемы

  • Точность до секунды: если ресурс изменяется несколько раз в течение одной секунды, Last-Modified может не отразить последнее изменение.
  • Зависимость от серверного времени: если часы на сервере сбиты или настроены некорректно, заголовок может вводить в заблуждение.
  • Не подходит для динамического контента: для страниц, генерируемых на лету (например, PHP-скрипты, выдающие персонализированные данные), Last-Modified часто не устанавливается или устанавливается в текущее время, что делает кэширование неэффективным.
  • Проблемы с кластеризацией: если серверов несколько, их системные часы должны быть синхронизированы (например, через NTP), иначе разные серверы могут выдавать разные значения.
  • Не отражает изменения метаданных: заголовок фиксирует изменение содержимого, но не изменение прав доступа, владельца файла или других атрибутов файловой системы (хотя на практике эти изменения часто также обновляют временную метку).

Взаимодействие с другими заголовками

Last-Modified часто используется совместно с:

  • Cache-Control — задаёт директивы кэширования (например, max-age, no-cache, must-revalidate).
  • Expires — устаревший заголовок, указывающий абсолютное время устаревания кэша.
  • ETag — более точный идентификатор версии ресурса. При наличии обоих заголовков серверы и клиенты обычно отдают приоритет ETag.
  • Vary — указывает, что кэширование должно учитывать определённые заголовки запроса (например, Accept-Encoding).

Примеры использования

Простой GET-запрос и ответ с Last-Modified

``` GET /index.html HTTP/1.1 Host: example.com

HTTP/1.1 200 OK Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT Content-Type: text/html Content-Length: 1234 ```

Условный запрос с If-Modified-Since

``` GET /index.html HTTP/1.1 Host: example.com If-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMT

HTTP/1.1 304 Not Modified ```

Условный запрос с If-Unmodified-Since (для PUT)

``` PUT /document.html HTTP/1.1 Host: example.com If-Unmodified-Since: Wed, 21 Oct 2023 07:28:00 GMT Content-Type: text/html Content-Length: 5678

... тело запроса ... ```

Если ресурс был изменён после указанной даты, сервер вернёт 412 Precondition Failed.

Реализация на стороне сервера

Веб-серверы (Apache, Nginx, IIS) автоматически устанавливают Last-Modified для статических файлов на основе временной метки файловой системы (mtime). Для динамического контента разработчики могут устанавливать заголовок вручную, например, в PHP:

``php header("Last-Modified: " . gmdate("D, d M Y H:i:s", $timestamp) . " GMT"); ``

В Node.js (Express):

``javascript res.setHeader('Last-Modified', new Date(file.mtime).toUTCString()); ``

Альтернативы и эволюция

С развитием протокола HTTP/2 и HTTP/3, а также с ростом популярности одностраничных приложений (SPA) и API, роль Last-Modified несколько снизилась. Для кэширования API-ответов чаще используют ETag на основе хеша тела ответа. Для статического контента (CSS, JS, изображения) всё чаще применяется стратегия «fingerprinting» — добавление хеша содержимого в имя файла (например, style.a1b2c3d4.css), что позволяет устанавливать длительные сроки кэширования без необходимости в проверках.

Тем не менее, Last-Modified остаётся широко поддерживаемым и простым в реализации механизмом, особенно для статических сайтов и CMS (например, WordPress, Joomla), где он используется для управления кэшированием страниц.

Источники

  • RFC 7232 — Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests
  • RFC 7231 — Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
  • RFC 2616 — Hypertext Transfer Protocol — HTTP/1.1 (устаревшая, но исторически значимая)
  • Документация Apache HTTP Server: модуль mod_headers
  • Документация Nginx: директива if_modified_since
  • MDN Web Docs: HTTP заголовки — Last-Modified

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →