0

I want to set the Cache-Control and ETag headers correctly in my responses. To do that I have disabled request caching through spring security configuration:

httpSecurity.headers().cacheControl().disable();

Then when returning the response:

ResponseEntity.ok()
        .header("Cache-Control", "max-age=60")
        .header("ETag", "my-tag")
        .build()

It seems to work in the sense that the default spring security cache-control headers are not returned (by default I think they return "no-cache, no-store, max-age=0, must-revalidate") and my headers are present in the response. However there is also something else there:

Cache-Control: private
Expires: Thu, 01 Jan 1970 00:00:00 GMT
ETag: "0.42.1-20181213080300000"
Cache-Control: max-age=60
...other headers

The lower cache headers are mine but the top ones are unwanted. They seem to come from org.apache.catalina.authenticator.AuthenticatorBase which seems to be part of the embedded Tomcat being used. I have been unable to find a way to access and modify the configuration of this particular class.

Please advise on how to get rid of the unwanted headers.

I am on Spring boot 1.5.18.RELEASE

Tarmo
  • 1,136
  • 13
  • 28

1 Answers1

0

In order to make changes to the configuration of a Valve I had to look it up from the context at the appropriate lifecycle phase using EmbeddedServletContainerCustomizer as shown below.

@Component
public class TomcatCacheControlCustomizer implements EmbeddedServletContainerCustomizer {

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        if(container instanceof TomcatEmbeddedServletContainerFactory){
            TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;
            containerFactory.addContextLifecycleListeners((LifecycleListener) event -> {
                Context context = (Context) event.getLifecycle();
                if(event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)){
                    if(context.getPipeline() != null){
                        Pipeline pipeline = context.getPipeline();
                        if(pipeline.getValves() != null){
                            Optional<Valve> authenticatorBase = Arrays.stream(pipeline.getValves()).filter(v -> v instanceof AuthenticatorBase).findFirst();
                            if(authenticatorBase.isPresent()){
                                ((AuthenticatorBase) authenticatorBase.get()).setDisableProxyCaching(false);
                            }
                        }
                    }
                }
            });
        }
    }

}

After updating the configuration of AuthenticatorBase, the undesired Cache-Control headers were no longer added to responses and only my custom headers remained.

Tarmo
  • 1,136
  • 13
  • 28