Add check for unused WebSocket sessions
Sessions connected to a STOMP endpoint are expected to receive some client messages. Having received none after successfully connecting could be an indication of proxy or network issue. This change adds periodic checks to see if we have not received any messages on a session which is an indication the session isn't going anywhere most likely due to a proxy issue (or unreliable network) and close those sessions. Issue: SPR-11884
This commit is contained in:
@@ -17,16 +17,24 @@
|
||||
package org.springframework.web.socket.messaging;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
import org.springframework.web.socket.TextMessage;
|
||||
import org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator;
|
||||
import org.springframework.web.socket.handler.TestWebSocketSession;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
@@ -56,11 +64,9 @@ public class SubProtocolWebSocketHandlerTests {
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
this.webSocketHandler = new SubProtocolWebSocketHandler(this.inClientChannel, this.outClientChannel);
|
||||
when(stompHandler.getSupportedProtocols()).thenReturn(Arrays.asList("v10.stomp", "v11.stomp", "v12.stomp"));
|
||||
when(mqttHandler.getSupportedProtocols()).thenReturn(Arrays.asList("MQTT"));
|
||||
|
||||
this.session = new TestWebSocketSession();
|
||||
this.session.setId("1");
|
||||
}
|
||||
@@ -140,4 +146,32 @@ public class SubProtocolWebSocketHandlerTests {
|
||||
this.webSocketHandler.afterConnectionEstablished(session);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkSession() throws Exception {
|
||||
TestWebSocketSession session1 = new TestWebSocketSession("id1");
|
||||
TestWebSocketSession session2 = new TestWebSocketSession("id2");
|
||||
session1.setAcceptedProtocol("v12.stomp");
|
||||
session2.setAcceptedProtocol("v12.stomp");
|
||||
|
||||
this.webSocketHandler.setProtocolHandlers(Arrays.asList(this.stompHandler));
|
||||
this.webSocketHandler.afterConnectionEstablished(session1);
|
||||
this.webSocketHandler.afterConnectionEstablished(session2);
|
||||
session1.setOpen(true);
|
||||
session2.setOpen(true);
|
||||
|
||||
long sixtyOneSecondsAgo = System.currentTimeMillis() - 61 * 1000;
|
||||
new DirectFieldAccessor(this.webSocketHandler).setPropertyValue("lastSessionCheckTime", sixtyOneSecondsAgo);
|
||||
Map<String, ?> sessions = (Map<String, ?>) new DirectFieldAccessor(this.webSocketHandler).getPropertyValue("sessions");
|
||||
new DirectFieldAccessor(sessions.get("id1")).setPropertyValue("createTime", sixtyOneSecondsAgo);
|
||||
new DirectFieldAccessor(sessions.get("id2")).setPropertyValue("createTime", sixtyOneSecondsAgo);
|
||||
|
||||
this.webSocketHandler.handleMessage(session1, new TextMessage("foo"));
|
||||
|
||||
assertTrue(session1.isOpen());
|
||||
assertFalse(session2.isOpen());
|
||||
assertNull(session1.getCloseStatus());
|
||||
assertEquals(CloseStatus.PROTOCOL_ERROR, session2.getCloseStatus());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user