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"); ``
``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 →