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 εγγυώνται ότι ο πόρος δεν έχει αλλάξει byte προς byte. Είναι υποχρεωτικά για αιτήματα εύρους (Range requests) και για έλεγχο ακεραιότητας μερικών μεταφορτώσεων.
Αδύναμο ETag (weak ETag) — αναγνωριστικά με πρόθεμα W/, για παράδειγμα W/"abc123def". Επιτρέπουν στον πόρο να είναι σημασιολογικά ισοδύναμος, ακόμα κι αν η αναπαράσταση byte διαφέρει. Τα αδύναμα ETag είναι χρήσιμα για διακομιστές που δημιουργούν δυναμικά αποκρίσεις με διαφορετικά κενά ή μορφοποίηση αλλά ίδιο νόημα. Ωστόσο, τα αδύναμα ETag δεν υποστηρίζουν αιτήματα εύρους.
Σύγκριση τύπων ETag:
| Χαρακτηριστικό | Ισχυρό ETag | Αδύναμο ETag |
|---|---|---|
| Μορφή | "hash" | W/"hash" |
| Ευαισθησία | Byte προς byte | Σημασιολογική |
| Αιτήματα εύρους | Υποστηρίζονται | Δεν υποστηρίζονται |
| Προσωρινή αποθήκευση 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 και ο πελάτης ολοκληρώνει τον συγχρονισμό. Αν υπάρχουν αλλαγές, ο διακομιστής επιστρέφει μόνο τους τροποποιημένους πόρους. Αυτή η προσέγγιση ονομάζεται συγχρονισμός δέλτα και είναι κρίσιμη για συσκευές κινητών με περιορισμένη κίνηση.
Σε σενάρια με αισιόδοξο κλείδωμα, το ETag χρησιμοποιείται για την πρόληψη συγκρούσεων Lost Update. Όταν ο πελάτης στέλνει αίτημα PUT για ενημέρωση του πόρου, συμπεριλαμβάνει την κεφαλίδα If-Match: "etag". Αν το ETag δεν ταιριάζει (άλλος πελάτης έχει ήδη τροποποιήσει τον πόρο), ο διακομιστής απαντά με 412 Precondition Failed και ο πελάτης πρέπει να μεταφορτώσει ξανά την τρέχουσα έκδοση και να επαναλάβει την αλλαγή. Αυτή η προσέγγιση εξασφαλίζει συνέπεια δεδομένων χωρίς κλειδώματα σε επίπεδο βάσης δεδομένων.
Για κατανεμημένα συστήματα με λειτουργία εκτός σύνδεσης, το ETag χρησιμοποιείται σε συνδυασμό με Επίλυση Συγκρούσεων. Ο πελάτης συγχρονίζεται λαμβάνοντας τα τρέχοντα 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 (χωρίς πρόθεμα) διακρίνουν τους πόρους byte προς byte. Αδύναμα ETag (με πρόθεμα W/) επιτρέπουν σημασιολογική ισοδυναμία. Τα ισχυρά απαιτούνται για αιτήματα εύρους, τα αδύναμα για δυναμικά παραγόμενο περιεχόμενο.
Το ETag μειώνει την κίνηση κατά 80–90%: ο πελάτης ελέγχει την επικαιρότητα όλων των πόρων μέσω If-None-Match, μεταφορτώνοντας μόνο τους αλλαγμένους. Χωρίς ETag, ο πελάτης θα μεταφόρτωνε πλήρη δεδομένα σε κάθε συγχρονισμό, σπαταλώντας κίνηση και μπαταρία.
Ο διακομιστής υπολογίζει το ETag ως κατακερματισμό (MD5, SHA-256) του περιεχομένου απόκρισης ή χρησιμοποιεί τον αριθμό έκδοσης της εγγραφής από τη βάση δεδομένων. Στο Spring Boot, η σημείωση @Cacheable με etag = true είναι επαρκής. Στο Express.js, το middleware etag είναι ενεργοποιημένο από προεπιλογή.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης