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 شرطی در برنامه موبایل میانگین زمان بارگذاری را برای بازدیدهای مکرر ۴۰–۶۰٪ کاهش میدهد و مصرف ترافیک را برای صفحات با بهروزرسانی نادر ۷۰–۹۰٪ کاهش میدهد. این اثر به ویژه در اتصالات کند (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 در توالی درخواستها:
// مرحله ۱: درخواست اول — دریافت داده و ETag
GET /api/profile
Response: 200 OK
ETag: "33a64df551425fcc55e"
Body: { "name": "Alice" }
// مرحله ۲: تکرار درخواست — با 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 سربار اضافی به صورت هدرها (معمولاً ۵۰–۲۰۰ بایت در هر درخواست) اضافه میکند، اما در پاسخ 304 کیلوبایت و مگابایت صرفهجویی میکند. هرچه منبع بزرگتر باشد، درخواست شرطی مقرونبهصرفهتر است. برای تصاویر، لیستهای داده و اسناد JSON با اندازه ۱۰ کیلوبایت به بالا، Conditional GET از اولین درخواست مجدد به صرفه میشود.
مقایسه دو رویکرد:
| پارامتر | GET معمولی | Conditional GET |
|---|---|---|
| ترافیک (بدون تغییر) | پاسخ کامل | فقط هدرها (~۲۰۰ بایت) |
| تأخیر | بارگذاری کامل | میلیثانیه (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 را برای تغییرات محلی ارسال میکند. چنین رویکرد دو مرحلهای حداقل مصرف ترافیک را تضمین میکند.
در ترکیب با حل تعارض، Conditional GET امکان تشخیص مؤثر تعارضات را فراهم میکند. اگر کلاینت 200 با دادههای جدید دریافت کرده است (منبع تغییر کرده)، اما کلاینت تغییرات محلی ارسالنشده دارد — یک تعارض ثبت میشود. کلاینت میتواند LWW را اعمال کند (تغییرات محلی از دست میروند) یا استراتژی ادغام را برای ترکیب تغییرات محلی و راه دور اجرا کند. به گفته Meta Engineering Blog (2025)، پیادهسازی Conditional GET در Messenger میانگین مصرف ترافیک همگامسازی را ۷۳٪ کاهش داد.
سؤالات متداول
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 سرور بدنه پاسخ را منتقل نمیکند — فقط هدرها (~۲۰۰ بایت). برای منبعی با اندازه ۵۰ کیلوبایت این به معنای صرفهجویی ۹۹.۶٪ ترافیک است. برای برنامهای که ۵۰ بار در روز همگامسازی میکند، صرفهجویی به دهها مگابایت در ماه میرسد.
بله، این رویکرد استاندارد برای همگامسازی دلتا است. کلاینت بهروزرسانی هر منبع را از طریق Conditional GET بررسی میکند، فقط منابع تغییر کرده را بارگذاری میکند و تغییرات محلی را ارسال میکند. این رویکرد در Twitter، Instagram، Telegram و اکثر APIهای مدرن استفاده میشود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.