Conditional GET: що це, механізм умовного запиту

Автор: IT Sectr Опубліковано: 2026-06-14 Час читання: 7 хв

Conditional 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), впровадження умовних 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
// Крок 1: Перший запит — отримати дані та ETag
GET /api/profile
Response: 200 OK
ETag: "33a64df551425fcc55e"
Body: { "name": "Alice" }

// Крок 2: Повторити запит — з If-None-Match
GET /api/profile
If-None-Match: "33a64df551425fcc55e"
Response: 304 Not Modified
// Тіло відповіді відсутнє — використати локальну копію

У другому запиті сервер порівнює 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() // з локального кешу
            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), оновлення профілю користувача, завантаження списку сповіщень та синхронізація завдань. У кожному випадку застосунок може перевіряти актуальність даних, не завантажуючи їх повторно.

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

У комбінації з вирішенням конфліктів Conditional GET дозволяє ефективно виявляти конфлікти. Якщо клієнт отримав 200 з новими даними (ресурс змінився), але має невідправлені локальні зміни — реєструється конфлікт. Клієнт може або застосувати LWW (локальні зміни втрачаються), або запустити стратегію об’єднання для злиття локальних та віддалених змін. За даними 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

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