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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође