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 — е GET заявка, съдържаща една или повече условни заглавки, въз основа на които сървърът решава дали да върне пълен отговор или само статус 304 Not Modified. Основната цел е да се избегне предаването на тялото на отговора, ако ресурсът не се е променил от последната заявка. Това е основен механизъм на HTTP кеширане, дефиниран в спецификацията RFC 7232.
За мобилни приложения Conditional GET е един от най-ефективните начини за оптимизиране на мрежовия трафик. Типичен сценарий: при отваряне на приложението клиентът изпраща серия от условни GET заявки за зареждане на емисията, профила и настройките. Ако данните не са се променили, приложението получава 304 и използва локално копие. Това отнема милисекунди вместо секунди и не изразходва мобилен трафик.
Според Google Web Fundamentals (2025), внедряването на условни GET заявки в мобилно приложение намалява средното време за зареждане с 40–60% за повторни посещения и намалява консумацията на трафик със 70–90% за страници с редки актуализации. Ефектът е особено забележим при бавни връзки (3G, Edge), където всеки байт е от значение.
Процесът се състои от три стъпки. Първа — клиентът изпраща обикновена 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 в последователността на заявките:
// Стъпка 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: минимален трафик при максимална актуалност на данните.
Обикновената GET заявка винаги връща пълен отговор 200 OK с тяло. Дори ако ресурсът не е променен, сървърът предава всички данни отново. Това е приемливо за малки ресурси или редки заявки, но за мобилни приложения със стотици заявки при всяко стартиране, такъв подход води до прекомерна консумация на трафик и батерия.
Conditional GET добавя допълнителен товар под формата на заглавки (обикновено 50–200 байта на заявка), но спестява килобайти и мегабайти при отговор 304. Колкото по-голям е ресурсът, толкова по-изгодна е условната заявка. За изображения, списъци с данни и JSON документи с размер от 10 KB нагоре, Conditional GET се изплаща още от първата повторна заявка.
Сравнение на двата подхода:
| Параметър | Обикновена GET | Conditional GET |
|---|---|---|
| Трафик (без промени) | Пълен отговор | Само заглавки (~200 байта) |
| Закъснение | Пълно зареждане | Милисекунди (304) |
| Натоварване на сървъра | Генериране + предаване | Само проверка на ETag |
| Сложност на реализацията | Минимална | Изисква съхранение на ETag |
| Ефективност за големи данни | Ниска | Висока |
Нека разгледаме пълна реализация на Conditional GET в Kotlin с използване на OkHttp и Room за съхранение на ETag. Приложение за списък със задачи зарежда задачи от сървъра и използва условни заявки за минимизиране на трафика. ETag се съхраняват в локална база данни за запазване между сесиите.
Репозиториум с Conditional GET в 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 се използва широко в мобилни приложения за оптимизиране на синхронизацията на данни. Основни сценарии: зареждане на новинарска емисия (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 — HTTP GET заявка с условни заглавки (If-None-Match, If-Modified-Since). Сървърът връща 304 Not Modified, ако ресурсът не е променен, или 200 с нови данни. Това е механизъм за ефективно кеширане.
Обикновената GET винаги връща пълен отговор с тяло. Conditional GET добавя заглавки за проверка на версията (ETag, дата). Ако данните не са се променили, сървърът отговаря с 304 без тяло, спестявайки трафик и време за зареждане.
За ефективно кеширане запазвайте ETag и Last-Modified от всеки отговор на сървъра в локална база данни. При следващата заявка ги изпращайте в заглавките If-None-Match и If-Modified-Since. При 304 използвайте данните от локалния кеш.
При отговор 304 сървърът не предава тяло на отговора — само заглавки (~200 байта). За ресурс с размер 50 KB това означава спестяване на 99.6% от трафика. За приложение, което се синхронизира 50 пъти дневно, спестяването достига десетки мегабайта на месец.
Да, това е стандартният подход за делта синхронизация. Клиентът проверява актуалността на всеки ресурс чрез Conditional GET, зарежда само променените и изпраща локални промени. Този подход се използва в Twitter, Instagram, Telegram и повечето съвременни API.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също