java - redirection - ¿Cómo prevenir correctamente el almacenamiento en caché de la ubicación de redireccionamiento 302?
redirect 301 apache (5)
He encontrado el siguiente problema con el patrón Publicar / Redirigir / Obtener . Al realizar GET
después de redirigir, Chrome toma la página de la memoria caché. Entonces el usuario ve datos obsoletos.
Intenté seguir para forzar / apoyar la revalidación
if (request.checkNotModified(sinceLastTweet)) return null;
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Last-Modified", String.valueOf(sinceLastTweet));
Pero solo no-store
causa una solicitud de servidor.
¿Por qué Chrome toma la página de la memoria caché al realizar la redirección?
@RequestMapping(method = GET)
public String home(ModelMap model, @PathVariable String username, HttpServletResponse response, WebRequest request) {
// response.setHeader("Cache-Control", "no-store");
List<Tweet> tweets = tweetRepository.findAll();
// long sinceLastTweet = tweets.get(0).getTimestamp().toEpochMilli();
// if (request.checkNotModified(sinceLastTweet)) return null;
// response.setHeader("Cache-Control", "no-cache");
// response.setHeader("Last-Modified", String.valueOf(sinceLastTweet));
model.addAttribute("tweets", tweets);
model.addAttribute("tweet", new Tweet());
model.addAttribute("username", username);
return "home";
}
1) Debes intentar obligar a Chrome a no usar el caché,
¿Cómo controlar el almacenamiento en caché de la página web en todos los navegadores?
Al igual que la respuesta a esa pregunta, sugiera que debe poner este encabezado en la respuesta http:
response.header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.header("Pragma: no-cache"); // HTTP 1.0.
response.header("Expires: 0"); // Proxies.
2) Puedes hacer un pequeño truco
Puede programar para responder cualquier solicitud con el siguiente formato con el mismo controlador:
http://localhost:8080/spitter/username-{timestamp}
Luego cambia los enlaces en su página para tener la última marca de tiempo antes de enviar la solicitud.
En este caso, evento si Chrome guarda en caché la página, no importa.
En lugar de marca de tiempo, puede usar cualquier otra metodología, como "autoincrement" o "uuid".
Agregue algunos números aleatorios (hora actual en milisegundos) al final de la URL. como la URL del servicio es
http://localhost:7001/rest/getBook/5
Entonces, en lugar de hacer una llamada a la URL anterior, agregue algunos números al azar mientras realiza la llamada de servicio anterior
/rest/getBook/5?_time-in-milisec
No es necesario modificar la llamada de servicio en javascript.
URL = http://localhost:7001/rest/getBook/5 + "?_" +new Date()
Dado que cada URL de tiempo es diferente, no se refiere a la memoria caché del navegador.
Puede usar POST en lugar de GET. Los POST no se almacenan en caché.
Si una instancia de Chrome tiene una página /username
caché, Chrome no afecta esa página como efecto de la redirección porque Chrome lee el encabezado de Location
y sirve la página almacenada en caché.
Tal vez una vez visitó la página mientras intentaba encabezados de caché y ahora su Chrome piensa que debe almacenarla en caché, tal vez incluso para siempre.
Debe invalidar el caché (con ese Chrome) para la página /username
:
- configure la página
/username
para que se sirva siempre con encabezados que deshabiliten el almacenamiento en caché, como los sugeridos por rev_dihazum o cómo se hace en Spring WebContentGenerator . - Borre el caché manualmente o visite
/username
y presione CTRL + R mientras se encuentra en la página: se solicitará realmente la página, se leerán los encabezados de desactivación del caché y a partir de ese momento se volverá a solicitar la página al servidor, incluso cuándo solicitado como efecto de una redirección.
Si la página es pública y los usuarios cuyos navegadores no puede controlar, ya la almacenaron en la memoria caché, entonces el problema es peor y puede elegir una de las siguientes opciones:
- esperar a que el caché expire
- cambiar el nombre a la página
- agregue un número aleatorio, más o menos como lo sugiere prad121, a la URL de
Location
para hacerlo único, una variación de 2)
Tenga en cuenta que el formato de hora Last-Modified
es Tue, 15 Nov 1994 08:12:31 GMT
, puede usar el método setDateHeader
para establecerlo como un long
Puede buscar en WebContentGenerator para ver otro código de caché en Spring.
Tal vez puedas intentar usar un ETag para tu página.
Sin embargo, no estoy seguro de si entiendo correctamente tu escenario de redirección.
Supongamos que tiene alguna página de visualización que contiene un username
y tiene una segunda página que proporciona Edición para sus datos y desea poder cambiar el username
allí y presionar un botón para guardarlo y luego regresar a la página de visualización.
Una opción sería incluir el username
de username
en la URL (como ...&username=Jack
). Como el nombre de usuario ha cambiado, la URL también cambiará (es decir, ...&username=Jim
). En este caso, Chrome no tendría una versión en caché de la página de visualización para Jack y obtendría una versión nueva del mismo desde el servidor. (Si tiene algún campo que no desea mencionar explícitamente en la URL, puede calcular una suma de verificación en todos los campos y agregar esto como un parámetro como ...&check=12345678
).
Otra opción sería hacer que el servidor genere un ETag, así que veamos esto en detalle. Lo que queremos es que la aplicación del servidor esté a cargo de decirle al navegador si los datos necesitan una actualización o si se pueden tomar de la memoria caché, ¿no?
{Perdóneme que no estoy usando su ejemplo aquí, ya que actualmente estoy desarrollando en una pila diferente; sin embargo, creo que su problema se puede resolver con su Java / Spring Stack de la misma manera}
Eche un vistazo a la captura de pantalla en la sección Encabezados de respuesta y en el medio verá ETag . Este ID lo genera el servidor, por lo que la aplicación de servidor tiene el control aquí. (Tal vez este article ayude si aún no ha implementado un ETag).
¿Así que lo que ocurre? Tan pronto como el contenido cambia en el servidor, el ETag también cambia: el navegador ve el ETag en la respuesta, respeta que el servidor esté a cargo y pregunta al servidor si el contenido ha cambiado y si es así, emite la página en caché con el contenido caducado y solicita uno nuevo del servidor.
Debe asegurarse, por supuesto, de que tan pronto como el servidor se entere de que el usuario ha cambiado de Jack a Jim (o de cualquier otro campo en consecuencia), la aplicación de servidor genera la nueva ETag para la página de visualización de este usuario.
¡Espero eso ayude!