ETag: ما هو، آلية التخزين المؤقت وتكوين الرأس

المؤلف: IT Sectr نُشر: 2026-03-09 وقت القراءة: 8 دق

ETag (Entity Tag) هو رأس HTTP يخصص معرفاً فريداً لإصدار مورد على الخادم، مما يسمح للعميل بالتحقق بكفاءة من صلاحية البيانات المخزنة مؤقتاً. عند الطلب المتكرر، يرسل المتصفح أو التطبيق ETag المحفوظ، ويقارنه الخادم بالحالي: في حالة التطابق، يتم إرجاع الحالة 304 Not Modified بدون نص استجابة. وفقاً لـ RFC 7232 (IETF, 2014)، تقلل الطلبات الشرطية مع ETag حجم البيانات المنقولة بنسبة تصل إلى 95% للموارد المطلوبة بشكل متكرر. وهذا يجعل الرأس بالغ الأهمية لأداء التطبيقات المحمولة.

الخلاصة

  • ETag — رأس HTTP بمعرف فريد لإصدار المورد للطلبات الشرطية والتخزين المؤقت
  • مبدأ العمل — يولد الخادم تجزئة للمحتوى أو رقم إصدار، ويرسله العميل في رأس If-None-Match
  • ETags القوية والضعيفة — القوية (المحتوى متطابق بايت ببايت) والضعيفة (المحتوى مكافئ دلالياً، البادئة W/)
  • 304 Not Modified — استجابة الخادم عند تطابق ETag، مما يوفر حركة المرور ويسرع التحميل
  • ETag مقابل Last-Modified — ETag أكثر دقة (تجزئة المحتوى)، Last-Modified أبسط (تاريخ)، معاً يعطيان أقصى كفاءة

ما هو ETag؟

ETag (Entity Tag) هو رأس استجابة HTTP يحتوي على معرف فريد لإصدار معين من مورد. يحسب الخادم ETag بناءً على محتويات الملف أو بياناته الوصفية أو رقم المراجعة ويرسله إلى العميل في الاستجابة لطلب GET. يحفظ العميل هذا المعرف وفي الطلبات اللاحقة لنفس المورد يرسله في رأس If-None-Match. إذا لم يتغير المورد، يستجيب الخادم بـ 304 Not Modified ويستخدم العميل نسخته المخزنة مؤقتاً.

يتم تعريف تنسيق ETag في RFC 7232 كسلسلة بين علامتي اقتباس: "33a64df551425fcc55e4d42a148795d9f25f89d4". يمكن أن تكون القيمة تجزئة SHA-1 لمحتويات الملف، أو رقم إصدار متزايد، أو مزيج من inode-رقم-الوقت للملفات الثابتة، أو رمزاً عشوائياً يولده الخادم. الشرط الوحيد هو أن تتغير القيمة عندما يتغير المورد وألا تتغير إذا بقي المورد كما هو.

ينتمي ETag إلى آليات الطلبات الشرطية (conditional requests) — أحد التحسينات الأساسية لبروتوكول HTTP. على عكس الطلبات غير الشرطية حيث يعيد الخادم دائماً استجابة كاملة، يسمح الطلب الشرطي للعميل بالتحقق من صلاحية التخزين المؤقت دون إعادة تحميل البيانات. وفقاً HTTP Archive (2025)، حوالي 40% من جميع استجابات HTTP هي 304 Not Modified بفضل التكوين الصحيح لـ ETag و Last-Modified.

أين يُستخدم ETag

يُستخدم ETag في REST API لتحسين تحميل مجموعات البيانات — إذا لم تتغير قائمة الكائنات، يتلقى العميل 304 دون نقل كل JSON. في الملفات الثابتة (CSS, JS, الصور)، يسمح ETag لشبكات CDN والمتصفحات بالتحقق بكفاءة من صلاحية التخزين المؤقت. في التطبيقات المحمولة، يعتبر ETag حاسماً للمزامنة في الخلفية: يتحقق التطبيق مما إذا كانت البيانات على الخادم قد تغيرت ويقوم بتنزيل التحديثات فقط عند الضرورة. وهذا يوفر حركة المرور وعمر بطارية الجهاز.

كيف يعمل ETag؟

تتكون دورة عمل ETag الكاملة من أربع خطوات. يولد الخادم ETag عند الطلب الأول ويعيده في رأس الاستجابة. يحفظ العميل ETag مع المورد المخزن مؤقتاً. عند الطلب المتكرر، يرسل العميل رأس If-None-Match مع قيمة ETag المحفوظة. يقارن الخادم القيمة المستلمة مع ETag الحالي للمورد: في حالة التطابق، يعيد 304 Not Modified بجسم فارغ؛ في حالة عدم التطابق، يعيد 200 OK مع المورد الجديد و ETag جديد.

http
// طلب العميل مع If-None-Match
GET /api/users HTTP/1.1
Host: example.com
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

// استجابة الخادم — المورد لم يتغير
HTTP/1.1 304 Not Modified
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

