From c1876326f2fa1e82a6adc30a720c4604c376c1cb Mon Sep 17 00:00:00 2001 From: dragonfsky Date: Mon, 4 May 2026 20:06:25 +0800 Subject: [PATCH] Handle WebSocket messages after MVC session closed Ignore text messages received after the MVC WebSocket session state has already been removed during connection close. Closes gh-1449 Signed-off-by: dragonfsky --- .../server/webmvc/GraphQlWebSocketHandler.java | 5 ++++- .../webmvc/GraphQlWebSocketHandlerTests.java | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlWebSocketHandler.java b/spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlWebSocketHandler.java index 6faeda65..0e0eff7c 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlWebSocketHandler.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlWebSocketHandler.java @@ -245,10 +245,13 @@ protected void handleTextMessage(WebSocketSession session, TextMessage webSocket } private void handleInternal(WebSocketSession session, TextMessage webSocketMessage) throws IOException { + SessionState state = this.sessionInfoMap.get(session.getId()); + if (state == null) { + return; + } GraphQlWebSocketMessage message = decode(webSocketMessage); String id = message.getId(); Map payload = message.getPayload(); - SessionState state = getSessionInfo(session); switch (message.resolvedType()) { case SUBSCRIBE -> { if (state.getConnectionInitPayload() == null) { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphQlWebSocketHandlerTests.java b/spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphQlWebSocketHandlerTests.java index 40509148..ec4bd254 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphQlWebSocketHandlerTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphQlWebSocketHandlerTests.java @@ -71,6 +71,7 @@ import static org.assertj.core.api.Assertions.as; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.mockito.Mockito.mock; import static org.springframework.graphql.server.support.GraphQlWebSocketMessageType.CONNECTION_ACK; import static org.springframework.graphql.server.support.GraphQlWebSocketMessageType.PING; @@ -273,6 +274,22 @@ public void handleConnectionClosed(WebSocketSessionInfo info, int status, Map assertMessageType(message, GraphQlWebSocketMessageType.CONNECTION_ACK)) + .then(this.session::close) + .expectComplete() + .verify(TIMEOUT); + + this.handler.afterConnectionClosed(this.session, CloseStatus.NORMAL); + + assertThatNoException().isThrownBy(() -> + this.handler.handleTextMessage(this.session, new TextMessage("{\"type\":\"ping\"}"))); + } + @Test void connectionInitRejected() throws Exception {