Spring Boot WebSocket - добавление тела в ответ CONNECT - PullRequest
0 голосов
/ 26 декабря 2018

У меня есть следующие функции JS, которые подключаются к WebSocket через STOMP и обрабатывают события onConnected соответственно.

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');
}

Теперь первая строка функции onConnected, этозаписывает следующее в консоль, что, по-видимому, похоже на то, к чему я мог бы добавить дополнительные данные со стороны сервера.

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

У меня также есть HttpHandshakeInterceptor, который реализует HandshakeInterceptor следующим образом.

@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;
}

Строка с комментарием, начинающимся с ***, - это то, что я делаю сейчас безуспешно.Что я делаю неправильно?Могу ли я даже сделать это и получить некоторые параметры для клиента?Если я делаю это неправильно, как и где это сделать правильно?(потому что теперь я начинаю чувствовать, что пытаюсь сделать это не в том месте)

1 Ответ

0 голосов
/ 14 января 2019

Хорошо.Итак, вот что я пытался сделать, безуспешно .

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;
    }
}

Что это в основном делает, перехватывает исходящие сообщения на сервере и, если сообщение CONNECTED, он добавит некоторый пользовательский заголовок (да, я первоначально пытался добавить тело, но в целях тестирования я пока придерживался заголовка).

Однако этот метод может перехватывать многие команды STOMP, кромеCONNECTED.Я не пытался перехватить других, но, вероятно, это должно быть.

Затем я снова сослался на Спецификацию протокола STOMP (спасибо @TimBish за его комментарий выше) и прочитал это утверждение оттам.

Только кадры SEND, MESSAGE и ERROR МОГУТ иметь тело.Все остальные кадры НЕ ДОЛЖНЫ иметь тело.

Итак, похоже, что мы не можем перехватить сообщения, за исключением SEND, MESSAGE & ERROR.Я предполагаю, что это из-за соблюдения спецификации протокола реализации Spring STOMP.

Почему я попытался сделать это, чтобы поделиться общим секретом между каждым подключенным клиентом и сервером, где секрет определяется сервером,Все еще ищу такую ​​реализацию.

...