في تطبيق محمول، يمكن تنفيذ هذه الدورة عبر عميل HTTP مع دعم التخزين المؤقت. OkHttp، على سبيل المثال، يدير ETag تلقائياً عبر CacheInterceptor: يحفظ ETag الاستجابة ويضيف If-None-Match في الطلبات المتكررة. عند استلام 304، يعيد OkHttp البيانات المخزنة مؤقتاً. OkHttp يدعم ETag بدون تكوين إضافي — فقط قم بتمكين التخزين المؤقت عبر OkHttpClient.Builder.cache().

توليد ETag على الخادم

يمكن للخادم حساب ETags بطرق مختلفة: عبر تجزئة MD5 أو SHA للمحتوى، عبر رقم مراجعة من قاعدة البيانات (مثل updated_at من MySQL)، عبر مزيج من inode + mtime + الحجم للملفات الثابتة (يقوم Nginx بتوليد ETags بهذه الطريقة تحديداً). لواجهات API الديناميكية، تجزئة المحتوى هي الأكثر موثوقية: إذا تغير حقل واحد في استجابة JSON، فإن ETag سيتغير. ومع ذلك، حساب تجزئة عند كل طلب يثقل وحدة المعالجة المركزية — للأنظمة عالية التحميل، من الأفضل استخدام رقم إصدار متزايد.

ETags القوية والضعيفة

يحدد RFC 7232 نوعين من ETags: القوية (strong) والضعيفة (weak). يعني ETag القوي أن تمثيلين للمورد متطابقان بايت ببايت — لا يختلف بت واحد. يضمن ETag الضعيف (البادئة W/) التكافؤ الدلالي فقط: قد يختلف المحتوى على مستوى التسلسل (المسافات، ترتيب حقول JSON)، لكن البيانات تعتبر متطابقة للعميل. يتم تمييز ETags الضعيفة بالبادئة W/، على سبيل المثال W/"1a2b3c".

يعتمد اختيار نوع ETag على متطلبات دقة المقارنة. للملفات الثابتة (CSS, JS, الصور)، يفضل استخدام ETags القوية — إذا تغير الملف، يجب أن يحصل العميل على الإصدار الجديد. لواجهات API الديناميكية، حيث قد يتم تسلسل نفس JSON بترتيب حقول أو تنسيق مختلف، توفر ETags الضعيفة مرونة أكبر: يولد الخادم ETag بناءً على بيانات الأعمال وليس على التمثيل النصي.

نوع ETagالتنسيقالضمانالاستخدام
Strong (قوي)"تجزئة"تطابق بايت ببايتالملفات الثابتة، الموارد الثنائية
Weak (ضعيف)W/"تجزئة"تكافؤ دلاليAPI JSON، الصفحات الديناميكية

قيد على ETags الضعيفة: لا يمكن استخدامها مع طلبات النطاق (Range requests). إذا طلب العميل جزءاً من ملف، يجب على الخادم إرجاع ETag قوي لضمان أن الجزء يتوافق مع المورد الكامل. ETags الضعيفة لا توفر هذا الضمان. في السيناريوهات الأخرى، ETags الضعيفة آمنة وموصى بها لواجهات API.

ETag مقابل Last-Modified

ETag و Last-Modified هما رأسان HTTP للطلبات الشرطية يُستخدمان معاً غالباً. يشير Last-Modified إلى تاريخ آخر تعديل للمورد ويعمل مع رأس If-Modified-Since. يوفر ETag معرف إصدار فريداً ويعمل مع If-None-Match. لكل منهما مزاياه وقيوده، والجمع بينهما يعطي أقصى كفاءة للتخزين المؤقت.

Last-Modified أبسط في التنفيذ — يحصل الخادم تلقائياً على التاريخ من نظام الملفات أو يحدّث حقل updated_at في قاعدة البيانات. ومع ذلك، دقة التاريخ بالثواني، وهو غير كافٍ للموارد التي تتغير عدة مرات في الثانية. بالإضافة إلى ذلك، لا يميز Last-Modified بين الحالات المختلفة: إذا تمت إعادة كتابة ملف بنفس الإصدار، يتغير التاريخ لكن المحتوى لا يتغير، وسيعيد العميل تحميل بيانات متطابقة.

ETag أكثر دقة: يتغير فقط عندما يتغير المحتوى فعلياً. إذا استعاد الخادم إصداراً سابقاً من نسخة احتياطية، يتغير ETag. إذا تمت إعادة كتابة ملف بنفس البيانات، يبقى ETag كما هو ولا يعيد العميل التحميل. الاستخدام المشترك موصى به من قبل مواصفات HTTP: يعيد الخادم كلا الرأسين، ويرسل العميل If-None-Match و If-Modified-Since في وقت واحد. إذا أشار رأس واحد على الأقل إلى تغيير، يعيد الخادم مورداً جديداً.

أولوية الرؤوس

وفقاً للمواصفات، ETag له أولوية على Last-Modified. إذا تلقى الخادم If-None-Match، يجب عليه التحقق من ETag فقط، متجاهلاً If-Modified-Since. هذا يمنع حالات السباق: إذا تغير المورد بين إرسال العميل Last-Modified والتحقق على الخادم، سيكون ETag المؤشر الأحدث. عملياً، تتحقق الخوادم عادةً من كلا الرأسين، ولكن عندما تتعارض النتائج، يفوز ETag.

تنفيذ ETag على الخادم

يعتمد تكوين ETag على نوع الخادم. يقوم Nginx بتوليد ETags للملفات الثابتة تلقائياً بناءً على inode و mtime والحجم. يستخدم Apache آلية FileETag. للتطبيقات الديناميكية على Node.js، PHP، Python، Ruby، يجب توليد ETags برمجياً — عبر تجزئة الاستجابة أو رقم إصدار البيانات أو مزيج من معاملات الطلب.

go
func etagMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter,
        r *http.Request) {
        // توليد ETag بناءً على البيانات
        etag := generateETag(r.URL.Path)
        w.Header().Set("ETag", etag)

        // التحقق من If-None-Match
        if r.Header.Get("If-None-Match") == etag {
            w.WriteHeader(http.StatusNotModified)
            return
        }
        next.ServeHTTP(w, r)
    })
}

يعترض Middleware بلغة Go الطلب، ويولد ETag لعنوان URL المطلوب (على سبيل المثال، يحسب تجزئة بيانات من التخزين المؤقت أو قاعدة البيانات) ويضبط رأس الاستجابة. إذا أرسل العميل If-None-Match وتطابق مع ETag الحالي، يعيد الخادم 304 Not Modified فوراً، دون استدعاء المعالج الرئيسي. في الإنتاج، يجب إضافة تخزين مؤقت لـ ETags المحسوبة حسب URL والمعاملات لتقليل الحمل على الخادم.

المشكلات والمزالق

في تكوين متعدد الخوادم (round-robin أو anycast)، يجب أن يكون ETag نفسه على جميع العقد لنفس المورد. إذا تم توليد ETag بناءً على inode الملف وكان الموقع منشوراً على عدة خوادم، ستختلف القيم. الحل هو استخدام تجزئة المحتوى أو تخزين مركزي للإصدارات (Redis, etcd). المشكلة الثانية هي ضغط gzip: يغير Nginx ETag عند تمكين الضغط، مما قد يسبب استجابات 304 زائدة. يجب تكوين gzip_vary on لمزامنة ETag مع المحتوى المضغوط.

الأسئلة الشائعة

هل يمكن أن يكون ETag متطابقاً لموارد مختلفة؟

نعم، إذا لم يمنع الخادم ذلك صراحةً. لا يجب أن يكون ETag فريداً عالمياً — إنه فريد ضمن عنوان URL محدد. للملفات الثابتة، الاصطدامات غير محتملة عند استخدام تجزئة SHA، لكن المولدات المخصصة قد تنتج تكرارات.

هل أحتاج إلى تكوين ETag لكل مورد؟

ETag الأكثر فعالية للموارد التي تُطلب بشكل متكرر ونادراً ما تتغير: الملفات الثابتة، قوائم API، التكوينات. للصفحات الفريدة التي تُحمل مرة واحدة (مثل صفحة تأكيد الطلب)، لا يوفر ETag فائدة.

كيف يعمل ETag مع CDN؟

تأخذ شبكات CDN بعين الاعتبار ETag في طلبات الأصل للتحقق من صلاحية التخزين المؤقت. إذا تغير ETag لمورد على الأصل، يقوم CDN بتحميل الإصدار الجديد. Cloudflare و Fastly يدعمان ETag كآلية قياسية لإبطال التخزين المؤقت على مستوى الأصل.

هل يمكن أن يكون ETag أطول من 255 حرفاً؟

لا يحدد RFC 7232 طول ETag، لكن الخوادم والبروكسيات قد تقطع أو تتجاهل القيم الطويلة جداً. يوصى باستخدام تجزئة بطول 20–40 حرفاً أو مزيج من معرف الإصدار والمجموع الاختباري.

ماذا تختار: ETag أم Cache-Control؟

هذه ليست آليات متعارضة. يحدد Cache-Control سياسة التخزين المؤقت (مدة التخزين، من المسموح له)، بينما ETag هو آلية تحقق للموارد المخزنة مؤقتاً. التكوين الأمثل يشمل كلا الرأسين معاً.

الملخص

  • ETag — رأس HTTP بمعرف فريد لإصدار المورد للطلبات الشرطية والتخزين المؤقت الفعال
  • المبدأ — يرسل العميل If-None-Match مع ETag المحفوظ، ويستجيب الخادم بـ 304 عند التطابق
  • ETags القوية — تطابق بايت ببايت للملفات الثابتة، الضعيفة — تكافؤ دلالي لواجهات API
  • ETag أكثر دقة من Last-Modified — يتتبع المحتوى وليس التاريخ، ويتغير فقط مع التعديلات الفعلية
  • الاستخدام المشترك مع Last-Modified يعطي أقصى كفاءة للتخزين المؤقت
  • جانب الخادم — التوليد عبر تجزئة المحتوى أو رقم إصدار البيانات أو مزيج من المعاملات
  • التوصية — استخدام ETag لجميع نقاط نهاية API والموارد الثابتة في التطبيقات المحمولة

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا