manash
manash

Reputation: 7106

Custom Jetty WebSocketPolicy with Spring Web Sockets and STOMP

I would like to customize the Jetty WebSocketPolicy when using Spring Web Sockets with STOMP.

Here is my config class:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
        registration.setMessageSizeLimit(128 * 1024);
    }

}

When setting the message size limit via the WebSocketTransportRegistration, it doesn't solve the problem since there is a text message size check made by Jetty before Spring is involved. You can see it via the following stack trace:

org.eclipse.jetty.websocket.api.MessageTooLargeException: Text message size [70412] exceeds maximum size [65536]
    at org.eclipse.jetty.websocket.api.WebSocketPolicy.assertValidTextMessageSize(WebSocketPolicy.java:140) ~[websocket-api-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.websocket.common.Parser.assertSanePayloadLength(Parser.java:127) ~[websocket-common-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.websocket.common.Parser.parseFrame(Parser.java:485) ~[websocket-common-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.websocket.common.Parser.parse(Parser.java:241) ~[websocket-common-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.readParse(AbstractWebSocketConnection.java:560) [websocket-common-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillable(AbstractWebSocketConnection.java:391) [websocket-common-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281) [jetty-io-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102) [jetty-io-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118) [jetty-io-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333) [jetty-util-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310) [jetty-util-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168) [jetty-util-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126) [jetty-util-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366) [jetty-util-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:762) [jetty-util-9.4.11.v20180605.jar:9.4.11.v20180605]
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:680) [jetty-util-9.4.11.v20180605.jar:9.4.11.v20180605]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]

Therefore, I'm looking for a way to provide a custom WebSocketPolicy and pass it when the JettyRequestUpgradeStrategy is created but I can't find a way to do it.

It looks possible when the following configuration class is used but then it misses message broker configuration:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

}

Upvotes: 1

Views: 1368

Answers (2)

rento
rento

Reputation: 132

In newer versions of Spring, the constructor in JettyRequestUpgradeStrategy with the policy as argument has been removed. So I made a small adjustment to the solution of @manash.

That is how it works now:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/ws").setHandshakeHandler(handshakeHandler());
    registry.addEndpoint("/ws").setHandshakeHandler(handshakeHandler()).withSockJS();
  }

  // This has changed
  @Bean
  public DefaultHandshakeHandler handshakeHandler() {
    var updateStrategy = new JettyRequestUpgradeStrategy();
    updateStrategy.addWebSocketConfigurer(config -> {
       config.setMaxTextMessageSize(128 * 1024);
    });

    return new DefaultHandshakeHandler(updateStrategy);
}

For reference:

Upvotes: 0

manash
manash

Reputation: 7106

The solution is simple but not documented...

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/ws").setHandshakeHandler(handshakeHandler());
    registry.addEndpoint("/ws").setHandshakeHandler(handshakeHandler()).withSockJS();
  }

  @Bean
  public DefaultHandshakeHandler handshakeHandler() {
    WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
    policy.setMaxTextMessageSize(128 * 1024);

    return new DefaultHandshakeHandler(new JettyRequestUpgradeStrategy(policy));
  }
}

Upvotes: 1

Related Questions