Issue #5866 - add Programmatic WebSocket Upgrade to Jetty API
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
78707fffde
commit
0d48b8b991
|
@ -123,6 +123,11 @@ public class WebSocketMappings implements Dumpable, LifeCycle.Listener
|
||||||
this.components = components;
|
this.components = components;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Handshaker getHandshaker()
|
||||||
|
{
|
||||||
|
return handshaker;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void lifeCycleStopping(LifeCycle context)
|
public void lifeCycleStopping(LifeCycle context)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.websocket.server;
|
package org.eclipse.jetty.websocket.server;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -20,6 +21,8 @@ import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.pathmap.PathSpec;
|
import org.eclipse.jetty.http.pathmap.PathSpec;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
@ -32,9 +35,14 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
|
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
|
||||||
import org.eclipse.jetty.websocket.common.SessionTracker;
|
import org.eclipse.jetty.websocket.common.SessionTracker;
|
||||||
import org.eclipse.jetty.websocket.core.Configuration;
|
import org.eclipse.jetty.websocket.core.Configuration;
|
||||||
|
import org.eclipse.jetty.websocket.core.WebSocketComponents;
|
||||||
import org.eclipse.jetty.websocket.core.exception.WebSocketException;
|
import org.eclipse.jetty.websocket.core.exception.WebSocketException;
|
||||||
import org.eclipse.jetty.websocket.core.internal.util.ReflectUtils;
|
import org.eclipse.jetty.websocket.core.internal.util.ReflectUtils;
|
||||||
|
import org.eclipse.jetty.websocket.core.server.Handshaker;
|
||||||
|
import org.eclipse.jetty.websocket.core.server.WebSocketCreator;
|
||||||
import org.eclipse.jetty.websocket.core.server.WebSocketMappings;
|
import org.eclipse.jetty.websocket.core.server.WebSocketMappings;
|
||||||
|
import org.eclipse.jetty.websocket.core.server.WebSocketNegotiator;
|
||||||
|
import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents;
|
||||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||||
import org.eclipse.jetty.websocket.server.internal.DelegatedServerUpgradeRequest;
|
import org.eclipse.jetty.websocket.server.internal.DelegatedServerUpgradeRequest;
|
||||||
import org.eclipse.jetty.websocket.server.internal.DelegatedServerUpgradeResponse;
|
import org.eclipse.jetty.websocket.server.internal.DelegatedServerUpgradeResponse;
|
||||||
|
@ -68,7 +76,8 @@ public class JettyWebSocketServerContainer extends ContainerLifeCycle implements
|
||||||
|
|
||||||
// Create the Jetty ServerContainer implementation
|
// Create the Jetty ServerContainer implementation
|
||||||
WebSocketMappings mappings = WebSocketMappings.ensureMappings(servletContext);
|
WebSocketMappings mappings = WebSocketMappings.ensureMappings(servletContext);
|
||||||
container = new JettyWebSocketServerContainer(contextHandler, mappings, executor);
|
WebSocketComponents components = WebSocketServerComponents.getWebSocketComponents(servletContext);
|
||||||
|
container = new JettyWebSocketServerContainer(contextHandler, mappings, components, executor);
|
||||||
servletContext.setAttribute(JETTY_WEBSOCKET_CONTAINER_ATTRIBUTE, container);
|
servletContext.setAttribute(JETTY_WEBSOCKET_CONTAINER_ATTRIBUTE, container);
|
||||||
contextHandler.addManaged(container);
|
contextHandler.addManaged(container);
|
||||||
contextHandler.addEventListener(container);
|
contextHandler.addEventListener(container);
|
||||||
|
@ -81,6 +90,7 @@ public class JettyWebSocketServerContainer extends ContainerLifeCycle implements
|
||||||
|
|
||||||
private final ServletContextHandler contextHandler;
|
private final ServletContextHandler contextHandler;
|
||||||
private final WebSocketMappings webSocketMappings;
|
private final WebSocketMappings webSocketMappings;
|
||||||
|
private final WebSocketComponents components;
|
||||||
private final JettyServerFrameHandlerFactory frameHandlerFactory;
|
private final JettyServerFrameHandlerFactory frameHandlerFactory;
|
||||||
private final Executor executor;
|
private final Executor executor;
|
||||||
private final Configuration.ConfigurationCustomizer customizer = new Configuration.ConfigurationCustomizer();
|
private final Configuration.ConfigurationCustomizer customizer = new Configuration.ConfigurationCustomizer();
|
||||||
|
@ -94,10 +104,11 @@ public class JettyWebSocketServerContainer extends ContainerLifeCycle implements
|
||||||
* @param webSocketMappings the {@link WebSocketMappings} that this container belongs to
|
* @param webSocketMappings the {@link WebSocketMappings} that this container belongs to
|
||||||
* @param executor the {@link Executor} to use
|
* @param executor the {@link Executor} to use
|
||||||
*/
|
*/
|
||||||
JettyWebSocketServerContainer(ServletContextHandler contextHandler, WebSocketMappings webSocketMappings, Executor executor)
|
JettyWebSocketServerContainer(ServletContextHandler contextHandler, WebSocketMappings webSocketMappings, WebSocketComponents components, Executor executor)
|
||||||
{
|
{
|
||||||
this.contextHandler = contextHandler;
|
this.contextHandler = contextHandler;
|
||||||
this.webSocketMappings = webSocketMappings;
|
this.webSocketMappings = webSocketMappings;
|
||||||
|
this.components = components;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
this.frameHandlerFactory = new JettyServerFrameHandlerFactory(this);
|
this.frameHandlerFactory = new JettyServerFrameHandlerFactory(this);
|
||||||
addBean(frameHandlerFactory);
|
addBean(frameHandlerFactory);
|
||||||
|
@ -136,6 +147,23 @@ public class JettyWebSocketServerContainer extends ContainerLifeCycle implements
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An immediate programmatic WebSocket upgrade that does not register a mapping or create a {@link WebSocketUpgradeFilter}.
|
||||||
|
* @param creator the WebSocketCreator to use.
|
||||||
|
* @param request the HttpServletRequest.
|
||||||
|
* @param response the HttpServletResponse.
|
||||||
|
* @return true if the connection was successfully upgraded to WebSocket.
|
||||||
|
* @throws IOException if an I/O error occurs.
|
||||||
|
*/
|
||||||
|
public boolean upgrade(JettyWebSocketCreator creator, HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||||
|
{
|
||||||
|
WebSocketCreator coreCreator = (req, resp) -> creator.createWebSocket(new DelegatedServerUpgradeRequest(req), new DelegatedServerUpgradeResponse(resp));
|
||||||
|
WebSocketNegotiator negotiator = WebSocketNegotiator.from(coreCreator, frameHandlerFactory, customizer);
|
||||||
|
|
||||||
|
Handshaker handshaker = webSocketMappings.getHandshaker();
|
||||||
|
return handshaker.upgradeRequest(negotiator, request, response, components, null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Executor getExecutor()
|
public Executor getExecutor()
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,6 @@ import java.net.URI;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.servlet.ServletConfig;
|
import javax.servlet.ServletConfig;
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServlet;
|
import javax.servlet.http.HttpServlet;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -30,12 +29,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||||
import org.eclipse.jetty.websocket.core.WebSocketComponents;
|
import org.eclipse.jetty.websocket.server.JettyWebSocketCreator;
|
||||||
import org.eclipse.jetty.websocket.core.server.FrameHandlerFactory;
|
|
||||||
import org.eclipse.jetty.websocket.core.server.Handshaker;
|
|
||||||
import org.eclipse.jetty.websocket.core.server.WebSocketCreator;
|
|
||||||
import org.eclipse.jetty.websocket.core.server.WebSocketNegotiator;
|
|
||||||
import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents;
|
|
||||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer;
|
import org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer;
|
||||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -81,26 +75,20 @@ public class ProgrammaticWebSocketUpgradeTest
|
||||||
|
|
||||||
public static class CustomUpgradeServlet extends HttpServlet
|
public static class CustomUpgradeServlet extends HttpServlet
|
||||||
{
|
{
|
||||||
private final Handshaker handshaker = Handshaker.newInstance();
|
private JettyWebSocketServerContainer container;
|
||||||
private FrameHandlerFactory frameHandlerFactory;
|
|
||||||
private WebSocketComponents components;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServletConfig config) throws ServletException
|
public void init(ServletConfig config) throws ServletException
|
||||||
{
|
{
|
||||||
super.init(config);
|
super.init(config);
|
||||||
ServletContext servletContext = getServletContext();
|
container = JettyWebSocketServerContainer.getContainer(getServletContext());
|
||||||
JettyWebSocketServerContainer container = JettyWebSocketServerContainer.getContainer(servletContext);
|
|
||||||
components = WebSocketServerComponents.getWebSocketComponents(servletContext);
|
|
||||||
frameHandlerFactory = container.getBean(FrameHandlerFactory.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
{
|
{
|
||||||
WebSocketCreator creator = (req, resp) -> new EchoSocket();
|
JettyWebSocketCreator creator = (req, resp) -> new EchoSocket();
|
||||||
WebSocketNegotiator negotiator = WebSocketNegotiator.from(creator, frameHandlerFactory);
|
container.upgrade(creator, request, response);
|
||||||
handshaker.upgradeRequest(negotiator, request, response, components, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue