Auto-configure GraphQL WebSocket endpoint

This commit auto-configures a GraphQL WebSocket endpoint for both Spring
MVC and Spring WebFlux. This is only enabled if the required libraries
are on the classpath and if the `"spring.graphql.websocket.path"`
property is defined.

See gh-29140
This commit is contained in:
Brian Clozel
2021-12-21 08:33:25 +01:00
parent 4ef9b9e3e5
commit 6ef1ed0dd0
5 changed files with 154 additions and 0 deletions

View File

@@ -33,12 +33,16 @@ import org.springframework.boot.test.context.runner.ReactiveWebApplicationContex
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
import org.springframework.graphql.web.WebGraphQlHandler;
import org.springframework.graphql.web.WebInterceptor;
import org.springframework.graphql.web.webflux.GraphQlHttpHandler;
import org.springframework.graphql.web.webflux.GraphQlWebSocketHandler;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.containsString;
/**
@@ -60,6 +64,12 @@ class GraphQlWebFluxAutoConfigurationTests {
"spring.graphql.cors.allowed-origins=https://example.com",
"spring.graphql.cors.allowed-methods=POST", "spring.graphql.cors.allow-credentials=true");
@Test
void shouldContributeDefaultBeans() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(GraphQlHttpHandler.class)
.hasSingleBean(WebGraphQlHandler.class).doesNotHaveBean(GraphQlWebSocketHandler.class));
}
@Test
void simpleQueryShouldWork() {
testWithWebClient((client) -> {
@@ -130,6 +140,12 @@ class GraphQlWebFluxAutoConfigurationTests {
});
}
@Test
void shouldConfigureWebSocketBeans() {
this.contextRunner.withPropertyValues("spring.graphql.websocket.path=/ws")
.run((context) -> assertThat(context).hasSingleBean(GraphQlWebSocketHandler.class));
}
private void testWithWebClient(Consumer<WebTestClient> consumer) {
this.contextRunner.run((context) -> {
WebTestClient client = WebTestClient.bindToApplicationContext(context).configureClient()

View File

@@ -31,13 +31,17 @@ import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
import org.springframework.graphql.web.WebGraphQlHandler;
import org.springframework.graphql.web.WebInterceptor;
import org.springframework.graphql.web.webmvc.GraphQlHttpHandler;
import org.springframework.graphql.web.webmvc.GraphQlWebSocketHandler;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@@ -65,6 +69,12 @@ class GraphQlWebMvcAutoConfigurationTests {
"spring.graphql.cors.allowed-origins=https://example.com",
"spring.graphql.cors.allowed-methods=POST", "spring.graphql.cors.allow-credentials=true");
@Test
void shouldContributeDefaultBeans() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(GraphQlHttpHandler.class)
.hasSingleBean(WebGraphQlHandler.class).doesNotHaveBean(GraphQlWebSocketHandler.class));
}
@Test
void simpleQueryShouldWork() {
testWith((mockMvc) -> {
@@ -137,6 +147,12 @@ class GraphQlWebMvcAutoConfigurationTests {
});
}
@Test
void shouldConfigureWebSocketBeans() {
this.contextRunner.withPropertyValues("spring.graphql.websocket.path=/ws")
.run((context) -> assertThat(context).hasSingleBean(GraphQlWebSocketHandler.class));
}
private void testWith(MockMvcConsumer mockMvcConsumer) {
this.contextRunner.run((context) -> {
MediaType mediaType = MediaType.APPLICATION_JSON;