Search code examples
javasslwebsocketjettyserver-side

How to setup secure Websocket server using Jetty 11


I'm new in Jetty and want to create a small test Websocket server with SSL (using Jetty 11). Found many Jetty 9 based examples, but nothing for Jetty 11.

My test code looks as this:

public class Test {
    public Test(int port, SSLContext sslContext) {
        port_ = port;

        server_ = new Server(port_);

        SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
        sslContextFactory.setSslContext(sslContext);

        HttpConfiguration httpsConfig = new HttpConfiguration();
        httpsConfig.addCustomizer(new SecureRequestCustomizer());

        connector_ = new ServerConnector(server_,
            new SslConnectionFactory(sslContextFactory,  HttpVersion.HTTP_1_1.asString()),
            new HttpConnectionFactory(httpsConfig));
        server_.addConnector(connector_);

        var servlet = new JettyWebSocketServlet() {
            @Override
            protected void configure(JettyWebSocketServletFactory factory) {
                factory.addMapping("/", (req, res) -> new WebSocketHandler());
            }
        };
        var handler = new ServletContextHandler();
        handler.addServlet(new ServletHolder(servlet), "/");
        JettyWebSocketServletContainerInitializer.configure(handler, (context, configurator) ->
        {
        });

        server_.setHandler(handler);
    }

    public void start() {
        try {
            server_.start();
            System.out.println("Server started at port " + connector_.getLocalPort());

            server_.join();
        } catch(Exception ex) {

        }
    }

    private int port_;
    private Server server_;
    private ServerConnector connector_;
}

An SSL context passed to the constructor is initialized via the keystore and etc. But when I'm trying to connect to this server I receive "SSL handshake error" at the client side. My client works properly with the same certs & co if I use another Websocket server.

On running the server I see this in the log:

[main] INFO org.eclipse.jetty.server.Server - jetty-11.0.15; built: 2023-04-11T18:37:53.775Z; git: 5bc5e562c8d05c5862505aebe5cf83a61bdbcb96; jvm 17.0.1+12-LTS-39
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@7f3b84b8{/,null,AVAILABLE}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@5f3a4b84{HTTP/1.1, (http/1.1)}{0.0.0.0:12345}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@149494d8{SSL, (ssl, http/1.1)}{0.0.0.0:52376}
[main] INFO org.eclipse.jetty.server.Server - Started Server@5af97850{STARTING}[11.0.15,sto=0] @3110ms
Server started at port 52376

So it seems the Websocket servlet is running of the port 12345, but SSL is not enabled for it. From other side, HTTP connector has SSL. I suspect that I'm missing something important.

So my questions are:

  • How to enable SSL for Websocket proprly om Jetty 11?
  • How it is possible to prevent using random port for HTTP and use single listener port both for the HTTP and Websocket? (actually I need HTTP only to open the Websocket)

Thanks in advance!


Solution

  • You are configuring two connectors.

    The server_ = new Server(port_); is adding the one, and you see in your output as Started ServerConnector@5f3a4b84{HTTP/1.1, (http/1.1)}{0.0.0.0:12345}.

    And the other is configured with connector_ = new ServerConnector(... you see in your output as Started ServerConnector@149494d8{SSL, (ssl, http/1.1)}{0.0.0.0:52376}.

    So create the server without specifying a port like server_ = new Server();, then set the port on the connector you configured with connector_.setPort(port_).