No se pueden almacenar en caché las imágenes servidas por Spring MVC
Estoy tratando de servir algunos activos utilizando un controlador Spring MVC. Mis activos son administrados por bases de datos y, por lo tanto, deben ser servidos de esta manera. El servicio busca los metadatos del activo en la base de datos, lee el archivo del sistema de archivos y genera la respuesta.
Así es como se ve mi controlador.
@Controller
@RequestMapping("/assets")
public class AssetController {
@Autowired
private AssetService assetService;
@RequestMapping("/{assetName:.+}")
public ResponseEntity<byte[]> getAsset(@PathVariable("assetName") String assetName) throws FileNotFoundException, IOException {
Asset asset = assetService.findByName(assetName);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf(asset.getContentType()));
headers.setCacheControl("max-age=1209600");
headers.setLastModified(asset.getModifiedOn().getTime()); // always in the past
return new ResponseEntity<byte[]>(assetService.toBytes(asset), headers, OK);
}
}
Parece lo suficientemente simple y directo? Uno esperaría ver el navegador guardando en caché las imágenes. Pero a pesar de intentar todas las combinaciones deCache-Control
, Expires
, Last-Modified-On
yETag
, No he tenido exito
A continuación se muestran los encabezados HTTP (se eliminaron los encabezados irrelevantes) durante dos solicitudes sucesivas.
GET /adarshr-web/assets/Acer.png HTTP/1.1
Host: localhost:8080
Pragma: no-cache
Cache-Control: no-cache
HTTP/1.1 200 OK
Cache-Control: max-age=1209600
Last-Modified: Sun, 21 Jul 2013 11:56:32 GMT
Content-Type: image/png
Date: Tue, 23 Jul 2013 21:22:58 GMT
----------------------------------------------------------
GET /adarshr-web/assets/Acer.png HTTP/1.1
Host: localhost:8080
If-Modified-Since: Sun, 21 Jul 2013 11:56:32 GMT
Cache-Control: max-age=0
HTTP/1.1 200 OK <-- Why not 304 Not Modified?
Cache-Control: max-age=1209600
Last-Modified: Sun, 21 Jul 2013 11:56:32 GMT
Content-Type: image/png
Date: Tue, 23 Jul 2013 21:23:03 GMT
Sin embargo, cuando intento la misma secuencia (Ctrl + F5 para la primera solicitud y F5 para las siguientes) en URL como
http://www.google.co.uk/images/srpr/logo4w.png (Logotipo de Google)http://fbstatic-a.akamaihd.net/rsrc.php/v2/yI/r/0PsXdTWc41M.png (Imagen móvil de Facebook)Veo los encabezados como estos (que se muestran para la URL de Facebook) que indican que la respuesta está siendo almacenada en caché por el navegador.
GET /rsrc.php/v2/yI/r/0PsXdTWc41M.png HTTP/1.1
Host: fbstatic-a.akamaihd.net
Pragma: no-cache
Cache-Control: no-cache
HTTP/1.1 200 OK
Content-Type: image/png
Last-Modified: Sat, 15 Jun 2013 00:48:42 GMT
Cache-Control: public, max-age=31535893
Expires: Wed, 23 Jul 2014 21:27:47 GMT
Date: Tue, 23 Jul 2013 21:29:34 GMT
----------------------------------------------------------
GET /rsrc.php/v2/yI/r/0PsXdTWc41M.png HTTP/1.1
Host: fbstatic-a.akamaihd.net
If-Modified-Since: Sat, 15 Jun 2013 00:48:42 GMT
Cache-Control: max-age=0
HTTP/1.1 304 Not Modified <-- Note this
Content-Type: image/png
Last-Modified: Sat, 15 Jun 2013 00:48:42 GMT
Cache-Control: public, max-age=31535892
Expires: Wed, 23 Jul 2014 21:27:47 GMT
Date: Tue, 23 Jul 2013 21:29:35 GMT
Notas:
No tengo un<mvc:resources />
sección en mi configuración de primavera ya que estoy haciendo exactamente lo mismo en mi controlador. Incluso agregarlo no hace ninguna diferencia.No tengo unorg.springframework.web.servlet.mvc.WebContentInterceptor
definido en la configuración de primavera de nuevo por las razones anteriores. He intentado agregar uno sin ganancia.He intentado todos los métodos explicados enhttps://developers.google.com/speed/docs/best-practices/caching.Puedo replicar esto en todos los navegadores.