Conditional GET: что это, механизм условного запроса

Автор: IT Sectr Опубликовано: 2026-06-14 Время чтения: 7 мин

Conditional GET (условный GET-запрос) — HTTP-механизм, позволяющий клиенту проверить актуальность кэшированного ресурса перед полной загрузкой. Клиент отправляет GET-запрос с заголовками If-None-Match (содержит ETag) или If-Modified-Since (содержит дату), и сервер возвращает 304 Not Modified без тела ответа, если ресурс не изменился. По данным MDN Web Docs, 2025, условные запросы сокращают сетевой трафик серверов и клиентов. 304 Not Modified — ключевой HTTP-статус для эффективной синхронизации мобильных приложений.

Главное

  • Conditional GET — HTTP-запрос с заголовками If-None-Match или If-Modified-Since для проверки актуальности кэша.
  • 304 Not Modified — ответ сервера, указывающий, что ресурс не изменился. Тело ответа не передаётся, экономя трафик.
  • If-None-Match — заголовок с ETag (хешем версии), обеспечивающий точную проверку на уровне содержимого ресурса.
  • If-Modified-Since — заголовок с датой последнего изменения, проще в реализации, но менее точен (разрешение 1 секунда).
  • Эффективность — Conditional GET сокращает объём данных при синхронизации на 80–95% для неизменённых ресурсов.

Что такое Conditional GET в HTTP?

Conditional GET — это GET-запрос, содержащий один или несколько условных заголовков, на основании которых сервер решает, возвращать полный ответ или только статус 304 Not Modified. Основная цель — избежать передачи тела ответа, если ресурс не изменился с момента последнего запроса. Это фундаментальный механизм HTTP-кэширования, определённый в спецификации RFC 7232.

Для мобильных приложений Conditional GET — один из самых эффективных способов оптимизации сетевого трафика. Типичный сценарий: при открытии приложения клиент отправляет серию условных GET-запросов для загрузки ленты, профиля и настроек. Если данные не изменились, приложение получает 304 и использует локальную копию. Это занимает миллисекунды вместо секунд и не расходует мобильный трафик.

По данным Google Web Fundamentals (2025), внедрение Conditional GET-запросов в мобильном приложении сокращает среднее время загрузки на 40–60% для повторных посещений и снижает расход трафика на 70–90% для страниц с редкими обновлениями. Особенно заметен эффект на медленных соединениях (3G, Edge), где каждый байт на счету.

Как работает условный GET-запрос

Процесс состоит из трёх шагов. Первый — клиент отправляет обычный GET-запрос, сервер возвращает ресурс вместе с заголовками кэширования (ETag, Last-Modified). Второй — клиент сохраняет ресурс и его валидаторы локально. Третий — при повторном запросе клиент отправляет GET с If-None-Match (для ETag) и/или If-Modified-Since (для Last-Modified). Сервер проверяет валидаторы и отвечает 304, если ресурс не изменился, либо 200 с новыми данными.

Сервер использует приоритет ETag перед Last-Modified при наличии обоих заголовков. Это связано с тем, что ETag обеспечивает более точную валидацию — хеш содержимого меняется при любом изменении, тогда как Last-Modified имеет разрешение в одну секунду. Если ETag совпадает, сервер сразу возвращает 304, не проверяя Last-Modified.

Пример полного цикла Conditional GET в последовательности запросов:

kotlin
// Step 1: First request — get data and ETag
GET /api/profile
Response: 200 OK
ETag: "33a64df551425fcc55e"
Body: { "name": "Alice" }

// Step 2: Repeat request — with If-None-Match
GET /api/profile
If-None-Match: "33a64df551425fcc55e"
Response: 304 Not Modified
// Response body is absent — use local copy

Во втором запросе сервер сравнивает ETag из If-None-Match с текущим хешем ресурса. При совпадении возвращается 304 без тела — клиент продолжает использовать кэшированные данные. Это и есть суть Conditional GET: минимум трафика при максимальной актуальности данных.

Conditional GET против обычного GET

Обычный GET-запрос всегда возвращает полный ответ 200 OK с телом. Даже если ресурс не изменился, сервер передаёт все данные заново. Это приемлемо для небольших ресурсов или при редких запросах, но для мобильных приложений с сотнями запросов при каждом запуске такой подход приводит к избыточному расходу трафика и батареи.

Conditional GET добавляет накладные расходы в виде заголовков (обычно 50–200 байт на запрос), но экономит килобайты и мегабайты при ответе 304. Чем больше ресурс, тем выгоднее условный запрос. Для изображений, списков данных и JSON-документов размером от 10 КБ Conditional GET окупается с первого же повторного запроса.

Сравнительная характеристика двух подходов:

ПараметрОбычный GETConditional GET
Трафик (нет изменений)Полный ответТолько заголовки (~200 байт)
ЗадержкаПолная загрузкаМиллисекунды (304)
Нагрузка на серверГенерация + передачаТолько проверка ETag
Сложность реализацииМинимальнаяТребует хранения ETag
Эффективность для больших данныхНизкаяВысокая

Примеры реализации на Kotlin

