Commit 5df473a6 authored by Andy Wilkinson's avatar Andy Wilkinson

Add env-based configuration of TTL of Tomcat's static resource cache

Closes gh-9670
parent 1225a6a0
......@@ -609,6 +609,11 @@ public class ServerProperties {
*/
private List<String> additionalTldSkipPatterns = new ArrayList<>();
/**
* Static resource configuration.
*/
private final Resource resource = new Resource();
public int getMaxThreads() {
return this.maxThreads;
}
......@@ -741,6 +746,10 @@ public class ServerProperties {
this.additionalTldSkipPatterns = additionalTldSkipPatterns;
}
public Resource getResource() {
return this.resource;
}
/**
* Tomcat access log properties.
*/
......@@ -880,6 +889,26 @@ public class ServerProperties {
}
/**
* Tomcat static resource properties.
*/
public static class Resource {
/**
* Time-to-live in milliseconds of the static resource cache.
*/
private Long cacheTtl;
public Long getCacheTtl() {
return this.cacheTtl;
}
public void setCacheTtl(Long cacheTtl) {
this.cacheTtl = cacheTtl;
}
}
}
/**
......
......@@ -24,6 +24,7 @@ import javax.servlet.ServletException;
import javax.servlet.SessionCookieConfig;
import io.undertow.UndertowOptions;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.valves.RemoteIpValve;
import org.apache.coyote.AbstractProtocol;
......@@ -41,6 +42,7 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties.Session;
import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.Resource;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
......@@ -259,6 +261,7 @@ public class DefaultServletWebServerFactoryCustomizer
factory.getTldSkipPatterns()
.addAll(tomcatProperties.getAdditionalTldSkipPatterns());
}
customizeStaticResources(serverProperties.getTomcat().getResource(), factory);
}
private static void customizeAcceptCount(TomcatServletWebServerFactory factory,
......@@ -384,6 +387,20 @@ public class DefaultServletWebServerFactoryCustomizer
.setMapperContextRootRedirectEnabled(redirectContextRoot));
}
private static void customizeStaticResources(Resource resource,
TomcatServletWebServerFactory factory) {
if (resource.getCacheTtl() == null) {
return;
}
factory.addContextCustomizers((context) -> {
context.addLifecycleListener((event) -> {
if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
context.getResources().setCacheTtl(resource.getCacheTtl());
}
});
});
}
}
private static class UndertowCustomizer {
......
......@@ -31,6 +31,7 @@ import javax.servlet.SessionTrackingMode;
import org.apache.catalina.Context;
import org.apache.catalina.Valve;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.valves.RemoteIpValve;
import org.apache.coyote.AbstractProtocol;
......@@ -602,6 +603,25 @@ public class DefaultServletWebServerFactoryCustomizerTests {
verify(factory, never()).setAccessLogEnabled(anyBoolean());
}
@Test
public void customTomcatStaticResourceCacheTtl() {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.resource.cache-ttl", "10000");
bindProperties(map);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(0);
this.customizer.customize(factory);
TomcatWebServer embeddedFactory = (TomcatWebServer) factory.getWebServer();
embeddedFactory.start();
try {
Tomcat tomcat = embeddedFactory.getTomcat();
Context context = (Context) tomcat.getHost().findChildren()[0];
assertThat(context.getResources().getCacheTtl()).isEqualTo(10000L);
}
finally {
embeddedFactory.stop();
}
}
private void triggerInitializers(ConfigurableServletWebServerFactory factory,
ServletContext servletContext) throws ServletException {
verify(factory, atLeastOnce()).addInitializers(this.initializersCaptor.capture());
......
......@@ -243,6 +243,7 @@ content into your application; rather pick only the properties that you need.
server.tomcat.protocol-header-https-value=https # Value of the protocol header that indicates that the incoming request uses SSL.
server.tomcat.redirect-context-root= # Whether requests to the context root should be redirected by appending a / to the path.
server.tomcat.remote-ip-header= # Name of the http header from which the remote ip is extracted. For instance `X-FORWARDED-FOR`
spring.tomcat.resource.cache-ttl=5000 # Time-to-live in milliseconds of the static resource cache.
server.tomcat.uri-encoding=UTF-8 # Character encoding to use to decode the URI.
server.undertow.accesslog.dir= # Undertow access log directory.
server.undertow.accesslog.enabled=false # Enable access log.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment