ETag — هدر پاسخ HTTP حاوی شناسه یکتای نسخه منبع. سرور ETag را به عنوان هش محتوا یا شماره نسخه تولید میکند و همراه با دادهها به کلاینت بازمیگرداند. در درخواستهای بعدی، کلاینت این شناسه را در هدر If-None-Match ارسال میکند و به سرور امکان میدهد بررسی کند که آیا منبع تغییر کرده است. به گفته MDN Web Docs, 2025، ETag اساس مکانیسم درخواستهای GET شرطی در HTTP است. درخواستهای شرطی با ETag حجم دادههای منتقل شده در حین همگامسازی برنامههای موبایل را تا 90% کاهش میدهند.
نکات اصلی
ETag (Entity Tag) — هدر HTTP از خانواده هدرهای شرطی که اعتبارسنجی منابع ذخیره شده در کش را فراهم میکند. سرور ETag را به صورت جمع هش (MD5، SHA-256) یا شماره نسخه منبع محاسبه کرده و در پاسخ به درخواست GET بازمیگرداند. کلاینت ETag را همراه با دادهها ذخیره میکند و در درخواست بعدی آن را در هدر If-None-Match ارسال میکند. اگر محتوای منبع تغییر نکرده باشد، سرور با وضعیت 304 Not Modified بدون بدنه پاسخ میدهد.
برای برنامههای موبایل، ETag حیاتی است زیرا حجم دادههای دانلودی را کاهش میدهد. در هر اجرا یا همگامسازی، برنامه با درخواست If-None-Match صحت منابع را بررسی میکند — به جای دانلود کامل دادهها، 304 دریافت کرده و از نسخه محلی استفاده میکند. به گفته Google Chrome Team (2024)، استفاده از ETag در APIهای موبایل حجم متوسط پاسخ را برای لیستها 87% و برای اشیاء منفرد 94% کاهش میدهد.
ETag در سمت سرور تولید میشود و میتواند هم قطعی (یکسان برای محتوای یکسان، که برای کشهای اشتراکی مفید است) و هم منحصربهفرد برای هر پاسخ (برای اعتبارسنجی دقیق) باشد. در REST APIهای طراحی شده برای همگامسازی موبایل، معمولاً از ترکیب هش محتوا و شماره نسخه رکورد در پایگاه داده استفاده میشود.
ETag قوی (strong ETag) — شناسههایی که با هر تغییر محتوا، از جمله تغییرات جزئی (فاصلهها، قالببندی) تغییر میکنند. قالب: "abc123def" (در داخل گیومه، بدون پیشوند). ETagهای قوی تضمین میکنند که منبع بایت به بایت تغییر نکرده است. آنها برای درخواستهای محدوده (Range requests) و بررسی integrity دانلودهای جزئی الزامی هستند.
ETag ضعیف (weak ETag) — شناسههایی با پیشوند W/، مانند W/"abc123def". آنها معادلسازی معنایی منبع را حتی در صورت تفاوت نمایش بایتی مجاز میدانند. ETagهای ضعیف برای سرورهایی مفید هستند که پاسخهایی با فاصلهها یا قالببندی متفاوت اما معنای یکسان تولید میکنند. با این حال، ETagهای ضعیف از درخواستهای محدوده پشتیبانی نمیکنند.
مقایسه انواع ETag:
| ویژگی | ETag قوی | ETag ضعیف |
|---|---|---|
| قالب | "hash" | W/"hash" |
| حساسیت | بایت به بایت | معنایی |
| درخواستهای محدوده | پشتیبانی میشود | پشتیبانی نمیشود |
| کش کردن CDN | ایدهآل | محدود |
| همگامسازی | دقت بالا | مجاز به برخورد |
Last-Modified — هدر HTTP که تاریخ و زمان آخرین تغییر منبع را نشان میدهد. کلاینت آن را در هدر If-Modified-Since بازمیگرداند. Last-Modified پیادهسازی سادهتری دارد (سرور فقط به تاریخ نیاز دارد)، اما محدودیتهای اساسی دارد: دقت یک ثانیه (دو تغییر در یک ثانیه قابل تشخیص نیستند) و عدم توانایی در تعیین تغییر محتوا با همان زمان (مثلاً پس از بازیابی از پشتیبان).
ETag این مشکلات را حل میکند: هش محتوا مستقل از زمان با هر تغییری تغییر میکند. به همین دلیل REST APIهای مدرن از ترکیب هر دو هدر استفاده میکنند: ETag برای اعتبارسنجی دقیق و Last-Modified برای فیلتر تقریبی در CDN. Apache HTTP Server و Nginx به طور پیشفرض هر دو هدر را برای فایلهای ایستا تولید میکنند.
برای برنامههای موبایل با همگامسازی، ETag حیاتیتر است زیرا امکان تشخیص تداخل ویرایش را فراهم میکند. اگر کلاینت درخواست PUT را با هدر If-Match: "etag" ارسال کند، در صورت تغییر منبع توسط کلاینت دیگر، سرور درخواست را رد میکند (قفل خوشبینانه). Last-Modified به دلیل دقت ثانیهای نمیتواند چنین اطمینانی را تضمین کند.
پیادهسازی سمت کلاینت ETag را در یک برنامه موبایل با Kotlin با استفاده از Retrofit و OkHttp بررسی میکنیم. در هر درخواست GET، کلاینت ETag را از پاسخ ذخیره میکند و در درخواست بعدی آن را در هدر If-None-Match ارسال میکند. اگر سرور 304 بازگرداند، دادهها دوباره دانلود نمیشوند.
پیکربندی کلاینت OkHttp با کش ETag:
class EtagClient {
private val etagCache =
mutableMapOf<String, String>()
private val client = OkHttpClient.Builder().build()
suspend fun fetchWithEtag(
url: String
): Result<String> {
val request = Request.Builder()
.url(url)
.header("If-None-Match",
etagCache[url] ?: "")
.build()
val response = client.newCall(request).await()
return when (response.code) {
304 -> Result.success(
"not_modified")
200 -> {
response.header("ETag")?.let {
etagCache[url] = it
}
Result.success(response.body?.string()
?: "")
}
else -> Result.failure(
Exception("HTTP ${response.code}"))
}
}
}
کلاینت ETag را پس از پاسخ موفق 200 ذخیره میکند و در درخواست بعدی آن را در هدر If-None-Match ارسال میکند. در صورت 304، کلاینت میداند که نسخه محلی بهروز است و ترافیک را برای دانلود مجدد دادهها هدر نمیدهد. این الگو هزینههای شبکه برنامه موبایل را برای منابع پر درخواست 80–90% کاهش میدهد.
ETag مکانیسم کلیدی برای بهینهسازی همگامسازی برنامههای موبایل با REST API است. در طرح استاندارد همگامسازی، کلاینت ابتدا لیست منابع را با اعتبارسنجی ETag درخواست میکند — اگر هیچ منبعی تغییر نکرده باشد، سرور 304 بازمیگرداند و کلاینت همگامسازی را پایان میدهد. اگر تغییراتی وجود داشته باشد، سرور فقط منابع تغییر یافته را بازمیگرداند. این رویکرد همگامسازی تفاضلی (delta-sync) نام دارد و برای دستگاههای موبایل با ترافیک محدود حیاتی است.
در سناریوهای قفل خوشبینانه، ETag برای جلوگیری از تداخل Lost Update استفاده میشود. وقتی کلاینت درخواست PUT برای بهروزرسانی منبع ارسال میکند، هدر If-Match: "etag" را اضافه میکند. اگر ETag مطابقت نداشته باشد (کلاینت دیگری منبع را تغییر داده است)، سرور با 412 Precondition Failed پاسخ میدهد و کلاینت باید نسخه بهروز را دوباره دانلود کرده و تغییر را تکرار کند. این رویکرد بدون قفل در سطح پایگاه داده، سازگاری دادهها را تضمین میکند.
برای سیستمهای توزیعشده با حالت آفلاین، ETag در ترکیب با حل تعارض (Conflict Resolution) استفاده میشود. کلاینت با دریافت ETagهای فعلی برای همه منابع همگامسازی میکند. هنگام ارسال تغییرات، سرور If-Match را بررسی میکند — اگر ETag مطابقت نداشته باشد، تعارضی ثبت میشود که طبق استراتژی انتخاب شده (LWW، Merge) حل میشود. طبق گزارش Postman API Report (2025)، 67% از REST APIهای تولیدی برای برنامههای موبایل از ETag به عنوان مکانیسم اصلی اعتبارسنجی نسخه استفاده میکنند.
سوالات متداول
ETag — هدر پاسخ HTTP حاوی شناسه یکتای نسخه منبع. کلاینت از آن برای درخواستهای شرطی استفاده میکند: اگر منبع تغییر نکرده باشد، سرور بدون بدنه پاسخ 304 Not Modified بازمیگرداند و در ترافیک صرفهجویی میکند.
ETag از هش محتوا برای مقایسه دقیق استفاده میکند. Last-Modified بر اساس تاریخ تغییر با دقت یک ثانیه است. ETag برای تشخیص تغییرات واقعی قابل اعتمادتر است و از قفل خوشبینانه از طریق If-Match پشتیبانی میکند.
ETag قوی (بدون پیشوند) منابع را بایت به بایت تشخیص میدهد. ETag ضعیف (با پیشوند W/) معادلسازی معنایی را مجاز میداند. ETagهای قوی برای درخواستهای محدوده الزامی هستند، ETagهای ضعیف برای محتوای تولید شده پویا مناسباند.
ETag ترافیک را 80–90% کاهش میدهد: کلاینت صحت همه منابع را از طریق If-None-Match بررسی میکند و فقط منابع تغییر یافته را دانلود میکند. بدون ETag، کلاینت در هر همگامسازی دادههای کامل را دانلود میکرد و ترافیک و باتری هدر میرفت.
سرور ETag را به عنوان هش (MD5، SHA-256) محتوای پاسخ محاسبه میکند یا از شماره نسخه رکورد در پایگاه داده استفاده میکند. در Spring Boot، annotation @Cacheable با etag = true کافی است. در Express.js، middleware etag به طور پیشفرض فعال است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.