Apply RSocket server customizers to netty web server

This commit applies `ServerRSocketFactoryCustomizer` beans to RSocket
setups when the RSocket server is being plugged into an existing Reactor
Netty web server.

Fixes gh-18208
This commit is contained in:
Brian Clozel 2019-09-11 21:06:11 +02:00
parent 1f280e394b
commit 219bafaba1
4 changed files with 52 additions and 5 deletions

View File

@ -68,10 +68,13 @@ public class RSocketServerAutoConfiguration {
static class WebFluxServerAutoConfiguration {
@Bean
@ConditionalOnMissingBean
RSocketWebSocketNettyRouteProvider rSocketWebsocketRouteProvider(RSocketProperties properties,
RSocketMessageHandler messageHandler) {
return new RSocketWebSocketNettyRouteProvider(properties.getServer().getMappingPath(),
messageHandler.responder());
RSocketMessageHandler messageHandler, ObjectProvider<ServerRSocketFactoryCustomizer> customizers) {
RSocketWebSocketNettyRouteProvider routeProvider = new RSocketWebSocketNettyRouteProvider(
properties.getServer().getMappingPath(), messageHandler.responder());
routeProvider.setCustomizers(customizers.orderedStream().collect(Collectors.toList()));
return routeProvider;
}
}

View File

@ -16,12 +16,16 @@
package org.springframework.boot.autoconfigure.rsocket;
import java.util.Collections;
import java.util.List;
import io.rsocket.RSocketFactory;
import io.rsocket.SocketAcceptor;
import io.rsocket.transport.ServerTransport;
import io.rsocket.transport.netty.server.WebsocketRouteTransport;
import reactor.netty.http.server.HttpServerRoutes;
import org.springframework.boot.rsocket.server.ServerRSocketFactoryCustomizer;
import org.springframework.boot.web.embedded.netty.NettyRouteProvider;
/**
@ -35,15 +39,24 @@ class RSocketWebSocketNettyRouteProvider implements NettyRouteProvider {
private final SocketAcceptor socketAcceptor;
private List<ServerRSocketFactoryCustomizer> customizers = Collections.emptyList();
RSocketWebSocketNettyRouteProvider(String mappingPath, SocketAcceptor socketAcceptor) {
this.mappingPath = mappingPath;
this.socketAcceptor = socketAcceptor;
}
void setCustomizers(List<ServerRSocketFactoryCustomizer> customizers) {
this.customizers = customizers;
}
@Override
public HttpServerRoutes apply(HttpServerRoutes httpServerRoutes) {
ServerTransport.ConnectionAcceptor acceptor = RSocketFactory.receive().acceptor(this.socketAcceptor)
.toConnectionAcceptor();
RSocketFactory.ServerRSocketFactory server = RSocketFactory.receive();
for (ServerRSocketFactoryCustomizer customizer : this.customizers) {
server = customizer.apply(server);
}
ServerTransport.ConnectionAcceptor acceptor = server.acceptor(this.socketAcceptor).toConnectionAcceptor();
return httpServerRoutes.ws(this.mappingPath, WebsocketRouteTransport.newHandler(acceptor));
}

View File

@ -86,6 +86,15 @@ class RSocketServerAutoConfigurationTests {
.getBeanNames(RSocketServerBootstrap.class).containsExactly("customServerBootstrap"));
}
@Test
void shouldUseCustomNettyRouteProvider() {
reactiveWebContextRunner().withUserConfiguration(CustomNettyRouteProviderConfig.class)
.withPropertyValues("spring.rsocket.server.transport=websocket",
"spring.rsocket.server.mapping-path=/rsocket")
.run((context) -> assertThat(context).getBeanNames(RSocketWebSocketNettyRouteProvider.class)
.containsExactly("customNettyRouteProvider"));
}
private ApplicationContextRunner contextRunner() {
return new ApplicationContextRunner().withUserConfiguration(BaseConfiguration.class)
.withConfiguration(AutoConfigurations.of(RSocketServerAutoConfiguration.class));
@ -119,4 +128,14 @@ class RSocketServerAutoConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
static class CustomNettyRouteProviderConfig {
@Bean
RSocketWebSocketNettyRouteProvider customNettyRouteProvider() {
return mock(RSocketWebSocketNettyRouteProvider.class);
}
}
}

View File

@ -28,6 +28,7 @@ import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
import org.springframework.boot.rsocket.server.ServerRSocketFactoryCustomizer;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
@ -76,6 +77,7 @@ class RSocketWebSocketNettyRouteProviderTests {
WebTestClient client = createWebTestClient(serverContext.getWebServer());
client.get().uri("/protocol").exchange().expectStatus().isOk().expectBody().jsonPath("name",
"http");
assertThat(WebConfiguration.customizerCallCount).isEqualTo(1);
});
}
@ -93,6 +95,8 @@ class RSocketWebSocketNettyRouteProviderTests {
@Configuration(proxyBeanMethods = false)
static class WebConfiguration {
static int customizerCallCount = 0;
@Bean
WebController webController() {
return new WebController();
@ -105,6 +109,14 @@ class RSocketWebSocketNettyRouteProviderTests {
return serverFactory;
}
@Bean
ServerRSocketFactoryCustomizer myRSocketFactoryCustomizer() {
return (server) -> {
customizerCallCount++;
return server;
};
}
}
@Controller