web-dev-qa-db-fra.com

Comment ajouter un en-tête Cache-Control à une ressource statique dans Spring Boot?

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
19
MatteKarla

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);
    }

}
11
Maleen Abewardana

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: 

  1. Désactiver la sécurité de printemps pour les ressources statiques
  2. Activer le traitement du cache de ressources statiques

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= 

Voir plus dans docs

11
Alexandr Latushkin

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

2
Mateusz Stefek

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("/");
    }
}
1
Ronan Fauglas

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. "

1
Thomas Jahncke

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");
0
Merv