Compare commits

...

5 Commits

Author SHA1 Message Date
Spencer Gibb 89cb8a9171
Returns databuffer if not netty 5 years ago
Spencer Gibb 5fe08db6e6
Run on random server port 5 years ago
Spencer Gibb 257ca8240f
Guard for webflux classes 5 years ago
Spencer Gibb 7459be61bd
Handles DataBufferWrapper 5 years ago
Spencer Gibb bc3841ce1b
Initial support for Jetty, Tomcat and Undertow. 5 years ago
  1. 1
      pom.xml
  2. 44
      spring-cloud-gateway-core/pom.xml
  3. 18
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
  4. 5
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java
  5. 10
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
  6. 6
      spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/TestUtils.java
  7. 2
      spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/WebfluxNotIncludedTests.java
  8. 5
      spring-cloud-gateway-dependencies/pom.xml
  9. 110
      spring-cloud-gateway-webserver/pom.xml
  10. 119
      spring-cloud-gateway-webserver/src/main/java/org/springframework/cloud/gateway/webserver/GatewayWebServerAutoConfiguration.java
  11. 46
      spring-cloud-gateway-webserver/src/main/java/org/springframework/cloud/gateway/webserver/NettyWebsocketProperties.java
  12. 3
      spring-cloud-gateway-webserver/src/main/resources/META-INF/spring.factories
  13. 101
      spring-cloud-gateway-webserver/src/test/java/org/springframework/cloud/gateway/webserver/GatewayWebServerAutoConfigurationTests.java

1
pom.xml

@ -152,6 +152,7 @@ @@ -152,6 +152,7 @@
<module>spring-cloud-gateway-dependencies</module>
<module>spring-cloud-gateway-mvc</module>
<module>spring-cloud-gateway-webflux</module>
<module>spring-cloud-gateway-webserver</module>
<module>spring-cloud-gateway-core</module>
<module>spring-cloud-starter-gateway</module>
<module>spring-cloud-gateway-sample</module>

44
spring-cloud-gateway-core/pom.xml

@ -19,6 +19,10 @@ @@ -19,6 +19,10 @@
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-webserver</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
@ -239,6 +243,46 @@ @@ -239,6 +243,46 @@
</plugins>
</build>
<profiles>
<profile>
<id>jetty</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>tomcat</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>undertow</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>java8plus</id>
<activation>

18
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java

@ -43,13 +43,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -43,13 +43,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.embedded.NettyWebServerFactoryCustomizer;
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint;
import org.springframework.cloud.gateway.actuate.GatewayLegacyControllerEndpoint;
import org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter;
@ -560,23 +557,10 @@ public class GatewayAutoConfiguration { @@ -560,23 +557,10 @@ public class GatewayAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HttpClient.class)
protected static class NettyConfiguration {
protected static class NettyClientConfiguration {
protected final Log logger = LogFactory.getLog(getClass());
@Bean
@ConditionalOnProperty(name = "spring.cloud.gateway.httpserver.wiretap")
public NettyWebServerFactoryCustomizer nettyServerWiretapCustomizer(
Environment environment, ServerProperties serverProperties) {
return new NettyWebServerFactoryCustomizer(environment, serverProperties) {
@Override
public void customize(NettyReactiveWebServerFactory factory) {
factory.addServerCustomizers(httpServer -> httpServer.wiretap(true));
super.customize(factory);
}
};
}
@Bean
@ConditionalOnMissingBean
public HttpClient gatewayHttpClient(HttpClientProperties properties) {

5
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java

@ -40,6 +40,7 @@ import org.springframework.cloud.gateway.route.Route; @@ -40,6 +40,7 @@ import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.TimeoutException;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferWrapper;
import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.core.io.buffer.NettyDataBuffer;
import org.springframework.http.HttpHeaders;
@ -215,6 +216,10 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered { @@ -215,6 +216,10 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered {
DefaultDataBuffer buffer = (DefaultDataBuffer) dataBuffer;
return Unpooled.wrappedBuffer(buffer.getNativeBuffer());
}
else if (dataBuffer instanceof DataBufferWrapper) {
DataBufferWrapper wrapper = (DataBufferWrapper) dataBuffer;
return Unpooled.wrappedBuffer(wrapper.asByteBuffer());
}
throw new IllegalArgumentException(
"Unable to handle DataBuffer of type " + dataBuffer.getClass());
}

10
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java

@ -359,9 +359,13 @@ public final class ServerWebExchangeUtils { @@ -359,9 +359,13 @@ public final class ServerWebExchangeUtils {
// probably == downstream closed
return null;
}
// TODO: deal with Netty
NettyDataBuffer pdb = (NettyDataBuffer) dataBuffer;
return pdb.factory().wrap(pdb.getNativeBuffer().retainedSlice());
if (dataBuffer instanceof NettyDataBuffer) {
NettyDataBuffer buffer = (NettyDataBuffer) dataBuffer;
return buffer.factory()
.wrap(buffer.getNativeBuffer().retainedSlice());
}
// FIXME: is this going to be a problem?
return dataBuffer;
}).flux();
}
};

