Allow Tomcat context root redirect to be configured via the environment
This commit adds a new property, server.tomcat.redirect-context-root, that can be used to configure the Tomcat Context’s mapperContextRootRedirectEnabled property. The default is to not apply any configuration and, therefore, to use Tomcat’s default of true. Closes gh-6248
This commit is contained in:
parent
05b9dd1cb9
commit
2b970f9efc
|
@ -646,6 +646,12 @@ public class ServerProperties
|
||||||
*/
|
*/
|
||||||
private int maxHttpHeaderSize = 0; // bytes
|
private int maxHttpHeaderSize = 0; // bytes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether requests to the context root should be redirected by appending a / to
|
||||||
|
* the path.
|
||||||
|
*/
|
||||||
|
private Boolean redirectContextRoot;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Character encoding to use to decode the URI.
|
* Character encoding to use to decode the URI.
|
||||||
*/
|
*/
|
||||||
|
@ -742,6 +748,14 @@ public class ServerProperties
|
||||||
this.portHeader = portHeader;
|
this.portHeader = portHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getRedirectContextRoot() {
|
||||||
|
return this.redirectContextRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedirectContextRoot(Boolean redirectContextRoot) {
|
||||||
|
this.redirectContextRoot = redirectContextRoot;
|
||||||
|
}
|
||||||
|
|
||||||
public String getRemoteIpHeader() {
|
public String getRemoteIpHeader() {
|
||||||
return this.remoteIpHeader;
|
return this.remoteIpHeader;
|
||||||
}
|
}
|
||||||
|
@ -789,6 +803,9 @@ public class ServerProperties
|
||||||
customizeConnectionTimeout(factory,
|
customizeConnectionTimeout(factory,
|
||||||
serverProperties.getConnectionTimeout());
|
serverProperties.getConnectionTimeout());
|
||||||
}
|
}
|
||||||
|
if (this.redirectContextRoot != null) {
|
||||||
|
customizeRedirectContextRoot(factory, this.redirectContextRoot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void customizeConnectionTimeout(
|
private void customizeConnectionTimeout(
|
||||||
|
@ -911,6 +928,19 @@ public class ServerProperties
|
||||||
factory.addContextValves(valve);
|
factory.addContextValves(valve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void customizeRedirectContextRoot(
|
||||||
|
TomcatEmbeddedServletContainerFactory factory,
|
||||||
|
final boolean redirectContextRoot) {
|
||||||
|
factory.addContextCustomizers(new TomcatContextCustomizer() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void customize(Context context) {
|
||||||
|
context.setMapperContextRootRedirectEnabled(redirectContextRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static class Accesslog {
|
public static class Accesslog {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,6 +29,7 @@ import javax.servlet.ServletException;
|
||||||
import javax.servlet.SessionCookieConfig;
|
import javax.servlet.SessionCookieConfig;
|
||||||
import javax.servlet.SessionTrackingMode;
|
import javax.servlet.SessionTrackingMode;
|
||||||
|
|
||||||
|
import org.apache.catalina.Context;
|
||||||
import org.apache.catalina.Valve;
|
import org.apache.catalina.Valve;
|
||||||
import org.apache.catalina.valves.RemoteIpValve;
|
import org.apache.catalina.valves.RemoteIpValve;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -41,6 +42,7 @@ import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.boot.bind.RelaxedDataBinder;
|
import org.springframework.boot.bind.RelaxedDataBinder;
|
||||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||||
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
||||||
|
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
|
||||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||||
import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
|
import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
|
||||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||||
|
@ -150,6 +152,30 @@ public class ServerPropertiesTests {
|
||||||
.isEqualTo("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
|
.isEqualTo("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void redirectContextRootIsNotConfiguredByDefault() throws Exception {
|
||||||
|
bindProperties(new HashMap<String, String>());
|
||||||
|
ServerProperties.Tomcat tomcat = this.properties.getTomcat();
|
||||||
|
assertThat(tomcat.getRedirectContextRoot()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void redirectContextRootCanBeConfigured() throws Exception {
|
||||||
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
map.put("server.tomcat.redirect-context-root", "false");
|
||||||
|
bindProperties(map);
|
||||||
|
ServerProperties.Tomcat tomcat = this.properties.getTomcat();
|
||||||
|
assertThat(tomcat.getRedirectContextRoot()).isEqualTo(false);
|
||||||
|
TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory();
|
||||||
|
this.properties.customize(container);
|
||||||
|
Context context = mock(Context.class);
|
||||||
|
for (TomcatContextCustomizer customizer : container
|
||||||
|
.getTomcatContextCustomizers()) {
|
||||||
|
customizer.customize(context);
|
||||||
|
}
|
||||||
|
verify(context).setMapperContextRootRedirectEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTrailingSlashOfContextPathIsRemoved() {
|
public void testTrailingSlashOfContextPathIsRemoved() {
|
||||||
new RelaxedDataBinder(this.properties, "server").bind(new MutablePropertyValues(
|
new RelaxedDataBinder(this.properties, "server").bind(new MutablePropertyValues(
|
||||||
|
|
|
@ -214,6 +214,7 @@ content into your application; rather pick only the properties that you need.
|
||||||
server.tomcat.port-header=X-Forwarded-Port # Name of the HTTP header used to override the original port value.
|
server.tomcat.port-header=X-Forwarded-Port # Name of the HTTP header used to override the original port value.
|
||||||
server.tomcat.protocol-header= # Header that holds the incoming protocol, usually named "X-Forwarded-Proto".
|
server.tomcat.protocol-header= # Header that holds the incoming protocol, usually named "X-Forwarded-Proto".
|
||||||
server.tomcat.protocol-header-https-value=https # Value of the protocol header that indicates that the incoming request uses SSL.
|
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`
|
server.tomcat.remote-ip-header= # Name of the http header from which the remote ip is extracted. For instance `X-FORWARDED-FOR`
|
||||||
server.tomcat.uri-encoding=UTF-8 # Character encoding to use to decode the URI.
|
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.dir= # Undertow access log directory.
|
||||||
|
|
|
@ -184,7 +184,6 @@ public class TomcatEmbeddedServletContainerFactory
|
||||||
: ClassUtils.getDefaultClassLoader());
|
: ClassUtils.getDefaultClassLoader());
|
||||||
try {
|
try {
|
||||||
context.setUseRelativeRedirects(false);
|
context.setUseRelativeRedirects(false);
|
||||||
context.setMapperContextRootRedirectEnabled(true);
|
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodError ex) {
|
catch (NoSuchMethodError ex) {
|
||||||
// Tomcat is < 8.0.30. Continue
|
// Tomcat is < 8.0.30. Continue
|
||||||
|
|
Loading…
Reference in New Issue