@Before public void setup() { this.protocolHandler = new StompSubProtocolHandler(); this.channel = Mockito.mock(MessageChannel.class); this.messageCaptor = ArgumentCaptor.forClass(Message.class); when(this.channel.send(any())).thenReturn(true); this.session = new TestWebSocketSession(); this.session.setId("s1"); this.session.setPrincipal(new TestPrincipal("joe")); }
@Test public void getSubProtocols() throws Exception { SubscribableChannel channel = mock(SubscribableChannel.class); SubProtocolWebSocketHandler handler = new SubProtocolWebSocketHandler(channel, channel); StompSubProtocolHandler stompHandler = new StompSubProtocolHandler(); handler.addProtocolHandler(stompHandler); TaskScheduler scheduler = mock(TaskScheduler.class); DefaultSockJsService service = new DefaultSockJsService(scheduler); WebSocketServerSockJsSession session = new WebSocketServerSockJsSession("1", service, handler, null); SockJsWebSocketHandler sockJsHandler = new SockJsWebSocketHandler(service, handler, session); assertEquals(stompHandler.getSupportedProtocols(), sockJsHandler.getSubProtocols()); }
StompHeaderAccessor accessor = getStompHeaderAccessor(message); StompCommand command = accessor.getCommand(); accessor = toMutableAccessor(accessor, message); accessor.removeNativeHeader(SimpMessageHeaderAccessor.ORIGINAL_DESTINATION); accessor.setDestination(origDestination); accessor = afterStompSessionConnected(message, accessor, session); if (this.eventPublisher != null) { try { SimpAttributes simpAttributes = new SimpAttributes(session.getId(), session.getAttributes()); SimpAttributesContextHolder.setAttributes(simpAttributes); Principal user = getUser(session); publishEvent(this.eventPublisher, new SessionConnectedEvent(this, (Message<byte[]>) message, user)); if (StompCommand.ERROR.equals(command) && getErrorHandler() != null) { Message<byte[]> errorMessage = getErrorHandler().handleErrorMessageToClient((Message<byte[]>) message); if (errorMessage != null) { accessor = MessageHeaderAccessor.getAccessor(errorMessage, StompHeaderAccessor.class); sendToClient(session, accessor, payload);
private void handleError(WebSocketSession session, Throwable ex, @Nullable Message<byte[]> clientMessage) { if (getErrorHandler() == null) { sendErrorMessage(session, ex); return; } Message<byte[]> message = getErrorHandler().handleClientMessageProcessingError(clientMessage, ex); if (message == null) { return; } StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); Assert.state(accessor != null, "No StompHeaderAccessor"); sendToClient(session, accessor, message.getPayload()); }
@Override public void afterSessionEnded(WebSocketSession session, CloseStatus closeStatus, MessageChannel outputChannel) { this.decoders.remove(session.getId()); Message<byte[]> message = createDisconnectMessage(session); SimpAttributes simpAttributes = SimpAttributes.fromMessage(message); try { SimpAttributesContextHolder.setAttributes(simpAttributes); if (this.eventPublisher != null) { Principal user = getUser(session); publishEvent(this.eventPublisher, new SessionDisconnectEvent(this, message, session.getId(), closeStatus, user)); } outputChannel.send(message); } finally { this.stompAuthentications.remove(session.getId()); SimpAttributesContextHolder.resetAttributes(); simpAttributes.sessionCompleted(); } }
" in session " + session.getId() + ". Sending STOMP ERROR to client.", ex); handleError(session, ex, null); return; headerAccessor.setUser(getUser(session)); headerAccessor.setHeader(SimpMessageHeaderAccessor.HEART_BEAT_HEADER, headerAccessor.getHeartbeat()); if (!detectImmutableMessageInterceptor(outputChannel)) { headerAccessor.setImmutable(); Principal user = getUser(session); if (isConnect) { publishEvent(this.eventPublisher, new SessionConnectEvent(this, message, user)); publishEvent(this.eventPublisher, new SessionSubscribeEvent(this, message, user)); publishEvent(this.eventPublisher, new SessionUnsubscribeEvent(this, message, user)); " in session " + session.getId() + ". Sending STOMP ERROR to client.", ex); handleError(session, ex, message);
public WebMvcStompEndpointRegistry(WebSocketHandler webSocketHandler, WebSocketTransportRegistration transportRegistration, TaskScheduler defaultSockJsTaskScheduler) { Assert.notNull(webSocketHandler, "WebSocketHandler is required "); Assert.notNull(transportRegistration, "WebSocketTransportRegistration is required"); this.webSocketHandler = webSocketHandler; this.subProtocolWebSocketHandler = unwrapSubProtocolWebSocketHandler(webSocketHandler); if (transportRegistration.getSendTimeLimit() != null) { this.subProtocolWebSocketHandler.setSendTimeLimit(transportRegistration.getSendTimeLimit()); } if (transportRegistration.getSendBufferSizeLimit() != null) { this.subProtocolWebSocketHandler.setSendBufferSizeLimit(transportRegistration.getSendBufferSizeLimit()); } if (transportRegistration.getTimeToFirstMessage() != null) { this.subProtocolWebSocketHandler.setTimeToFirstMessage(transportRegistration.getTimeToFirstMessage()); } this.stompHandler = new StompSubProtocolHandler(); if (transportRegistration.getMessageSizeLimit() != null) { this.stompHandler.setMessageSizeLimit(transportRegistration.getMessageSizeLimit()); } this.sockJsScheduler = defaultSockJsTaskScheduler; }
@Test public void handleMessageFromClientWithoutImmutableMessageInterceptor() { AtomicReference<Boolean> mutable = new AtomicReference<>(); ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(); channel.addInterceptor(new ChannelInterceptor() { @Override public Message<?> preSend(Message<?> message, MessageChannel channel) { mutable.set(MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class).isMutable()); return message; } }); StompSubProtocolHandler handler = new StompSubProtocolHandler(); handler.afterSessionStarted(this.session, channel); TextMessage message = StompTextMessageBuilder.create(StompCommand.CONNECT).build(); handler.handleMessageFromClient(this.session, message, channel); assertNotNull(mutable.get()); assertFalse(mutable.get()); }
@Test public void eventPublicationWithExceptions() { ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class); this.protocolHandler.setApplicationEventPublisher(publisher); this.protocolHandler.afterSessionStarted(this.session, this.channel); StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.CONNECT); Message<byte[]> message = MessageBuilder.createMessage(EMPTY_PAYLOAD, headers.getMessageHeaders()); TextMessage textMessage = new TextMessage(new StompEncoder().encode(message)); this.protocolHandler.handleMessageFromClient(this.session, textMessage, this.channel); verify(this.channel).send(this.messageCaptor.capture()); Message<?> actual = this.messageCaptor.getValue(); assertNotNull(actual); assertEquals(StompCommand.CONNECT, StompHeaderAccessor.wrap(actual).getCommand()); reset(this.channel); headers = StompHeaderAccessor.create(StompCommand.CONNECTED); message = MessageBuilder.createMessage(EMPTY_PAYLOAD, headers.getMessageHeaders()); this.protocolHandler.handleMessageToClient(this.session, message); assertEquals(1, this.session.getSentMessages().size()); textMessage = (TextMessage) this.session.getSentMessages().get(0); assertEquals("CONNECTED\n" + "user-name:joe\n" + "\n" + "\u0000", textMessage.getPayload()); this.protocolHandler.afterSessionEnded(this.session, CloseStatus.BAD_DATA, this.channel); verify(this.channel).send(this.messageCaptor.capture()); actual = this.messageCaptor.getValue(); assertNotNull(actual); StompHeaderAccessor accessor = StompHeaderAccessor.wrap(actual); assertEquals(StompCommand.DISCONNECT, accessor.getCommand()); assertEquals("s1", accessor.getSessionId()); assertEquals("joe", accessor.getUser().getName()); }
SimpMessageType messageType = SimpMessageHeaderAccessor.getMessageType(message.getHeaders()); if (SimpMessageType.CONNECT_ACK.equals(messageType)) { stompAccessor = convertConnectAcktoStompConnected(stompAccessor); String receipt = getDisconnectReceipt(stompAccessor); if (receipt != null) { stompAccessor = StompHeaderAccessor.create(StompCommand.RECEIPT);
StompSubProtocolHandler stompHandler = (StompSubProtocolHandler) handlerMap.get("v12.stomp"); assertNotNull(stompHandler); assertEquals(128 * 1024, stompHandler.getMessageSizeLimit()); assertNotNull(stompHandler.getErrorHandler()); assertEquals(TestStompErrorHandler.class, stompHandler.getErrorHandler().getClass());
@Override public String toString() { return "StompSubProtocolHandler" + getSupportedProtocols(); }
@Override public void afterSessionStarted(WebSocketSession session, MessageChannel outputChannel) { if (session.getTextMessageSizeLimit() < MINIMUM_WEBSOCKET_MESSAGE_SIZE) { session.setTextMessageSizeLimit(MINIMUM_WEBSOCKET_MESSAGE_SIZE); } this.decoders.put(session.getId(), new BufferingStompDecoder(this.stompDecoder, getMessageSizeLimit())); }
protected void setApplicationContext(ApplicationContext applicationContext) { this.stompHandler.setApplicationEventPublisher(applicationContext); }
@Bean public SubProtocolHandler stompSubProtocolHandler() { StompSubProtocolHandler stompSubProtocolHandler = new StompSubProtocolHandler(); stompSubProtocolHandler.setEncoder(new ClientStompEncoder()); return stompSubProtocolHandler; }
@Test public void errorHandler() throws Exception { StompSubProtocolErrorHandler errorHandler = mock(StompSubProtocolErrorHandler.class); this.endpointRegistry.setErrorHandler(errorHandler); this.endpointRegistry.addEndpoint("/stompOverWebSocket"); Map<String, SubProtocolHandler> protocolHandlers = this.webSocketHandler.getProtocolHandlerMap(); StompSubProtocolHandler stompHandler = (StompSubProtocolHandler) protocolHandlers.get("v12.stomp"); assertSame(errorHandler, stompHandler.getErrorHandler()); }
" in session " + session.getId() + ". Sending STOMP ERROR to client.", ex); handleError(session, ex, null); return; headerAccessor.setUser(getUser(session)); headerAccessor.setHeader(SimpMessageHeaderAccessor.HEART_BEAT_HEADER, headerAccessor.getHeartbeat()); if (!detectImmutableMessageInterceptor(outputChannel)) { headerAccessor.setImmutable(); Principal user = getUser(session); if (isConnect) { publishEvent(this.eventPublisher, new SessionConnectEvent(this, message, user)); publishEvent(this.eventPublisher, new SessionSubscribeEvent(this, message, user)); publishEvent(this.eventPublisher, new SessionUnsubscribeEvent(this, message, user)); " in session " + session.getId() + ". Sending STOMP ERROR to client.", ex); handleError(session, ex, message);
private void handleError(WebSocketSession session, Throwable ex, @Nullable Message<byte[]> clientMessage) { if (getErrorHandler() == null) { sendErrorMessage(session, ex); return; } Message<byte[]> message = getErrorHandler().handleClientMessageProcessingError(clientMessage, ex); if (message == null) { return; } StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); Assert.state(accessor != null, "No StompHeaderAccessor"); sendToClient(session, accessor, message.getPayload()); }
@Override public void afterSessionEnded(WebSocketSession session, CloseStatus closeStatus, MessageChannel outputChannel) { this.decoders.remove(session.getId()); Message<byte[]> message = createDisconnectMessage(session); SimpAttributes simpAttributes = SimpAttributes.fromMessage(message); try { SimpAttributesContextHolder.setAttributes(simpAttributes); if (this.eventPublisher != null) { Principal user = getUser(session); publishEvent(this.eventPublisher, new SessionDisconnectEvent(this, message, session.getId(), closeStatus, user)); } outputChannel.send(message); } finally { this.stompAuthentications.remove(session.getId()); SimpAttributesContextHolder.resetAttributes(); simpAttributes.sessionCompleted(); } }
public WebMvcStompEndpointRegistry(WebSocketHandler webSocketHandler, WebSocketTransportRegistration transportRegistration, TaskScheduler defaultSockJsTaskScheduler) { Assert.notNull(webSocketHandler, "WebSocketHandler is required "); Assert.notNull(transportRegistration, "WebSocketTransportRegistration is required"); this.webSocketHandler = webSocketHandler; this.subProtocolWebSocketHandler = unwrapSubProtocolWebSocketHandler(webSocketHandler); if (transportRegistration.getSendTimeLimit() != null) { this.subProtocolWebSocketHandler.setSendTimeLimit(transportRegistration.getSendTimeLimit()); } if (transportRegistration.getSendBufferSizeLimit() != null) { this.subProtocolWebSocketHandler.setSendBufferSizeLimit(transportRegistration.getSendBufferSizeLimit()); } this.stompHandler = new StompSubProtocolHandler(); if (transportRegistration.getMessageSizeLimit() != null) { this.stompHandler.setMessageSizeLimit(transportRegistration.getMessageSizeLimit()); } this.sockJsScheduler = defaultSockJsTaskScheduler; }