Browse Source

Apply server.jetty.* config to reactive servers

This commit applies `server.jetty.*` configuration properties
to Jetty when configured as a reactive web server.

It also removes some infrastructure support for Jetty 8, which
is not supported anymore in Spring Boot 2.0 (partial fix for
gh-11504).

See gh-11500
pull/11497/merge
Brian Clozel 8 years ago
parent
commit
15bc718248
  1. 184
      spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/jetty/JettyCustomizer.java
  2. 22
      spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/jetty/package-info.java
  3. 6
      spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/DefaultReactiveWebServerFactoryCustomizer.java
  4. 162
      spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DefaultServletWebServerFactoryCustomizer.java
  5. 100
      spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/DefaultReactiveWebServerFactoryCustomizerTests.java
  6. 3
      spring-boot-project/spring-boot-parent/src/checkstyle/import-control.xml
  7. 56
      spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ConfigurableJettyWebServerFactory.java
  8. 45
      spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ForwardHeadersCustomizer.java
  9. 94
      spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactory.java
  10. 49
      spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java

184
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/jetty/JettyCustomizer.java

@ -0,0 +1,184 @@ @@ -0,0 +1,184 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.web.embedded.jetty;
import java.time.Duration;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.core.env.Environment;
/**
* Customization for Jetty-specific features common
* for both Servlet and Reactive servers.
*
* @author Brian Clozel
* @since 2.0.0
*/
public final class JettyCustomizer {
private JettyCustomizer() {
}
public static void customizeJetty(ServerProperties serverProperties,
Environment environment, ConfigurableJettyWebServerFactory factory) {
ServerProperties.Jetty jettyProperties = serverProperties.getJetty();
factory.setUseForwardHeaders(
getOrDeduceUseForwardHeaders(serverProperties, environment));
if (jettyProperties.getAcceptors() != null) {
factory.setAcceptors(jettyProperties.getAcceptors());
}
if (jettyProperties.getSelectors() != null) {
factory.setSelectors(jettyProperties.getSelectors());
}
if (serverProperties.getMaxHttpHeaderSize() > 0) {
customizeMaxHttpHeaderSize(factory,
serverProperties.getMaxHttpHeaderSize());
}
if (jettyProperties.getMaxHttpPostSize() > 0) {
customizeMaxHttpPostSize(factory, jettyProperties.getMaxHttpPostSize());
}
if (serverProperties.getConnectionTimeout() != null) {
customizeConnectionTimeout(factory,
serverProperties.getConnectionTimeout());
}
if (jettyProperties.getAccesslog().isEnabled()) {
customizeAccessLog(factory, jettyProperties.getAccesslog());
}
}
private static boolean getOrDeduceUseForwardHeaders(ServerProperties serverProperties,
Environment environment) {
if (serverProperties.isUseForwardHeaders() != null) {
return serverProperties.isUseForwardHeaders();
}
CloudPlatform platform = CloudPlatform.getActive(environment);
return platform != null && platform.isUsingForwardHeaders();
}
private static void customizeConnectionTimeout(
ConfigurableJettyWebServerFactory factory, Duration connectionTimeout) {
factory.addServerCustomizers((server) -> {
for (org.eclipse.jetty.server.Connector connector : server
.getConnectors()) {
if (connector instanceof AbstractConnector) {
((AbstractConnector) connector)
.setIdleTimeout(connectionTimeout.toMillis());
}
}
});
}
private static void customizeMaxHttpHeaderSize(
ConfigurableJettyWebServerFactory factory, int maxHttpHeaderSize) {
factory.addServerCustomizers(new JettyServerCustomizer() {
@Override
public void customize(Server server) {
for (org.eclipse.jetty.server.Connector connector : server
.getConnectors()) {
for (ConnectionFactory connectionFactory : connector
.getConnectionFactories()) {
if (connectionFactory instanceof HttpConfiguration.ConnectionFactory) {
customize(
(HttpConfiguration.ConnectionFactory) connectionFactory);
}
}
}
}
private void customize(HttpConfiguration.ConnectionFactory factory) {
HttpConfiguration configuration = factory.getHttpConfiguration();
configuration.setRequestHeaderSize(maxHttpHeaderSize);
configuration.setResponseHeaderSize(maxHttpHeaderSize);
}
});
}
private static void customizeMaxHttpPostSize(ConfigurableJettyWebServerFactory factory,
int maxHttpPostSize) {
factory.addServerCustomizers(new JettyServerCustomizer() {
@Override
public void customize(Server server) {
setHandlerMaxHttpPostSize(maxHttpPostSize, server.getHandlers());
}
private void setHandlerMaxHttpPostSize(int maxHttpPostSize,
Handler... handlers) {
for (Handler handler : handlers) {
if (handler instanceof ContextHandler) {
((ContextHandler) handler)
.setMaxFormContentSize(maxHttpPostSize);
}
else if (handler instanceof HandlerWrapper) {
setHandlerMaxHttpPostSize(maxHttpPostSize,
((HandlerWrapper) handler).getHandler());
}
else if (handler instanceof HandlerCollection) {
setHandlerMaxHttpPostSize(maxHttpPostSize,
((HandlerCollection) handler).getHandlers());
}
}
}
});
}
private static void customizeAccessLog(ConfigurableJettyWebServerFactory factory,
ServerProperties.Jetty.Accesslog properties) {
factory.addServerCustomizers((server) -> {
NCSARequestLog log = new NCSARequestLog();
if (properties.getFilename() != null) {
log.setFilename(properties.getFilename());
}
if (properties.getFileDateFormat() != null) {
log.setFilenameDateFormat(properties.getFileDateFormat());
}
log.setRetainDays(properties.getRetentionPeriod());
log.setAppend(properties.isAppend());
log.setExtended(properties.isExtendedFormat());
if (properties.getDateFormat() != null) {
log.setLogDateFormat(properties.getDateFormat());
}
if (properties.getLocale() != null) {
log.setLogLocale(properties.getLocale());
}
if (properties.getTimeZone() != null) {
log.setLogTimeZone(properties.getTimeZone().getID());
}
log.setLogCookies(properties.isLogCookies());
log.setLogServer(properties.isLogServer());
log.setLogLatency(properties.isLogLatency());
server.setRequestLog(log);
});
}
}

