Add reactive web server infrastructure
This commit adds the infrastructure for creating and customizing reactive embedded web servers. Common configuration has been refactored into the new `ConfigurableEmbeddedWebServer` interface. See gh-8302
This commit is contained in:
@@ -112,6 +112,7 @@ org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguratio
|
||||
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.webflux.ReactiveWebServerAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.context.embedded;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.boot.web.servlet.ErrorPage;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link ConfigurableReactiveWebServer} implementations.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class AbstractConfigurableReactiveWebServer implements ConfigurableReactiveWebServer {
|
||||
|
||||
private int port = 8080;
|
||||
|
||||
private Set<ErrorPage> errorPages = new LinkedHashSet<ErrorPage>();
|
||||
|
||||
private InetAddress address;
|
||||
|
||||
private Ssl ssl;
|
||||
|
||||
private SslStoreProvider sslStoreProvider;
|
||||
|
||||
private Compression compression;
|
||||
|
||||
private String serverHeader;
|
||||
|
||||
/**
|
||||
* Create a new {@link AbstractConfigurableReactiveWebServer} instance.
|
||||
*/
|
||||
public AbstractConfigurableReactiveWebServer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AbstractConfigurableReactiveWebServer} instance with the
|
||||
* specified port.
|
||||
* @param port the port number for the reactive web server
|
||||
*/
|
||||
public AbstractConfigurableReactiveWebServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAddress(InetAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the address that the reactive web server binds to.
|
||||
* @return the address
|
||||
*/
|
||||
public InetAddress getAddress() {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* The port that the reactive web server listens on.
|
||||
* @return the port
|
||||
*/
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorPages(Set<? extends ErrorPage> errorPages) {
|
||||
Assert.notNull(errorPages, "ErrorPages must not be null");
|
||||
this.errorPages = new LinkedHashSet<ErrorPage>(errorPages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addErrorPages(ErrorPage... errorPages) {
|
||||
Assert.notNull(errorPages, "ErrorPages must not be null");
|
||||
this.errorPages.addAll(Arrays.asList(errorPages));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a mutable set of {@link ErrorPage ErrorPages} that will be used when
|
||||
* handling exceptions.
|
||||
* @return the error pages
|
||||
*/
|
||||
public Set<ErrorPage> getErrorPages() {
|
||||
return this.errorPages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSsl(Ssl ssl) {
|
||||
this.ssl = ssl;
|
||||
}
|
||||
|
||||
public Ssl getSsl() {
|
||||
return this.ssl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSslStoreProvider(SslStoreProvider sslStoreProvider) {
|
||||
this.sslStoreProvider = sslStoreProvider;
|
||||
}
|
||||
|
||||
public SslStoreProvider getSslStoreProvider() {
|
||||
return this.sslStoreProvider;
|
||||
}
|
||||
|
||||
public Compression getCompression() {
|
||||
return this.compression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompression(Compression compression) {
|
||||
this.compression = compression;
|
||||
}
|
||||
|
||||
public String getServerHeader() {
|
||||
return this.serverHeader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServerHeader(String serverHeader) {
|
||||
this.serverHeader = serverHeader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.context.embedded;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link ReactiveWebServerFactory} implementations.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class AbstractReactiveWebServerFactory
|
||||
extends AbstractConfigurableReactiveWebServer
|
||||
implements ReactiveWebServerFactory {
|
||||
|
||||
public AbstractReactiveWebServerFactory() {
|
||||
}
|
||||
|
||||
public AbstractReactiveWebServerFactory(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,16 +17,12 @@
|
||||
package org.springframework.boot.context.embedded;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.boot.web.servlet.ErrorPage;
|
||||
import org.springframework.boot.web.servlet.ErrorPageRegistry;
|
||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
|
||||
/**
|
||||
@@ -41,7 +37,7 @@ import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
* @see EmbeddedServletContainerFactory
|
||||
* @see EmbeddedServletContainerCustomizer
|
||||
*/
|
||||
public interface ConfigurableEmbeddedServletContainer extends ErrorPageRegistry {
|
||||
public interface ConfigurableEmbeddedServletContainer extends ConfigurableEmbeddedWebServer {
|
||||
|
||||
/**
|
||||
* Sets the context path for the embedded servlet container. The context should start
|
||||
@@ -59,14 +55,6 @@ public interface ConfigurableEmbeddedServletContainer extends ErrorPageRegistry
|
||||
*/
|
||||
void setDisplayName(String displayName);
|
||||
|
||||
/**
|
||||
* Sets the port that the embedded servlet container should listen on. If not
|
||||
* specified port '8080' will be used. Use port -1 to disable auto-start (i.e start
|
||||
* the web application context but not have it listen to any port).
|
||||
* @param port the port to set
|
||||
*/
|
||||
void setPort(int port);
|
||||
|
||||
/**
|
||||
* The session timeout in seconds (default 30 minutes). If 0 or negative then sessions
|
||||
* never expire.
|
||||
@@ -94,12 +82,6 @@ public interface ConfigurableEmbeddedServletContainer extends ErrorPageRegistry
|
||||
*/
|
||||
void setSessionStoreDir(File sessionStoreDir);
|
||||
|
||||
/**
|
||||
* Sets the specific network address that the server should bind to.
|
||||
* @param address the address to set (defaults to {@code null})
|
||||
*/
|
||||
void setAddress(InetAddress address);
|
||||
|
||||
/**
|
||||
* Set if the DefaultServlet should be registered. Defaults to {@code true} so that
|
||||
* files from the {@link #setDocumentRoot(File) document root} will be served.
|
||||
@@ -107,12 +89,6 @@ public interface ConfigurableEmbeddedServletContainer extends ErrorPageRegistry
|
||||
*/
|
||||
void setRegisterDefaultServlet(boolean registerDefaultServlet);
|
||||
|
||||
/**
|
||||
* Sets the error pages that will be used when handling exceptions.
|
||||
* @param errorPages the error pages
|
||||
*/
|
||||
void setErrorPages(Set<? extends ErrorPage> errorPages);
|
||||
|
||||
/**
|
||||
* Sets the mime-type mappings.
|
||||
* @param mimeMappings the mime type mappings (defaults to
|
||||
@@ -146,38 +122,12 @@ public interface ConfigurableEmbeddedServletContainer extends ErrorPageRegistry
|
||||
*/
|
||||
void addInitializers(ServletContextInitializer... initializers);
|
||||
|
||||
/**
|
||||
* Sets the SSL configuration that will be applied to the container's default
|
||||
* connector.
|
||||
* @param ssl the SSL configuration
|
||||
*/
|
||||
void setSsl(Ssl ssl);
|
||||
|
||||
/**
|
||||
* Sets a provider that will be used to obtain SSL stores.
|
||||
* @param sslStoreProvider the SSL store provider
|
||||
*/
|
||||
void setSslStoreProvider(SslStoreProvider sslStoreProvider);
|
||||
|
||||
/**
|
||||
* Sets the configuration that will be applied to the container's JSP servlet.
|
||||
* @param jsp the JSP servlet configuration
|
||||
*/
|
||||
void setJsp(Jsp jsp);
|
||||
|
||||
/**
|
||||
* Sets the compression configuration that will be applied to the container's default
|
||||
* connector.
|
||||
* @param compression the compression configuration
|
||||
*/
|
||||
void setCompression(Compression compression);
|
||||
|
||||
/**
|
||||
* Sets the server header value.
|
||||
* @param serverHeader the server header value
|
||||
*/
|
||||
void setServerHeader(String serverHeader);
|
||||
|
||||
/**
|
||||
* Sets the Locale to Charset mappings.
|
||||
* @param localeCharsetMappings the Locale to Charset mappings
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.context.embedded;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.boot.web.servlet.ErrorPage;
|
||||
import org.springframework.boot.web.servlet.ErrorPageRegistry;
|
||||
|
||||
/**
|
||||
* Interface that regroups common customizations to
|
||||
* embedded server factories such as {@link EmbeddedServletContainerFactory}
|
||||
* and {@link ReactiveWebServerFactory}.
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public interface ConfigurableEmbeddedWebServer extends ErrorPageRegistry {
|
||||
|
||||
/**
|
||||
* Sets the port that the embedded servlet container should listen on. If not
|
||||
* specified port '8080' will be used. Use port -1 to disable auto-start (i.e start
|
||||
* the web application context but not have it listen to any port).
|
||||
* @param port the port to set
|
||||
*/
|
||||
void setPort(int port);
|
||||
|
||||
/**
|
||||
* Sets the specific network address that the server should bind to.
|
||||
* @param address the address to set (defaults to {@code null})
|
||||
*/
|
||||
void setAddress(InetAddress address);
|
||||
|
||||
/**
|
||||
* Sets the error pages that will be used when handling exceptions.
|
||||
* @param errorPages the error pages
|
||||
*/
|
||||
void setErrorPages(Set<? extends ErrorPage> errorPages);
|
||||
|
||||
/**
|
||||
* Sets the SSL configuration that will be applied to the container's default
|
||||
* connector.
|
||||
* @param ssl the SSL configuration
|
||||
*/
|
||||
void setSsl(Ssl ssl);
|
||||
|
||||
/**
|
||||
* Sets a provider that will be used to obtain SSL stores.
|
||||
* @param sslStoreProvider the SSL store provider
|
||||
*/
|
||||
void setSslStoreProvider(SslStoreProvider sslStoreProvider);
|
||||
|
||||
/**
|
||||
* Sets the compression configuration that will be applied to the container's default
|
||||
* connector.
|
||||
* @param compression the compression configuration
|
||||
*/
|
||||
void setCompression(Compression compression);
|
||||
|
||||
/**
|
||||
* Sets the server header value.
|
||||
* @param serverHeader the server header value
|
||||
*/
|
||||
void setServerHeader(String serverHeader);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.context.embedded;
|
||||
|
||||
/**
|
||||
* Interface that represents customizations to a {@link ReactiveWebServerFactory}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public interface ConfigurableReactiveWebServer extends ConfigurableEmbeddedWebServer {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.context.embedded;
|
||||
|
||||
/**
|
||||
* Strategy interface for customizing auto-configured embedded reactive servers. Any
|
||||
* beans of this type will get a callback with the server factory before the server
|
||||
* itself is started, so you can set the port, address, error pages etc.
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ReactiveWebServerCustomizer {
|
||||
|
||||
/**
|
||||
* Customize the specified {@link ConfigurableReactiveWebServer}.
|
||||
* @param server the server to customize
|
||||
*/
|
||||
void customize(ConfigurableReactiveWebServer server);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.context.embedded;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
|
||||
/**
|
||||
* {@link BeanPostProcessor} that applies all {@link ReactiveWebServerCustomizer}s
|
||||
* from the bean factory to {@link ConfigurableReactiveWebServer} beans.
|
||||
*
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class ReactiveWebServerCustomizerBeanPostProcessor
|
||||
implements BeanPostProcessor, ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private List<ReactiveWebServerCustomizer> customizers;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof ConfigurableReactiveWebServer) {
|
||||
postProcessBeforeInitialization((ConfigurableReactiveWebServer) bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
private void postProcessBeforeInitialization(
|
||||
ConfigurableReactiveWebServer bean) {
|
||||
for (ReactiveWebServerCustomizer customizer : getCustomizers()) {
|
||||
customizer.customize(bean);
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<ReactiveWebServerCustomizer> getCustomizers() {
|
||||
if (this.customizers == null) {
|
||||
// Look up does not include the parent context
|
||||
this.customizers = new ArrayList<ReactiveWebServerCustomizer>(
|
||||
this.applicationContext
|
||||
.getBeansOfType(ReactiveWebServerCustomizer.class,
|
||||
false, false)
|
||||
.values());
|
||||
Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
|
||||
this.customizers = Collections.unmodifiableList(this.customizers);
|
||||
}
|
||||
return this.customizers;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.context.embedded;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
|
||||
/**
|
||||
* Factory interface that can be used to create reactive {@link EmbeddedWebServer}s.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
* @see EmbeddedWebServer
|
||||
*/
|
||||
public interface ReactiveWebServerFactory {
|
||||
|
||||
/**
|
||||
* Gets a new fully configured but paused {@link EmbeddedWebServer} instance.
|
||||
* Clients should not be able to connect to the returned server until
|
||||
* {@link EmbeddedWebServer#start()} is called (which happens when the
|
||||
* {@link ApplicationContext} has been fully refreshed).
|
||||
* @param httpHandler the HTTP handler in charge of processing requests
|
||||
* @return a fully configured and started {@link EmbeddedWebServer}
|
||||
* @see EmbeddedWebServer#stop()
|
||||
*/
|
||||
EmbeddedWebServer getReactiveHttpServer(HttpHandler httpHandler);
|
||||
|
||||
/**
|
||||
* Register a map of {@link HttpHandler}s, each to a specific context path.
|
||||
*
|
||||
* @param handlerMap a map of context paths and the associated {@code HttpHandler}
|
||||
* @return a fully configured and started {@link EmbeddedWebServer}
|
||||
* @see EmbeddedWebServer#stop()
|
||||
*/
|
||||
EmbeddedWebServer getReactiveHttpServer(Map<String, HttpHandler> handlerMap);
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.context.embedded;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.boot.testutil.InternalOutputCapture;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.util.SocketUtils;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Base for testing classes that extends {@link AbstractReactiveWebServerFactory}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Rule
|
||||
public InternalOutputCapture output = new InternalOutputCapture();
|
||||
|
||||
protected EmbeddedWebServer webServer;
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (this.webServer != null) {
|
||||
try {
|
||||
this.webServer.stop();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract AbstractReactiveWebServerFactory getFactory();
|
||||
|
||||
@Test
|
||||
public void startStopServer() {
|
||||
this.webServer = getFactory().getReactiveHttpServer(new EchoHandler());
|
||||
this.webServer.start();
|
||||
Mono<String> result = getWebClient()
|
||||
.post().uri("/test")
|
||||
.contentType(MediaType.TEXT_PLAIN)
|
||||
.exchange(BodyInserters.fromObject("Hello World"))
|
||||
.then(response -> response.bodyToMono(String.class));
|
||||
assertThat(result.block()).isEqualTo("Hello World");
|
||||
|
||||
this.webServer.stop();
|
||||
Mono<ClientResponse> response = getWebClient()
|
||||
.post().uri("/test")
|
||||
.contentType(MediaType.TEXT_PLAIN)
|
||||
.exchange(BodyInserters.fromObject("Hello World"));
|
||||
StepVerifier.create(response)
|
||||
.expectError()
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificPort() throws Exception {
|
||||
AbstractReactiveWebServerFactory factory = getFactory();
|
||||
int specificPort = SocketUtils.findAvailableTcpPort(41000);
|
||||
factory.setPort(specificPort);
|
||||
this.webServer = factory.getReactiveHttpServer(new EchoHandler());
|
||||
this.webServer.start();
|
||||
|
||||
Mono<String> result = WebClient.create("http://localhost:" + specificPort)
|
||||
.post().uri("/test")
|
||||
.contentType(MediaType.TEXT_PLAIN)
|
||||
.exchange(BodyInserters.fromObject("Hello World"))
|
||||
.then(response -> response.bodyToMono(String.class));
|
||||
|
||||
assertThat(result.block()).isEqualTo("Hello World");
|
||||
assertThat(this.webServer.getPort()).isEqualTo(specificPort);
|
||||
}
|
||||
|
||||
protected WebClient getWebClient() {
|
||||
return WebClient.create("http://localhost:" + this.webServer.getPort());
|
||||
}
|
||||
|
||||
protected static class EchoHandler implements HttpHandler {
|
||||
@Override
|
||||
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
return response.writeWith(request.getBody());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user