简体   繁体   中英

Spring Boot WebSocket - Adding body to the CONNECT response

I have the following JS functions, which are connecting to a WebSocket over STOMP, and handling the onConnected events, respectively.

function connect(event) {
    username = document.querySelector('#name').value.trim();

    if(username) {
        usernamePage.classList.add('hidden');
        chatPage.classList.remove('hidden');

        var socket = new SockJS('/ws');
        stompClient = Stomp.over(socket);

        stompClient.connect({}, onConnected, onError);
    }
    event.preventDefault();
}


function onConnected(response) {
    console.log(response);
    // Subscribe to the Public Topic
    stompClient.subscribe('/topic/public', onMessageReceived);

    // Tell your username to the server
    stompClient.send("/app/chat.addUser",
        {},
        JSON.stringify({sender: username, type: 'JOIN'})
    )

    connectingElement.classList.add('hidden');
}

Now the first line of the function onConnected , it logs the following into the console, which apparently looks like something I could add more data into, from the server side.

{
    command: "CONNECTED",
    headers: { 
        "heart-beat": "0,0",
        version: "1.1"
    },
    body: ""
}

I also have an HttpHandshakeInterceptor which implements HandshakeInterceptor as follows.

@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
        Map attributes) throws Exception {
    if (request instanceof ServletServerHttpRequest) {
        ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
        HttpSession session = servletRequest.getServletRequest().getSession();
        attributes.put("sessionId", session.getId());

        ServletServerHttpResponse servletResponse = (ServletServerHttpResponse) response;
        response.getHeaders().set("KEY","VALUE"); // *** I want this either to be in the response header or the body.
    }
    return true;
}

The line that has a comment starting with *** is what I am doing right now with no success. What am I doing wrong? Can I even do this and get some parameters there to the client? If I am doing it wrong, how and where to do it right? (because now I am starting to feel like I am trying to do this in the wrong place)

Okay. So the following is what I have tried to do, with no success .

public class OutboundMessageInterceptor implements ChannelInterceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(OutboundMessageInterceptor.class);

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        final StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
        final StompCommand command = headerAccessor.getCommand();

        LOGGER.info("Outbound channel preSend (" + command + ")...");

        if (command != null) {

            switch (command) {

                case CONNECTED:
                    final StompHeaderAccessor accessor = StompHeaderAccessor.create(headerAccessor.getCommand());
                    accessor.setSessionId(headerAccessor.getSessionId());
                    @SuppressWarnings("unchecked")
                    final MultiValueMap<String, String> nativeHeaders = (MultiValueMap<String, String>) headerAccessor.getHeader(StompHeaderAccessor.NATIVE_HEADERS);
                    accessor.addNativeHeaders(nativeHeaders);

                    // add custom headers
                    accessor.addNativeHeader("CUSTOM01", "CUSTOM01");

                    return MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders());
                default:
                    break;
            }
        }

        return message;
    }
}

What this basically does is, intercepting the outbound messages in the server and, if the message is CONNECTED , it will add some custom header (yes I was trying to add body originally, but for testing purposes I stuck to the header for the time being).

However this method can intercept many STOMP commands, except CONNECTED . I didn't try to intercept others but there probably should be.

Then I again referred to the STOMP Protocol Spec (thanks to @TimBish for his comment above) and read this statement from there.

Only the SEND, MESSAGE, and ERROR frames MAY have a body. All other frames MUST NOT have a body.

So, it seems like we cannot intercept the messages except for SEND , MESSAGE & ERROR . I presume it is because of the adherence to the protocol spec of Spring's STOMP implementation.

Why I tried doing this was to share some common secret between each client connected and the server, where the secret is determined by the server. Still looking for such implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM