2008-09-04 11 views

Antwort

9

Apache verwendet das Standardformat von inode-filesize-mtime. Der einzige Nachteil hierbei ist, dass die mtime epoch Zeit und mit Nullen aufgefüllt werden muss, so dass es 16 Ziffern ist. Hier ist, wie man es in PHP macht:

$fs = stat($file); 
header("Etag: ".sprintf('"%x-%x-%s"', $fs['ino'], $fs['size'],base_convert(str_pad($fs['mtime'],16,"0"),10,16))); 
+1

Warum nicht 'header (sprintf ('Etag:"% x-% x-% 016x "', $ fs ['ino'], $ fs ['größe'], $ fs ['mtime'])) ; '? –

+1

Ich habe festgestellt, dass der MTime-Teil des ETag meines Apache-Servers tatsächlich eine viel genauere MTime hat, es verwendet auch die Mikrosekunden. Wenn Sie also den ETag genau so erzeugen wollen wie Apache, benötigen Sie die Mikrozeit des mtime. Nach meinem Wissen ist das in PHP nicht möglich. Was Sie jedoch tun können, ist zu überprüfen, ob Apache's MTime _close genug_ ist (<1 Sekunde), so dass Sie mindestens ein '304 Not Modified' zurückgeben können. – Halcyon

1

Wenn Sie Ihre Seite dynamisch generieren, wird dies wahrscheinlich keinen Sinn ergeben. Wenn Sie in PHP sind, können Sie den Inode und die Dateigröße des Hauptskriptes auswählen, aber die Änderungszeit sagt Ihnen nicht, ob sich Ihre Daten geändert haben. Sofern Sie keinen guten Caching-Prozess haben oder nur statische Seiten generieren, sind Etags nicht hilfreich. Wenn Sie einen guten Caching-Prozess haben, sind der Inode und die Dateigröße wahrscheinlich irrelevant.

Edit: Für Leute, die nicht wissen, was etag s sind - sie sollen nur ein Wert sein, der sich ändert, wenn der Inhalt geändert wurde, für Zwischenspeicherungszwecke. Der Browser ruft das Etag vom Webserver ab, vergleicht es mit dem Etag für seine zwischengespeicherte Kopie und ruft dann die gesamte Seite ab, wenn sich das Etag geändert hat.

+0

Dieser Ansatz kann für Dinge wie Download-Skripts nützlich sein, die Dateien nur über PHP und andere Situationen streamen, in denen Antworten nicht dynamisch pro Anfrage sind. –

2

Eine Sache, die bei Apache's Etags zu beachten ist, ist, dass sie in Clustern nicht gut spielen, weil sie Inode-Informationen enthalten, die zwischen Maschinen im selben Cluster variieren können.

+3

Fügen Sie 'FileETag MTime Size' zu ​​Ihrem .htaccess hinzu, um den Etag-Inode unabhängig zu machen. – Halcyon

+0

In Apache Version 2.4 ist INode standardmäßig nicht mehr enthalten. – holmis83

1

die Antwort oben (von Chris) funktioniert gut, aber kann mit Hilfe eines impliziten Guss im sprintf vereinfacht werden:

sprintf('"%x-%x-%x"', $s['ino'], $s['size'], str_pad($s['mtime'], 16, "0")); 

Die vorgeschlagene %016x funktioniert nicht, weil die Polsterung nach der Umwandlung verhexen angewandt wird eher als vorher.

+0

Das funktioniert ** nicht, ich bin mir nicht sicher, warum, vielleicht weil% x ein 'int' als Eingabe benötigt? – Halcyon

+1

@FritsvanCampen: es erweist sich als ein bisschen komplizierter als das. 'sprintf' versucht, die Zeichenfolge in ein' int' zu konvertieren, aber da diese Zahlen so groß sind, überlaufen sie und verursachen Probleme. Die Lösung ist stattdessen 'float' zu verwenden:' sprintf ('"% x-% x-% x"', $ s ['ino'], $ s ['größe'], (float) str_pad ($ s [ 'mtime'], 16, '0')) '. –