22
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/jetty/package-info.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Configuration for embedded reactive and servlet Jetty web servers.
*
* @see org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory
*/
package org.springframework.boot.autoconfigure.web.embedded.jetty;

6
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/DefaultReactiveWebServerFactoryCustomizer.java

@ -17,7 +17,9 @@ @@ -17,7 +17,9 @@
package org.springframework.boot.autoconfigure.web.reactive;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.embedded.jetty.JettyCustomizer;
import org.springframework.boot.autoconfigure.web.embedded.tomcat.TomcatCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
@ -73,6 +75,10 @@ public class DefaultReactiveWebServerFactoryCustomizer implements @@ -73,6 +75,10 @@ public class DefaultReactiveWebServerFactoryCustomizer implements
TomcatCustomizer.customizeTomcat(this.serverProperties, this.environment,
(TomcatReactiveWebServerFactory) factory);
}
if (factory instanceof JettyReactiveWebServerFactory) {
JettyCustomizer.customizeJetty(this.serverProperties, this.environment,
(JettyReactiveWebServerFactory) factory);
}
}
}

162
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DefaultServletWebServerFactoryCustomizer.java

@ -25,21 +25,12 @@ import javax.servlet.ServletException; @@ -25,21 +25,12 @@ import javax.servlet.ServletException;
import javax.servlet.SessionCookieConfig;
import io.undertow.UndertowOptions;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
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.embedded.jetty.JettyCustomizer;
import org.springframework.boot.autoconfigure.web.embedded.tomcat.TomcatCustomizer;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
@ -128,7 +119,6 @@ public class DefaultServletWebServerFactoryCustomizer @@ -128,7 +119,6 @@ public class DefaultServletWebServerFactoryCustomizer
JettyCustomizer.customizeJetty(this.serverProperties, this.environment,
(JettyServletWebServerFactory) factory);
}
if (factory instanceof UndertowServletWebServerFactory) {
UndertowCustomizer.customizeUndertow(this.serverProperties, this.environment,
(UndertowServletWebServerFactory) factory);
@ -308,154 +298,4 @@ public class DefaultServletWebServerFactoryCustomizer @@ -308,154 +298,4 @@ public class DefaultServletWebServerFactoryCustomizer
}
private static class JettyCustomizer {
public static void customizeJetty(ServerProperties serverProperties,
Environment environment, JettyServletWebServerFactory factory) {
ServerProperties.Jetty jettyProperties = serverProperties.getJetty();
factory.setUseForwardHeaders(
getOrDeduceUseForwardHeaders(serverProperties, environment));
if (jettyProperties.getAcceptors() != null) {
factory.setAcceptors(jettyProperties.getAcceptors());
}
if (jettyProperties.getSelectors() != null) {
factory.setSelectors(jettyProperties.getSelectors());
}
if (serverProperties.getMaxHttpHeaderSize() > 0) {
customizeMaxHttpHeaderSize(factory,
serverProperties.getMaxHttpHeaderSize());
}
if (jettyProperties.getMaxHttpPostSize() > 0) {
customizeMaxHttpPostSize(factory, jettyProperties.getMaxHttpPostSize());
}
if (serverProperties.getConnectionTimeout() != null) {
customizeConnectionTimeout(factory,
serverProperties.getConnectionTimeout());
}
if (jettyProperties.getAccesslog().isEnabled()) {
customizeAccessLog(factory, jettyProperties.getAccesslog());
}
}
private static void customizeConnectionTimeout(
JettyServletWebServerFactory factory, Duration connectionTimeout) {
factory.addServerCustomizers((server) -> {
for (org.eclipse.jetty.server.Connector connector : server
.getConnectors()) {
if (connector instanceof AbstractConnector) {
((AbstractConnector) connector)
.setIdleTimeout(connectionTimeout.toMillis());
}
}
});
}
private static void customizeMaxHttpHeaderSize(
JettyServletWebServerFactory factory, int maxHttpHeaderSize) {
factory.addServerCustomizers(new JettyServerCustomizer() {
@Override
public void customize(Server server) {
for (org.eclipse.jetty.server.Connector connector : server
.getConnectors()) {
try {
for (ConnectionFactory connectionFactory : connector
.getConnectionFactories()) {
if (connectionFactory instanceof HttpConfiguration.ConnectionFactory) {
customize(
(HttpConfiguration.ConnectionFactory) connectionFactory);
}
}
}
catch (NoSuchMethodError ex) {
customizeOnJetty8(connector, maxHttpHeaderSize);
}
}
}
private void customize(HttpConfiguration.ConnectionFactory factory) {
HttpConfiguration configuration = factory.getHttpConfiguration();
configuration.setRequestHeaderSize(maxHttpHeaderSize);
configuration.setResponseHeaderSize(maxHttpHeaderSize);
}
private void customizeOnJetty8(
org.eclipse.jetty.server.Connector connector,
int maxHttpHeaderSize) {
try {
connector.getClass().getMethod("setRequestHeaderSize", int.class)
.invoke(connector, maxHttpHeaderSize);
connector.getClass().getMethod("setResponseHeaderSize", int.class)
.invoke(connector, maxHttpHeaderSize);
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
}
private static void customizeMaxHttpPostSize(JettyServletWebServerFactory factory,
int maxHttpPostSize) {
factory.addServerCustomizers(new JettyServerCustomizer() {
@Override
public void customize(Server server) {
setHandlerMaxHttpPostSize(maxHttpPostSize, server.getHandlers());
}
private void setHandlerMaxHttpPostSize(int maxHttpPostSize,
Handler... handlers) {
for (Handler handler : handlers) {
if (handler instanceof ContextHandler) {
((ContextHandler) handler)
.setMaxFormContentSize(maxHttpPostSize);
}
else if (handler instanceof HandlerWrapper) {
setHandlerMaxHttpPostSize(maxHttpPostSize,
((HandlerWrapper) handler).getHandler());
}
else if (handler instanceof HandlerCollection) {
setHandlerMaxHttpPostSize(maxHttpPostSize,
((HandlerCollection) handler).getHandlers());
}
}
}
});
}
private static void customizeAccessLog(JettyServletWebServerFactory factory,
ServerProperties.Jetty.Accesslog properties) {
factory.addServerCustomizers((server) -> {
NCSARequestLog log = new NCSARequestLog();
if (properties.getFilename() != null) {
log.setFilename(properties.getFilename());
}
if (properties.getFileDateFormat() != null) {
log.setFilenameDateFormat(properties.getFileDateFormat());
}
log.setRetainDays(properties.getRetentionPeriod());
log.setAppend(properties.isAppend());
log.setExtended(properties.isExtendedFormat());
if (properties.getDateFormat() != null) {
log.setLogDateFormat(properties.getDateFormat());
}
if (properties.getLocale() != null) {
log.setLogLocale(properties.getLocale());
}
if (properties.getTimeZone() != null) {
log.setLogTimeZone(properties.getTimeZone().getID());
}
log.setLogCookies(properties.isLogCookies());
log.setLogServer(properties.isLogServer());
log.setLogLatency(properties.isLogLatency());
server.setRequestLog(log);
});
}
}
}

100
spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/DefaultReactiveWebServerFactoryCustomizerTests.java

@ -16,9 +16,13 @@ @@ -16,9 +16,13 @@
package org.springframework.boot.autoconfigure.web.reactive;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import org.apache.catalina.Context;
import org.apache.catalina.Valve;
@ -26,6 +30,8 @@ import org.apache.catalina.startup.Tomcat; @@ -26,6 +30,8 @@ import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.valves.RemoteIpValve;
import org.apache.coyote.AbstractProtocol;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.RequestLog;
import org.junit.Before;
import org.junit.Test;
@ -34,6 +40,8 @@ import org.springframework.boot.context.properties.bind.Bindable; @@ -34,6 +40,8 @@ import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyWebServer;
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory;
@ -42,6 +50,7 @@ import org.springframework.mock.env.MockEnvironment; @@ -42,6 +50,7 @@ import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
/**
@ -340,6 +349,97 @@ public class DefaultReactiveWebServerFactoryCustomizerTests { @@ -340,6 +349,97 @@ public class DefaultReactiveWebServerFactoryCustomizerTests {
}
}
@Test
public void defaultUseForwardHeadersJetty() {
JettyReactiveWebServerFactory factory = spy(new JettyReactiveWebServerFactory());
this.customizer.customize(factory);
verify(factory).setUseForwardHeaders(false);
}
@Test
public void setUseForwardHeadersJetty() {
this.properties.setUseForwardHeaders(true);
JettyReactiveWebServerFactory factory = spy(new JettyReactiveWebServerFactory());
this.customizer.customize(factory);
verify(factory).setUseForwardHeaders(true);
}
@Test
public void deduceUseForwardHeadersJetty() {
this.customizer.setEnvironment(new MockEnvironment().withProperty("DYNO", "-"));
JettyReactiveWebServerFactory factory = spy(new JettyReactiveWebServerFactory());
this.customizer.customize(factory);
verify(factory).setUseForwardHeaders(true);
}
@Test
public void jettyAccessLogCanBeEnabled() {
JettyReactiveWebServerFactory factory = new JettyReactiveWebServerFactory(0);
Map<String, String> map = new HashMap<>();
map.put("server.jetty.accesslog.enabled", "true");
bindProperties(map);
this.customizer.customize(factory);
JettyWebServer webServer = (JettyWebServer) factory.getWebServer(mock(HttpHandler.class));
try {
NCSARequestLog requestLog = getNCSARequestLog(webServer);
assertThat(requestLog.getFilename()).isNull();
assertThat(requestLog.isAppend()).isFalse();
assertThat(requestLog.isExtended()).isFalse();
assertThat(requestLog.getLogCookies()).isFalse();
assertThat(requestLog.getLogServer()).isFalse();
assertThat(requestLog.getLogLatency()).isFalse();
}
finally {
webServer.stop();
}
}
@Test
public void jettyAccessLogCanBeCustomized() throws IOException {
File logFile = File.createTempFile("jetty_log", ".log");
JettyReactiveWebServerFactory factory = new JettyReactiveWebServerFactory(0);
Map<String, String> map = new HashMap<>();
String timezone = TimeZone.getDefault().getID();
map.put("server.jetty.accesslog.enabled", "true");
map.put("server.jetty.accesslog.filename", logFile.getAbsolutePath());
map.put("server.jetty.accesslog.file-date-format", "yyyy-MM-dd");
map.put("server.jetty.accesslog.retention-period", "42");
map.put("server.jetty.accesslog.append", "true");
map.put("server.jetty.accesslog.extended-format", "true");
map.put("server.jetty.accesslog.date-format", "HH:mm:ss");
map.put("server.jetty.accesslog.locale", "en_BE");
map.put("server.jetty.accesslog.time-zone", timezone);
map.put("server.jetty.accesslog.log-cookies", "true");
map.put("server.jetty.accesslog.log-server", "true");
map.put("server.jetty.accesslog.log-latency", "true");
bindProperties(map);
this.customizer.customize(factory);
JettyWebServer webServer = (JettyWebServer) factory.getWebServer(mock(HttpHandler.class));
NCSARequestLog requestLog = getNCSARequestLog(webServer);
try {
assertThat(requestLog.getFilename()).isEqualTo(logFile.getAbsolutePath());
assertThat(requestLog.getFilenameDateFormat()).isEqualTo("yyyy-MM-dd");
assertThat(requestLog.getRetainDays()).isEqualTo(42);
assertThat(requestLog.isAppend()).isTrue();
assertThat(requestLog.isExtended()).isTrue();
assertThat(requestLog.getLogDateFormat()).isEqualTo("HH:mm:ss");
assertThat(requestLog.getLogLocale()).isEqualTo(new Locale("en", "BE"));
assertThat(requestLog.getLogTimeZone()).isEqualTo(timezone);
assertThat(requestLog.getLogCookies()).isTrue();
assertThat(requestLog.getLogServer()).isTrue();
assertThat(requestLog.getLogLatency()).isTrue();
}
finally {
webServer.stop();
}
}
private NCSARequestLog getNCSARequestLog(JettyWebServer webServer) {
RequestLog requestLog = webServer.getServer().getRequestLog();
assertThat(requestLog).isInstanceOf(NCSARequestLog.class);
return (NCSARequestLog) requestLog;
}
private void bindProperties(Map<String, String> map) {
ConfigurationPropertySource source = new MapConfigurationPropertySource(map);
new Binder(source).bind("server", Bindable.ofInstance(this.properties));

3
spring-boot-project/spring-boot-parent/src/checkstyle/import-control.xml

@ -14,6 +14,9 @@ @@ -14,6 +14,9 @@
<subpackage name="client">
<allow pkg="org.springframework.boot.web.client" />
</subpackage>
<subpackage name="embedded.jetty">
<allow pkg="org.springframework.boot.web.embedded.jetty" />
</subpackage>
<subpackage name="embedded.tomcat">
<allow pkg="org.springframework.boot.web.embedded.tomcat" />
</subpackage>

56
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ConfigurableJettyWebServerFactory.java

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.web.embedded.jetty;
import org.eclipse.jetty.server.Server;
/**
* Web Server Factory configuration for Jetty-specific features.
*
* @author Brian Clozel
* @since 2.0.0
* @see JettyServletWebServerFactory
* @see JettyReactiveWebServerFactory
*/
public interface ConfigurableJettyWebServerFactory {
/**
* Set the number of acceptor threads to use.
* @param acceptors the number of acceptor threads to use
*/
void setAcceptors(int acceptors);
/**
* Set the number of selector threads to use.
* @param selectors the number of selector threads to use
*/
void setSelectors(int selectors);
/**
* Set if x-forward-* headers should be processed.
* @param useForwardHeaders if x-forward headers should be used
*/
void setUseForwardHeaders(boolean useForwardHeaders);
/**
* Add {@link JettyServerCustomizer}s that will be applied to the {@link Server}
* before it is started.
* @param customizers the customizers to add
*/
void addServerCustomizers(JettyServerCustomizer... customizers);
}

45
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ForwardHeadersCustomizer.java

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.web.embedded.jetty;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Server;
/**
* {@link JettyServerCustomizer} to add {@link ForwardedRequestCustomizer}.
* @author Phillip Webb
*/
class ForwardHeadersCustomizer implements JettyServerCustomizer {
@Override
public void customize(Server server) {
ForwardedRequestCustomizer customizer = new ForwardedRequestCustomizer();
for (Connector connector : server.getConnectors()) {
for (ConnectionFactory connectionFactory : connector
.getConnectionFactories()) {
if (connectionFactory instanceof HttpConfiguration.ConnectionFactory) {
((HttpConfiguration.ConnectionFactory) connectionFactory)
.getHttpConfiguration().addCustomizer(customizer);
}
}
}
}
}

94
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactory.java

@ -46,7 +46,8 @@ import org.springframework.util.Assert; @@ -46,7 +46,8 @@ import org.springframework.util.Assert;
* @author Brian Clozel
* @since 2.0.0
*/
public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory {
public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory
implements ConfigurableJettyWebServerFactory {
private static final Log logger = LogFactory
.getLog(JettyReactiveWebServerFactory.class);
@ -61,6 +62,8 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact @@ -61,6 +62,8 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
*/
private int selectors = -1;
private boolean useForwardHeaders;
private List<JettyServerCustomizer> jettyServerCustomizers = new ArrayList<>();
private ThreadPool threadPool;
@ -80,6 +83,16 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact @@ -80,6 +83,16 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
super(port);
}
@Override
public void setUseForwardHeaders(boolean useForwardHeaders) {
this.useForwardHeaders = useForwardHeaders;
}
@Override
public void setAcceptors(int acceptors) {
this.acceptors = acceptors;
}
@Override
public WebServer getWebServer(HttpHandler httpHandler) {
JettyHttpHandlerAdapter servlet = new JettyHttpHandlerAdapter(httpHandler);
@ -87,6 +100,37 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact @@ -87,6 +100,37 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
return new JettyWebServer(server, getPort() >= 0);
}
@Override
public void addServerCustomizers(JettyServerCustomizer... customizers) {
Assert.notNull(customizers, "Customizers must not be null");
this.jettyServerCustomizers.addAll(Arrays.asList(customizers));
}
/**
* Sets {@link JettyServerCustomizer}s that will be applied to the {@link Server}
* before it is started. Calling this method will replace any existing customizers.
* @param customizers the Jetty customizers to apply
*/
public void setServerCustomizers(
Collection<? extends JettyServerCustomizer> customizers) {
Assert.notNull(customizers, "Customizers must not be null");
this.jettyServerCustomizers = new ArrayList<>(customizers);
}
/**
* Returns a mutable collection of Jetty {@link JettyServerCustomizer}s that will be
* applied to the {@link Server} before it is created.
* @return the Jetty customizers
*/
public Collection<JettyServerCustomizer> getServerCustomizers() {
return this.jettyServerCustomizers;
}
@Override
public void setSelectors(int selectors) {
this.selectors = selectors;
}
protected Server createJettyServer(JettyHttpHandlerAdapter servlet) {
int port = (getPort() >= 0 ? getPort() : 0);
InetSocketAddress address = new InetSocketAddress(getAddress(), port);
@ -104,6 +148,9 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact @@ -104,6 +148,9 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
for (JettyServerCustomizer customizer : getServerCustomizers()) {
customizer.customize(server);
}
if (this.useForwardHeaders) {
new ForwardHeadersCustomizer().customize(server);
}
return server;
}
@ -143,49 +190,4 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact @@ -143,49 +190,4 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
this.threadPool = threadPool;
}
/**
* Set the number of acceptor threads to use.
* @param acceptors the number of acceptor threads to use
*/
public void setAcceptors(int acceptors) {
this.acceptors = acceptors;
}
/**
* Sets {@link JettyServerCustomizer}s that will be applied to the {@link Server}
* before it is started. Calling this method will replace any existing customizers.
* @param customizers the Jetty customizers to apply
*/
public void setServerCustomizers(
Collection<? extends JettyServerCustomizer> customizers) {
Assert.notNull(customizers, "Customizers must not be null");
this.jettyServerCustomizers = new ArrayList<>(customizers);
}
/**
* Returns a mutable collection of Jetty {@link JettyServerCustomizer}s that will be
* applied to the {@link Server} before it is created.
* @return the Jetty customizers
*/
public Collection<JettyServerCustomizer> getServerCustomizers() {
return this.jettyServerCustomizers;
}
/**
* Add {@link JettyServerCustomizer}s that will be applied to the {@link Server}
* before it is started.
* @param customizers the customizers to add
*/
public void addServerCustomizers(JettyServerCustomizer... customizers) {
Assert.notNull(customizers, "Customizers must not be null");
this.jettyServerCustomizers.addAll(Arrays.asList(customizers));
}
/**
* Set the number of selector threads to use.
* @param selectors the number of selector threads to use
*/
public void setSelectors(int selectors) {
this.selectors = selectors;
}
}

49
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java

@ -40,7 +40,6 @@ import org.eclipse.jetty.http.MimeTypes; @@ -40,7 +40,6 @@ import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Request;
@ -96,7 +95,7 @@ import org.springframework.util.StringUtils; @@ -96,7 +95,7 @@ import org.springframework.util.StringUtils;
* @see JettyWebServer
*/
public class JettyServletWebServerFactory extends AbstractServletWebServerFactory
implements ResourceLoaderAware {
implements ConfigurableJettyWebServerFactory, ResourceLoaderAware {
private List<Configuration> configurations = new ArrayList<>();
@ -438,29 +437,17 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor @@ -438,29 +437,17 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
this.resourceLoader = resourceLoader;
}
/**
* Set if x-forward-* headers should be processed.
* @param useForwardHeaders if x-forward headers should be used
* @since 1.3.0
*/
@Override
public void setUseForwardHeaders(boolean useForwardHeaders) {
this.useForwardHeaders = useForwardHeaders;
}
/**
* Set the number of acceptor threads to use.
* @param acceptors the number of acceptor threads to use
* @since 1.4.0
*/
@Override
public void setAcceptors(int acceptors) {
this.acceptors = acceptors;
}
/**
* Set the number of selector threads to use.
* @param selectors the number of selector threads to use
* @since 1.4.0
*/
@Override
public void setSelectors(int selectors) {
this.selectors = selectors;
}
@ -485,11 +472,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor @@ -485,11 +472,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
return this.jettyServerCustomizers;
}
/**
* Add {@link JettyServerCustomizer}s that will be applied to the {@link Server}
* before it is started.
* @param customizers the customizers to add
*/
@Override
public void addServerCustomizers(JettyServerCustomizer... customizers) {
Assert.notNull(customizers, "Customizers must not be null");
this.jettyServerCustomizers.addAll(Arrays.asList(customizers));
@ -565,28 +548,6 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor @@ -565,28 +548,6 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
}
}
/**
* {@link JettyServerCustomizer} to add {@link ForwardedRequestCustomizer}. Only
* supported with Jetty 9 (hence the inner class)
*/
private static class ForwardHeadersCustomizer implements JettyServerCustomizer {
@Override
public void customize(Server server) {
ForwardedRequestCustomizer customizer = new ForwardedRequestCustomizer();
for (Connector connector : server.getConnectors()) {
for (ConnectionFactory connectionFactory : connector
.getConnectionFactories()) {
if (connectionFactory instanceof HttpConfiguration.ConnectionFactory) {
((HttpConfiguration.ConnectionFactory) connectionFactory)
.getHttpConfiguration().addCustomizer(customizer);
}
}
}
}
}
/**
* {@link HandlerWrapper} to add a custom {@code server} header.
*/

Loading…
Cancel
Save