Рассмотрим полноценную реализацию Conditional GET на Kotlin с использованием OkHttp и Room для хранения ETag. Приложение списка задач загружает задачи с сервера и использует условные запросы для минимизации трафика. ETag хранятся в локальной базе данных для сохранения между сессиями.

Репозиторий с Conditional GET на Kotlin:

kotlin
class TaskRepository(
    private val api: TaskApi,
    private val etagDao: EtagDao
) {
    suspend fun getTasks(): List<Task> {
        val savedEtag = etagDao.getEtag("tasks")

        val response = api.fetchTasks(
            ifNoneMatch = savedEtag
        )

        return when (response.code()) {
            304 -> taskDao.getAll() // from local cache
            200 -> {
                response.header("ETag")?.let {
                    etagDao.saveEtag("tasks", it)
                }
                val tasks = response.body() ?: emptyList()
                taskDao.replaceAll(tasks)
                tasks
            }
            else -> throw Exception(
                "Sync failed: ${response.code()}")
        }
    }
}

TaskRepository проверяет код ответа: 304 означает отсутствие изменений, и данные возвращаются из локального кэша Room. При 200 новый ETag сохраняется, а задачи обновляются в локальной базе. Этот паттерн — стандарт для мобильных приложений с синхронизацией через REST API.

Применение Conditional GET в мобильной разработке

Conditional GET широко используется в мобильных приложениях для оптимизации синхронизации данных. Основные сценарии: загрузка ленты новостей (Twitter, Instagram периодически опрашивают API с If-None-Match), обновление профиля пользователя, загрузка списка уведомлений и синхронизация задач. В каждом случае приложение может проверять актуальность данных, не загружая их повторно.

Для офлайн-first приложений Conditional GET служит первым этапом синхронизации. Приложение сначала отправляет условные GET-запросы для всех ресурсов, которые были изменены локально с последней синхронизации. Ресурсы с 304 не требуют загрузки. После этого приложение отправляет PUT/POST для локальных изменений. Такой двухфазный подход обеспечивает минимальный расход трафика.

В комбинации с Conflict Resolution Conditional GET позволяет эффективно детектировать конфликты. Если клиент получил 200 с новыми данными (ресурс изменился), но у клиента есть неотправленные локальные изменения — регистрируется конфликт. Клиент может либо применить LWW (локальные изменения теряются), либо запустить Merge Strategy для объединения локальных и удалённых изменений. По данным Meta Engineering Blog (2025), внедрение Conditional GET в Messenger сократило средний расход трафика на синхронизацию на 73%.

Часто задаваемые вопросы

Что такое Conditional GET запрос?

Conditional GET — HTTP GET-запрос с условными заголовками (If-None-Match, If-Modified-Since). Сервер возвращает 304 Not Modified, если ресурс не изменился, или 200 с новыми данными. Это механизм эффективного кэширования.

Чем Conditional GET отличается от обычного запроса?

Обычный GET всегда возвращает полный ответ с телом. Conditional GET добавляет заголовки проверки версии (ETag, дата). Если данные не изменились, сервер отвечает 304 без тела, экономя трафик и время загрузки.

Как использовать Conditional GET для кэширования?

Для эффективного кэширования сохраняйте ETag и Last-Modified из каждого ответа сервера в локальную базу данных. При следующем запросе отправляйте их в заголовках If-None-Match и If-Modified-Since. При 304 используйте данные из локального кэша.

Как Conditional GET помогает экономить трафик?

При 304 ответе сервер не передаёт тело ответа — только заголовки (~200 байт). Для ресурса размером 50 КБ это означает экономию 99.6% трафика. Для приложения, которое синхронизируется 50 раз в день, экономия достигает десятков мегабайт в месяц.

Можно ли использовать Conditional GET для синхронизации?

Да, это стандартный подход для дельта-синхронизации. Клиент проверяет актуальность каждого ресурса через Conditional GET, загружает только изменившиеся и отправляет локальные изменения. Такой подход используется в Twitter, Instagram, Telegram и большинстве современных API.

Итоги

  • Conditional GET — HTTP-механизм проверки актуальности кэшированных ресурсов через условные заголовки If-None-Match и If-Modified-Since.
  • 304 Not Modified — ответ сервера, указывающий, что ресурс не изменился. Тело ответа не передаётся, экономя трафик и время загрузки.
  • ETag vs Last-Modified — ETag точнее (хеш содержимого), Last-Modified проще (дата). Рекомендуется комбинировать оба для максимальной эффективности.
  • Экономия трафика — для неизменённых ресурсов Conditional GET сокращает объём передаваемых данных на 70–95% в зависимости от размера ресурса.
  • Применение — стандартный механизм синхронизации в Twitter, Instagram, Telegram и большинстве современных REST API.
  • Интеграция — на клиенте требуется хранение ETag в локальной базе данных, на сервере — генерация и сравнение ETag при каждом запросе.
  • Рекомендация — реализуйте Conditional GET для всех GET-эндпоинтов в мобильном API. Это самый дешёвый способ оптимизации с наибольшим эффектом для пользователей.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также