2008-09-04 11 views

Respuesta

9

Apache utiliza el formato estándar de inode-filesize-mtime. La única advertencia a esto es que el mtime debe ser un tiempo de época y rellenado con ceros, por lo que tiene 16 dígitos. Aquí está cómo hacerlo en PHP:

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

Por qué no 'header (sprintf ('Etag:"% x-% x-% 016x "', $ fs ['ino'], $ fs ['size'], $ fs ['mtime'])) ; '? –

+1

Observé que la parte MTime del ETag de mi servidor Apache en realidad tiene un MTime mucho más preciso, también usa microsegundos. Entonces, si quieres generar el ETag exactamente como Apache lo hace, necesitarás la microtime del mtime. Que yo sepa, esto no es posible en PHP. Sin embargo, lo que puede hacer es verificar si el MTime de Apache es lo suficientemente cerrado (<1 segundo), por lo que al menos puede devolver un '304 no modificado'. – Halcyon

1

Sin embargo, si genera dinámicamente su página, esto probablemente no tenga sentido. Si está en PHP, puede elegir el inodo y el tamaño del archivo del script principal, pero el tiempo de modificación no le indicará si sus datos han cambiado. A menos que tenga un buen proceso de almacenamiento en caché o simplemente genere páginas estáticas, los etags no son útiles. Si tiene un buen proceso de almacenamiento en caché, el inodo y el tamaño del archivo probablemente sean irrelevantes.

Editar: Para las personas que no saben lo que etag s son, se supone que son un valor que cambia cuando el contenido ha cambiado, para fines de almacenamiento en caché. El navegador obtiene el etag del servidor web, lo compara con el etag para su copia en caché y luego recupera toda la página si el etag ha cambiado.

+0

Este enfoque puede ser útil para cosas como descargar scripts que solo transmiten archivos a través de PHP y otras situaciones donde las respuestas no son realmente dinámicas por solicitud. –

2

Una cosa para recordar acerca de los Etags de Apache es que no funcionan bien en clusters porque incluyen información de inodo que puede, y probablemente variará, entre máquinas en el mismo clúster.

+3

Agregue 'FileETag MTime Size' a su .htaccess para hacer que el inodo Etag sea independiente. – Halcyon

+0

En la versión 2.4 de Apache, INode ya no está incluido por defecto. – holmis83

1

la respuesta anterior (de Chris) funciona bien, pero se puede simplificar utilizando una conversión implícita en el sprintf:

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

El sugirió %016x no funciona porque se aplica el relleno después de la conversión a hexadecimal , en lugar de antes

+0

Esto no ** funciona **, no estoy seguro de por qué, tal vez porque% x necesita un 'int' como entrada? – Halcyon

+1

@FritsvanCampen: resulta ser un poco más complicado que eso. 'sprintf' intentará convertir la cadena en' int', pero dado que estos números son tan grandes, se desbordan y causan problemas. La solución es usar 'float' en su lugar:' sprintf ('"% x-% x-% x"', $ s ['ino'], $ s ['size'], (float) str_pad ($ s [ 'mtime'], 16, '0')) '. –

Cuestiones relacionadas