Add tests for the ordering of the default WebSocketUpgradeFilter.
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
f52e61156d
commit
aba2c93eae
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.tests;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -30,7 +31,10 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.servlet.DispatcherType;
|
import javax.servlet.DispatcherType;
|
||||||
import javax.servlet.FilterConfig;
|
import javax.servlet.FilterConfig;
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebListener;
|
||||||
import javax.servlet.http.HttpServlet;
|
import javax.servlet.http.HttpServlet;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
|
@ -38,15 +42,18 @@ import org.eclipse.jetty.server.ServerConnector;
|
||||||
import org.eclipse.jetty.servlet.FilterHolder;
|
import org.eclipse.jetty.servlet.FilterHolder;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||||
|
import org.eclipse.jetty.websocket.core.WebSocketConstants;
|
||||||
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.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter;
|
import org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
@ -64,6 +71,16 @@ public class JettyWebSocketFilterTest
|
||||||
private WebSocketClient client;
|
private WebSocketClient client;
|
||||||
private ServletContextHandler contextHandler;
|
private ServletContextHandler contextHandler;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before()
|
||||||
|
{
|
||||||
|
server = new Server();
|
||||||
|
connector = new ServerConnector(server);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
client = new WebSocketClient();
|
||||||
|
}
|
||||||
|
|
||||||
public void start(JettyWebSocketServletContainerInitializer.Configurator configurator) throws Exception
|
public void start(JettyWebSocketServletContainerInitializer.Configurator configurator) throws Exception
|
||||||
{
|
{
|
||||||
start(configurator, null);
|
start(configurator, null);
|
||||||
|
@ -76,20 +93,14 @@ public class JettyWebSocketFilterTest
|
||||||
|
|
||||||
public void start(JettyWebSocketServletContainerInitializer.Configurator configurator, ServletHolder servletHolder) throws Exception
|
public void start(JettyWebSocketServletContainerInitializer.Configurator configurator, ServletHolder servletHolder) throws Exception
|
||||||
{
|
{
|
||||||
server = new Server();
|
|
||||||
connector = new ServerConnector(server);
|
|
||||||
server.addConnector(connector);
|
|
||||||
|
|
||||||
contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||||
contextHandler.setContextPath("/");
|
contextHandler.setContextPath("/");
|
||||||
if (servletHolder != null)
|
if (servletHolder != null)
|
||||||
contextHandler.addServlet(servletHolder, "/");
|
contextHandler.addServlet(servletHolder, "/");
|
||||||
server.setHandler(contextHandler);
|
server.setHandler(contextHandler);
|
||||||
|
|
||||||
JettyWebSocketServletContainerInitializer.configure(contextHandler, configurator);
|
JettyWebSocketServletContainerInitializer.configure(contextHandler, configurator);
|
||||||
server.start();
|
|
||||||
|
|
||||||
client = new WebSocketClient();
|
server.start();
|
||||||
client.start();
|
client.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,6 +308,98 @@ public class JettyWebSocketFilterTest
|
||||||
assertThat(socket.textMessages.poll(), is("hElLo wOrLd"));
|
assertThat(socket.textMessages.poll(), is("hElLo wOrLd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultWebSocketUpgradeFilterOrdering() throws Exception
|
||||||
|
{
|
||||||
|
String timeoutFromAltFilter = "5999";
|
||||||
|
JettyWebSocketWebApp webApp = new JettyWebSocketWebApp("wsuf-ordering1");
|
||||||
|
Path webXml = MavenTestingUtils.getTestResourcePath("wsuf-ordering1.xml");
|
||||||
|
webApp.copyWebXml(webXml);
|
||||||
|
webApp.copyClass(WebSocketEchoServletContextListener.class);
|
||||||
|
webApp.copyClass(WebSocketEchoServletContextListener.EchoSocket.class);
|
||||||
|
|
||||||
|
server.setHandler(webApp);
|
||||||
|
server.start();
|
||||||
|
client.start();
|
||||||
|
|
||||||
|
// We have both websocket upgrade filters installed.
|
||||||
|
FilterHolder[] filterHolders = webApp.getServletHandler().getFilters();
|
||||||
|
assertThat(filterHolders.length, is(2));
|
||||||
|
assertThat(filterHolders[0].getFilter(), instanceOf(WebSocketUpgradeFilter.class));
|
||||||
|
assertThat(filterHolders[1].getFilter(), instanceOf(WebSocketUpgradeFilter.class));
|
||||||
|
|
||||||
|
// The custom filter defined in web.xml should be first in line so it will do the upgrade.
|
||||||
|
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + webApp.getContextPath() + "/echo");
|
||||||
|
EventSocket socket = new EventSocket();
|
||||||
|
CompletableFuture<Session> connect = client.connect(socket, uri);
|
||||||
|
try (Session session = connect.get(5, TimeUnit.SECONDS))
|
||||||
|
{
|
||||||
|
session.getRemote().sendString("hello world");
|
||||||
|
session.getRemote().sendString("getIdleTimeout");
|
||||||
|
}
|
||||||
|
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
|
||||||
|
assertThat(socket.textMessages.poll(), is("hello world"));
|
||||||
|
assertThat(socket.textMessages.poll(), is(timeoutFromAltFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWebSocketUpgradeFilterOrdering() throws Exception
|
||||||
|
{
|
||||||
|
String defaultIdleTimeout = Long.toString(WebSocketConstants.DEFAULT_IDLE_TIMEOUT.toMillis());
|
||||||
|
JettyWebSocketWebApp webApp = new JettyWebSocketWebApp("wsuf-ordering2");
|
||||||
|
Path webXml = MavenTestingUtils.getTestResourcePath("wsuf-ordering2.xml");
|
||||||
|
webApp.copyWebXml(webXml);
|
||||||
|
webApp.copyClass(WebSocketEchoServletContextListener.class);
|
||||||
|
webApp.copyClass(WebSocketEchoServletContextListener.EchoSocket.class);
|
||||||
|
|
||||||
|
server.setHandler(webApp);
|
||||||
|
server.start();
|
||||||
|
client.start();
|
||||||
|
|
||||||
|
// We have both websocket upgrade filters installed.
|
||||||
|
FilterHolder[] filterHolders = webApp.getServletHandler().getFilters();
|
||||||
|
assertThat(filterHolders.length, is(2));
|
||||||
|
assertThat(filterHolders[0].getFilter(), instanceOf(WebSocketUpgradeFilter.class));
|
||||||
|
assertThat(filterHolders[1].getFilter(), instanceOf(WebSocketUpgradeFilter.class));
|
||||||
|
|
||||||
|
// The custom filter defined in web.xml should be first in line so it will do the upgrade.
|
||||||
|
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + webApp.getContextPath() + "/echo");
|
||||||
|
EventSocket socket = new EventSocket();
|
||||||
|
CompletableFuture<Session> connect = client.connect(socket, uri);
|
||||||
|
try (Session session = connect.get(5, TimeUnit.SECONDS))
|
||||||
|
{
|
||||||
|
session.getRemote().sendString("hello world");
|
||||||
|
session.getRemote().sendString("getIdleTimeout");
|
||||||
|
}
|
||||||
|
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
|
||||||
|
assertThat(socket.textMessages.poll(), is("hello world"));
|
||||||
|
assertThat(socket.textMessages.poll(), is(defaultIdleTimeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
@WebListener
|
||||||
|
public static class WebSocketEchoServletContextListener implements ServletContextListener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce)
|
||||||
|
{
|
||||||
|
JettyWebSocketServerContainer container = JettyWebSocketServerContainer.getContainer(sce.getServletContext());
|
||||||
|
container.addMapping("/echo", EchoSocket.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WebSocket
|
||||||
|
public static class EchoSocket
|
||||||
|
{
|
||||||
|
@OnWebSocketMessage
|
||||||
|
public void onMessage(Session session, String message) throws IOException
|
||||||
|
{
|
||||||
|
if ("getIdleTimeout".equals(message))
|
||||||
|
session.getRemote().sendString(Long.toString(session.getIdleTimeout().toMillis()));
|
||||||
|
else
|
||||||
|
session.getRemote().sendString(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class MyUpgradeFilter extends WebSocketUpgradeFilter
|
public static class MyUpgradeFilter extends WebSocketUpgradeFilter
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
package org.eclipse.jetty.websocket.tests;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.toolchain.test.FS;
|
||||||
|
import org.eclipse.jetty.toolchain.test.IO;
|
||||||
|
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||||
|
import org.eclipse.jetty.util.TypeUtil;
|
||||||
|
import org.eclipse.jetty.util.resource.PathResource;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
import org.eclipse.jetty.websocket.server.config.JettyWebSocketConfiguration;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
|
||||||
|
public class JettyWebSocketWebApp extends WebAppContext
|
||||||
|
{
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(JettyWebSocketWebApp.class);
|
||||||
|
|
||||||
|
private final Path contextDir;
|
||||||
|
private final Path webInf;
|
||||||
|
private final Path classesDir;
|
||||||
|
|
||||||
|
public JettyWebSocketWebApp(String contextName)
|
||||||
|
{
|
||||||
|
// Ensure context directory.
|
||||||
|
Path testDir = MavenTestingUtils.getTargetTestingPath(JettyWebSocketWebApp.class.getName());
|
||||||
|
contextDir = testDir.resolve(contextName);
|
||||||
|
FS.ensureEmpty(contextDir);
|
||||||
|
|
||||||
|
// Ensure WEB-INF directories.
|
||||||
|
webInf = contextDir.resolve("WEB-INF");
|
||||||
|
FS.ensureDirExists(webInf);
|
||||||
|
classesDir = webInf.resolve("classes");
|
||||||
|
FS.ensureDirExists(classesDir);
|
||||||
|
|
||||||
|
// Configure the WebAppContext.
|
||||||
|
setContextPath("/" + contextName);
|
||||||
|
setBaseResource(new PathResource(contextDir));
|
||||||
|
addConfiguration(new JettyWebSocketConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getContextDir()
|
||||||
|
{
|
||||||
|
return contextDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createWebXml() throws IOException
|
||||||
|
{
|
||||||
|
String emptyWebXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||||
|
"<web-app xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://java.sun.com/xml/ns/javaee\" " +
|
||||||
|
"xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd\" " +
|
||||||
|
"metadata-complete=\"false\" version=\"3.0\"></web-app>";
|
||||||
|
|
||||||
|
Path webXml = webInf.resolve("web.xml");
|
||||||
|
try (FileWriter writer = new FileWriter(webXml.toFile()))
|
||||||
|
{
|
||||||
|
writer.write(emptyWebXml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyWebXml(Path webXml) throws IOException
|
||||||
|
{
|
||||||
|
IO.copy(webXml.toFile(), webInf.resolve("web.xml").toFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyClass(Class<?> clazz) throws Exception
|
||||||
|
{
|
||||||
|
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||||
|
String endpointPath = TypeUtil.toClassReference(clazz);
|
||||||
|
URL classUrl = cl.getResource(endpointPath);
|
||||||
|
assertThat("Class URL for: " + clazz, classUrl, notNullValue());
|
||||||
|
Path destFile = classesDir.resolve(endpointPath);
|
||||||
|
FS.ensureDirExists(destFile.getParent());
|
||||||
|
File srcFile = new File(classUrl.toURI());
|
||||||
|
IO.copy(srcFile, destFile.toFile());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app
|
||||||
|
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||||
|
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||||
|
version="3.1">
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<filter-name>wsuf-alt</filter-name>
|
||||||
|
<filter-class>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>idleTimeout</param-name>
|
||||||
|
<param-value>5999</param-value>
|
||||||
|
</init-param>
|
||||||
|
</filter>
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>wsuf-alt</filter-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app
|
||||||
|
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||||
|
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||||
|
version="3.1">
|
||||||
|
|
||||||
|
<!-- Make sure the default filter is first. -->
|
||||||
|
<filter>
|
||||||
|
<filter-name>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-name>
|
||||||
|
<filter-class>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-class>
|
||||||
|
</filter>
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
|
||||||
|
<!-- The custom filter is then tried after. -->
|
||||||
|
<filter>
|
||||||
|
<filter-name>wsuf-alt</filter-name>
|
||||||
|
<filter-class>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>idleTimeout</param-name>
|
||||||
|
<param-value>5999</param-value>
|
||||||
|
</init-param>
|
||||||
|
</filter>
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>wsuf-alt</filter-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
</web-app>
|
Loading…
Reference in New Issue