6
spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/TestUtils.java

@ -19,6 +19,7 @@ package org.springframework.cloud.gateway.test; @@ -19,6 +19,7 @@ package org.springframework.cloud.gateway.test;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.reactive.function.client.ClientResponse;
import static org.assertj.core.api.Assertions.assertThat;
@ -31,7 +32,10 @@ public class TestUtils { @@ -31,7 +32,10 @@ public class TestUtils {
@SuppressWarnings("unchecked")
public static Map<String, Object> getMap(Map response, String key) {
assertThat(response).containsKey(key).isInstanceOf(Map.class);
return (Map<String, Object>) response.get(key);
Map<String, Object> map = (Map<String, Object>) response.get(key);
LinkedCaseInsensitiveMap<Object> caseInsensitiveMap = new LinkedCaseInsensitiveMap<>();
caseInsensitiveMap.putAll(map);
return caseInsensitiveMap;
}
public static void assertStatus(ClientResponse response, HttpStatus status) {

2
spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/WebfluxNotIncludedTests.java

@ -31,7 +31,7 @@ public class WebfluxNotIncludedTests { @@ -31,7 +31,7 @@ public class WebfluxNotIncludedTests {
@Test
public void noWebfluxWorks() {
new SpringApplication(Config.class).run();
new SpringApplication(Config.class).run("--server.port=0");
}
@SpringBootConfiguration

5
spring-cloud-gateway-dependencies/pom.xml

@ -37,6 +37,11 @@ @@ -37,6 +37,11 @@
<artifactId>spring-cloud-gateway-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-webserver</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>

110
spring-cloud-gateway-webserver/pom.xml

@ -0,0 +1,110 @@ @@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-gateway-webserver</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Gateway Web Server</name>
<description>Spring Cloud Gateway Web Server</description>
<properties>
<main.basedir>${basedir}/..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>java8plus</id>
<activation>
<jdk>[1.8,2.0)</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

119
spring-cloud-gateway-webserver/src/main/java/org/springframework/cloud/gateway/webserver/GatewayWebServerAutoConfiguration.java

@ -0,0 +1,119 @@ @@ -0,0 +1,119 @@
/*
* Copyright 2013-2020 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
*
* https://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.cloud.gateway.webserver;
import java.io.IOException;
import io.undertow.Undertow;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.UpgradeProtocol;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.xnio.OptionMap;
import org.xnio.SslClientAuthMode;
import org.xnio.Xnio;
import reactor.netty.http.server.HttpServer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.embedded.NettyWebServerFactoryCustomizer;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.reactive.socket.client.JettyWebSocketClient;
import org.springframework.web.reactive.socket.client.TomcatWebSocketClient;
import org.springframework.web.reactive.socket.client.UndertowWebSocketClient;
import org.springframework.web.reactive.socket.client.WebSocketClient;
/**
* @author Spencer Gibb
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayWebServerAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class })
public static class JettyWebServerFactoryCustomizerConfiguration {
@Bean
@ConditionalOnMissingBean(WebSocketClient.class)
public JettyWebSocketClient jettyWebSocketClient() {
return new JettyWebSocketClient();
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HttpServer.class)
// Only enable netty if all other web servers are missing
@ConditionalOnMissingClass({ "org.eclipse.jetty.server.Server",
"org.eclipse.jetty.util.Loader", "org.eclipse.jetty.webapp.WebAppContext",
"org.apache.catalina.startup.Tomcat", "org.apache.coyote.UpgradeProtocol",
"io.undertow.Undertow", "org.xnio.SslClientAuthMode" })
public static class NettyWebServerConfiguration {
@Bean
@ConditionalOnProperty(name = "spring.cloud.gateway.httpserver.wiretap")
public NettyWebServerFactoryCustomizer nettyServerWiretapCustomizer(
Environment environment, ServerProperties serverProperties) {
return new NettyWebServerFactoryCustomizer(environment, serverProperties) {
@Override
public void customize(NettyReactiveWebServerFactory factory) {
factory.addServerCustomizers(httpServer -> httpServer.wiretap(true));
super.customize(factory);
}
};
}
// ReactorNettyWebSocketClient is still in GatwayAutoConfiguration because it
// needs HttpClient
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
public static class TomcatWebServerConfiguration {
@Bean
@ConditionalOnMissingBean(WebSocketClient.class)
public TomcatWebSocketClient tomcatWebSocketClient() {
return new TomcatWebSocketClient();
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Undertow.class, SslClientAuthMode.class })
public static class UndertowWebServerConfiguration {
@Bean
@ConditionalOnMissingBean(WebSocketClient.class)
public UndertowWebSocketClient undertowWebSocketClient() throws IOException {
return new UndertowWebSocketClient(
Xnio.getInstance().createWorker(OptionMap.EMPTY));
}
}
}

46
spring-cloud-gateway-webserver/src/main/java/org/springframework/cloud/gateway/webserver/NettyWebsocketProperties.java

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
/*
* Copyright 2013-2020 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
*
* https://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.cloud.gateway.webserver;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.style.ToStringCreator;
/**
* Configuration properties for the Netty
* {@link org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient}.
*/
@ConfigurationProperties("spring.cloud.gateway.httpclient.websocket")
public class NettyWebsocketProperties {
/** Max frame payload length. */
private Integer maxFramePayloadLength;
public Integer getMaxFramePayloadLength() {
return this.maxFramePayloadLength;
}
public void setMaxFramePayloadLength(Integer maxFramePayloadLength) {
this.maxFramePayloadLength = maxFramePayloadLength;
}
@Override
public String toString() {
return new ToStringCreator(this)
.append("maxFramePayloadLength", maxFramePayloadLength).toString();
}
}

3
spring-cloud-gateway-webserver/src/main/resources/META-INF/spring.factories

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.gateway.webserver.GatewayWebServerAutoConfiguration

101
spring-cloud-gateway-webserver/src/test/java/org/springframework/cloud/gateway/webserver/GatewayWebServerAutoConfigurationTests.java

@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
/*
* Copyright 2013-2020 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
*
* https://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.cloud.gateway.webserver;
import io.undertow.Undertow;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.UpgradeProtocol;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.Test;
import org.xnio.SslClientAuthMode;
import reactor.netty.http.server.HttpServer;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.embedded.NettyWebServerFactoryCustomizer;
import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.web.reactive.socket.client.JettyWebSocketClient;
import org.springframework.web.reactive.socket.client.TomcatWebSocketClient;
import org.springframework.web.reactive.socket.client.UndertowWebSocketClient;
import org.springframework.web.reactive.socket.client.WebSocketClient;
import static org.assertj.core.api.Assertions.assertThat;
public class GatewayWebServerAutoConfigurationTests {
@Test
public void jettyServerWorks() {
new ReactiveWebApplicationContextRunner()
.withClassLoader(new FilteredClassLoader(HttpServer.class, Tomcat.class,
UpgradeProtocol.class, Undertow.class, SslClientAuthMode.class))
.withConfiguration(
AutoConfigurations.of(GatewayWebServerAutoConfiguration.class))
.run(context -> {
assertThat(context).hasSingleBean(JettyWebSocketClient.class)
.hasSingleBean(WebSocketClient.class);
});
}
@Test
public void nettyServerWorks() {
new ReactiveWebApplicationContextRunner()
.withClassLoader(new FilteredClassLoader(Server.class, Loader.class,
WebAppContext.class, Tomcat.class, UpgradeProtocol.class,
Undertow.class, SslClientAuthMode.class))
.withConfiguration(AutoConfigurations.of(
ReactiveWebServerFactoryAutoConfiguration.class,
GatewayWebServerAutoConfiguration.class))
.withPropertyValues("spring.cloud.gateway.httpserver.wiretap=true")
.run(context -> {
assertThat(context)
.hasSingleBean(NettyWebServerFactoryCustomizer.class)
.doesNotHaveBean(WebSocketClient.class);
});
}
@Test
public void tomcatServerWorks() {
new ReactiveWebApplicationContextRunner()
.withClassLoader(new FilteredClassLoader(Server.class, Loader.class,
WebAppContext.class, HttpServer.class, Undertow.class,
SslClientAuthMode.class))
.withConfiguration(
AutoConfigurations.of(GatewayWebServerAutoConfiguration.class))
.run(context -> {
assertThat(context).hasSingleBean(TomcatWebSocketClient.class)
.hasSingleBean(WebSocketClient.class);
});
}
@Test
public void undertowServerWorks() {
new ReactiveWebApplicationContextRunner()
.withClassLoader(new FilteredClassLoader(Server.class, Loader.class,
WebAppContext.class, HttpServer.class, Tomcat.class,
UpgradeProtocol.class))
.withConfiguration(
AutoConfigurations.of(GatewayWebServerAutoConfiguration.class))
.run(context -> {
assertThat(context).hasSingleBean(UndertowWebSocketClient.class)
.hasSingleBean(WebSocketClient.class);
});
}
}
Loading…
Cancel
Save