Merge pull request #5115 from eclipse/jetty-10.0.x-5096-lazyUpgradeFilter

Issue #5096 - lazily initialize the WebSocketFilter if only using JettyWebSocketServlet
This commit is contained in:
Lachlan 2020-08-05 09:37:42 +10:00 committed by GitHub
commit 11db6f9d71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 8 deletions

View File

@ -43,6 +43,7 @@ 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.JettyServerFrameHandlerFactory; import org.eclipse.jetty.websocket.server.internal.JettyServerFrameHandlerFactory;
import org.eclipse.jetty.websocket.util.ReflectUtils; import org.eclipse.jetty.websocket.util.ReflectUtils;
import org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter;
import org.eclipse.jetty.websocket.util.server.internal.FrameHandlerFactory; import org.eclipse.jetty.websocket.util.server.internal.FrameHandlerFactory;
import org.eclipse.jetty.websocket.util.server.internal.WebSocketMapping; import org.eclipse.jetty.websocket.util.server.internal.WebSocketMapping;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -86,6 +87,7 @@ public class JettyWebSocketServerContainer extends ContainerLifeCycle implements
private static final Logger LOG = LoggerFactory.getLogger(JettyWebSocketServerContainer.class); private static final Logger LOG = LoggerFactory.getLogger(JettyWebSocketServerContainer.class);
private final ServletContextHandler contextHandler;
private final WebSocketMapping webSocketMapping; private final WebSocketMapping webSocketMapping;
private final WebSocketComponents webSocketComponents; private final WebSocketComponents webSocketComponents;
private final FrameHandlerFactory frameHandlerFactory; private final FrameHandlerFactory frameHandlerFactory;
@ -104,6 +106,7 @@ public class JettyWebSocketServerContainer extends ContainerLifeCycle implements
*/ */
JettyWebSocketServerContainer(ServletContextHandler contextHandler, WebSocketMapping webSocketMapping, WebSocketComponents webSocketComponents, Executor executor) JettyWebSocketServerContainer(ServletContextHandler contextHandler, WebSocketMapping webSocketMapping, WebSocketComponents webSocketComponents, Executor executor)
{ {
this.contextHandler = contextHandler;
this.webSocketMapping = webSocketMapping; this.webSocketMapping = webSocketMapping;
this.webSocketComponents = webSocketComponents; this.webSocketComponents = webSocketComponents;
this.executor = executor; this.executor = executor;
@ -128,6 +131,7 @@ public class JettyWebSocketServerContainer extends ContainerLifeCycle implements
if (webSocketMapping.getMapping(ps) != null) if (webSocketMapping.getMapping(ps) != null)
throw new WebSocketException("Duplicate WebSocket Mapping for PathSpec"); throw new WebSocketException("Duplicate WebSocket Mapping for PathSpec");
WebSocketUpgradeFilter.ensureFilter(contextHandler.getServletContext());
webSocketMapping.addMapping(ps, webSocketMapping.addMapping(ps,
(req, resp) -> creator.createWebSocket(new JettyServerUpgradeRequest(req), new JettyServerUpgradeResponse(resp)), (req, resp) -> creator.createWebSocket(new JettyServerUpgradeRequest(req), new JettyServerUpgradeResponse(resp)),
frameHandlerFactory, customizer); frameHandlerFactory, customizer);

View File

@ -22,13 +22,11 @@ import java.util.Set;
import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.listener.ContainerInitializer; import org.eclipse.jetty.servlet.listener.ContainerInitializer;
import org.eclipse.jetty.websocket.core.WebSocketComponents; import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents; 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.util.server.WebSocketUpgradeFilter;
import org.eclipse.jetty.websocket.util.server.internal.WebSocketMapping; import org.eclipse.jetty.websocket.util.server.internal.WebSocketMapping;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -91,12 +89,11 @@ public class JettyWebSocketServletContainerInitializer implements ServletContain
private static JettyWebSocketServerContainer initialize(ServletContextHandler context) private static JettyWebSocketServerContainer initialize(ServletContextHandler context)
{ {
WebSocketComponents components = WebSocketServerComponents.ensureWebSocketComponents(context.getServletContext()); WebSocketComponents components = WebSocketServerComponents.ensureWebSocketComponents(context.getServletContext());
FilterHolder filterHolder = WebSocketUpgradeFilter.ensureFilter(context.getServletContext());
WebSocketMapping mapping = WebSocketMapping.ensureMapping(context.getServletContext(), WebSocketMapping.DEFAULT_KEY); WebSocketMapping mapping = WebSocketMapping.ensureMapping(context.getServletContext(), WebSocketMapping.DEFAULT_KEY);
JettyWebSocketServerContainer container = JettyWebSocketServerContainer.ensureContainer(context.getServletContext()); JettyWebSocketServerContainer container = JettyWebSocketServerContainer.ensureContainer(context.getServletContext());
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("configureContext {} {} {} {}", container, mapping, filterHolder, components); LOG.debug("configureContext {} {} {}", container, mapping, components);
return container; return container;
} }

View File

@ -27,6 +27,7 @@ import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
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.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;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -34,6 +35,7 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
public class JettyWebSocketFilterTest public class JettyWebSocketFilterTest
@ -41,6 +43,7 @@ public class JettyWebSocketFilterTest
private Server server; private Server server;
private ServerConnector connector; private ServerConnector connector;
private WebSocketClient client; private WebSocketClient client;
private ServletContextHandler contextHandler;
@BeforeEach @BeforeEach
public void start() throws Exception public void start() throws Exception
@ -49,12 +52,11 @@ public class JettyWebSocketFilterTest
connector = new ServerConnector(server); connector = new ServerConnector(server);
server.addConnector(connector); server.addConnector(connector);
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setContextPath("/"); contextHandler.setContextPath("/");
server.setHandler(contextHandler); server.setHandler(contextHandler);
JettyWebSocketServletContainerInitializer.configure(contextHandler, (context, container) -> JettyWebSocketServletContainerInitializer.configure(contextHandler, null);
container.addMapping("/", (req, resp) -> new EchoSocket()));
server.start(); server.start();
client = new WebSocketClient(); client = new WebSocketClient();
@ -69,8 +71,20 @@ public class JettyWebSocketFilterTest
} }
@Test @Test
public void test() throws Exception public void testLazyWebSocketUpgradeFilter() throws Exception
{ {
// JettyWebSocketServerContainer has already been created.
JettyWebSocketServerContainer container = JettyWebSocketServerContainer.getContainer(contextHandler.getServletContext());
assertNotNull(container);
// We should have no WebSocketUpgradeFilter installed because we have added no mappings.
assertThat(contextHandler.getServletHandler().getFilters().length, is(0));
// After mapping is added we have an UpgradeFilter.
container.addMapping("/", EchoSocket.class);
assertThat(contextHandler.getServletHandler().getFilters().length, is(1));
// Test we can upgrade to websocket and send a message.
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/filterPath"); URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/filterPath");
EventSocket socket = new EventSocket(); EventSocket socket = new EventSocket();
CompletableFuture<Session> connect = client.connect(socket, uri); CompletableFuture<Session> connect = client.connect(socket, uri);