Comment ajouter un en-tête HTTP Cache-Control
dans Spring Boot pour les ressources statiques?
J'ai essayé d'utiliser un composant de filtre dans l'application, qui écrit correctement les en-têtes, mais Cache-Control
est remplacé.
@Component
public class CacheBustingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResp = (HttpServletResponse) resp;
httpResp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
httpResp.setHeader("This-Header-Is-Set", "no-cache, no-store, must-revalidate");
httpResp.setHeader("Expires", "0");
chain.doFilter(req, resp);
}
Ce que je reçois dans le navigateur est:
Cache-Control:no-store
This-Header-Is-Set:no-cache, no-store, must-revalidate
Expires:0
Ce que j'aimerais, c'est:
Cache-Control:no-cache, no-store, must-revalidate
This-Header-Is-Set:no-cache, no-store, must-revalidate
Expires:0
Selon la documentation de ResourceHandlerRegistry
. C'est assez facile. (Je n'ai pas de code lié à cela pour le moment.)
À l'endroit où vous configurez vos ressources statiques, ajoutez simplement la méthode addResourceHandler
. Cela retournera l'objet ResourceHandlerRegistration
.
Là, vous pouvez utiliser setCacheControl method. Ce que vous devez faire est de configurer et définir un CacheControl obejct.
Ceci est depuis le printemps 4.2, sinon vous devrez le faire comme ci-dessous.
@Configuration
@EnableWebMvc
@ComponentScan("my.packages.here")
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").setCachePeriod(0);
}
}
Cela est dû à Spring Security: il réécrit tous les en-têtes de cache pour désactiver totalement la mise en cache. Il faut donc faire deux choses:
Dans la version actuelle de Spring Boot, nous pouvons modifier ce comportement dans application.properties config.
Désactiver la sécurité de printemps pour certaines ressources:
# Comma-separated list of paths to exclude from the default secured
security.ignored=/myAssets/**
Activer l'envoi des en-têtes de cache pour les ressources statiques:
# Enable HTML5 application cache manifest rewriting.
spring.resources.chain.html-application-cache=true
# Enable the Spring Resource Handling chain. Disabled by default unless at least one strategy has been enabled.
spring.resources.chain.enabled=true
# Enable the content Version Strategy.
spring.resources.chain.strategy.content.enabled=true
# Comma-separated list of patterns to apply to the Version Strategy.
spring.resources.chain.strategy.content.paths=/**
# Locations of static resources.
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
C'est tout. Maintenant, Spring vérifie si vos fichiers statiques ont été modifiés et peut envoyer des réponses plus intelligentes (If-Modiffied-Since et autres) et réécrire votre appcache également.
De même, s'il existe des raisons de ne pas utiliser la version basée sur le contenu pour certaines ressources, vous pouvez utiliser une autre stratégie FixedVersion et définir explicitement la version dans votre configuration:
#Enable the fixed Version Strategy.
spring.resources.chain.strategy.fixed.enabled=false
# Comma-separated list of patterns to apply to the Version Strategy.
spring.resources.chain.strategy.fixed.paths=
# Version string to use for the Version Strategy.
spring.resources.chain.strategy.fixed.version=
Les propriétés qui contrôlent les en-têtes de cache par défaut pour les ressources sont les suivantes:
spring.resources.cache.cachecontrol.max-age: 3600
https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
En utilisant spring boot 1.3.3, j'avais une réponse 404 en utilisant maleenc answer ..__ Je pouvais le corriger en ajoutant un emplacement de ressource:
@Configuration
public class HttpClientConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").setCacheControl(CacheControl.maxAge(1, TimeUnit.DAYS))
.addResourceLocations("/");
}
}
Maleenc, la réponse est correcte. Cependant, cette implémentation pose un problème.
Le code suivant fournira le bon en-tête de contrôle du cache lors de la première requête, mais pas une demande ultérieure renvoyant 304 (non modifié) renverra l'en-tête de contrôle du cache par défaut défini par la sécurité printanière.
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").setCacheControl(CacheControl.maxAge(10, TimeUnit.SECONDS));
}
J'ai soulevé cette question à l'équipe de Spring, voir https://jira.spring.io/browse/SPR-15133 . Voici la réponse: "Maintenant, vous ne devriez pas désactiver les en-têtes de contrôle du cache de sécurité pour l’ensemble de votre application; le moyen approprié pour les désactiver pour un chemin spécifique (gestion des ressources, ici) est expliqué dans ce commentaire, voir le "Contournement" section. "
Au printemps, il y a beaucoup de façons de mettre en cache la ressource http. Utilisation de la botte à ressort 2.1.1 et de la sécurité à ressort 5.1.1.
1. Pour les ressources utilisant resourcehandler dans le code (UNTESTED):
Vous pouvez ajouter des extensions de ressources personnalisées de cette façon.
registry.addResourceHandler
Est pour ajouter le chemin URI où obtenir la ressource
.addResourceLocations
Permet de définir l'emplacement dans le système de fichiers où se trouvent les ressources ( Est donné avec un chemin classpath mais le chemin absolu avec file :: // est également possible.)
.setCacheControl
Permet de définir les en-têtes de cache (explicite.)
Resourcechain et resolver sont facultatifs (dans ce cas, exactement comme les valeurs par défaut).
@Configuration
public class CustomWebMVCConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.noStore()
.mustRevalidate())
.setCacheControl(CacheControl.noCache())
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
}
2. Pour les ressources utilisant le fichier de configuration des propriétés d'application
Comme ci-dessus, moins les modèles spécifiques, mais maintenant sous la forme config . Cette configuration est appliquée à toutes les ressources des emplacements statiques répertoriés.
spring.resources.cache.cachecontrol.no-store=true
spring.resources.cache.cachecontrol.must-revalidate=true
spring.resources.cache.cachecontrol.no-cache=true
3. Au niveau du contrôleur
La réponse ici est le HttpServletResponse injecté dans la méthode du contrôleur en tant que paramètre.
response.setHeader(HttpHeaders.CACHE_CONTROL,
"no-cache, must-revalidate, no-store");
response.setHeader("Expires", "0");