Support registering Filters in WebSocket test servers

This commit is contained in:
Rossen Stoyanchev
2014-06-19 11:11:41 -04:00
parent c14ba1a0ff
commit dc1d85d045
6 changed files with 86 additions and 25 deletions

View File

@@ -17,12 +17,17 @@
package org.springframework.web.socket;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.springframework.util.SocketUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.EnumSet;
/**
* Jetty based {@link WebSocketTestServer}.
*
@@ -46,13 +51,20 @@ public class JettyWebSocketTestServer implements WebSocketTestServer {
}
@Override
public void deployConfig(WebApplicationContext cxt) {
public void deployConfig(WebApplicationContext cxt, Filter... filters) {
ServletContextHandler contextHandler = new ServletContextHandler();
ServletHolder servletHolder = new ServletHolder(new DispatcherServlet(cxt));
contextHandler.addServlet(servletHolder, "/");
for (Filter filter : filters) {
contextHandler.addFilter(new FilterHolder(filter), "/*", getDispatcherTypes());
}
this.jettyServer.setHandler(contextHandler);
}
private EnumSet<DispatcherType> getDispatcherTypes() {
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC);
}
@Override
public void undeployConfig() {
// Stopping jetty will undeploy the servlet

View File

@@ -18,17 +18,23 @@ package org.springframework.web.socket;
import java.io.File;
import java.io.IOException;
import java.util.EnumSet;
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.http11.Http11NioProtocol;
import org.apache.tomcat.util.descriptor.web.ApplicationListener;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.websocket.server.WsContextListener;
import org.springframework.util.SocketUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
/**
* Tomcat based {@link WebSocketTestServer}.
*
@@ -82,11 +88,27 @@ public class TomcatWebSocketTestServer implements WebSocketTestServer {
}
@Override
public void deployConfig(WebApplicationContext wac) {
public void deployConfig(WebApplicationContext wac, Filter... filters) {
this.context = this.tomcatServer.addContext("", System.getProperty("java.io.tmpdir"));
this.context.addApplicationListener(WS_APPLICATION_LISTENER);
Tomcat.addServlet(context, "dispatcherServlet", new DispatcherServlet(wac));
Tomcat.addServlet(this.context, "dispatcherServlet", new DispatcherServlet(wac)).setAsyncSupported(true);
this.context.addServletMapping("/", "dispatcherServlet");
for (Filter filter : filters) {
FilterDef filterDef = new FilterDef();
filterDef.setFilterName(filter.getClass().getName());
filterDef.setFilter(filter);
filterDef.setAsyncSupported("true");
this.context.addFilterDef(filterDef);
FilterMap filterMap = new FilterMap();
filterMap.setFilterName(filter.getClass().getName());
filterMap.addURLPattern("/*");
filterMap.setDispatcher("REQUEST,FORWARD,INCLUDE,ASYNC");
this.context.addFilterMap(filterMap);
}
}
private EnumSet<DispatcherType> getDispatcherTypes() {
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC);
}
@Override

View File

@@ -16,12 +16,15 @@
package org.springframework.web.socket;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import io.undertow.Undertow;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.FilterInfo;
import io.undertow.servlet.api.InstanceFactory;
import io.undertow.servlet.api.InstanceHandle;
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
@@ -56,7 +59,7 @@ public class UndertowTestServer implements WebSocketTestServer {
}
@Override
public void deployConfig(WebApplicationContext cxt) {
public void deployConfig(WebApplicationContext cxt, Filter... filters) {
DispatcherServletInstanceFactory servletFactory = new DispatcherServletInstanceFactory(cxt);
DeploymentInfo servletBuilder = deployment()
@@ -66,6 +69,13 @@ public class UndertowTestServer implements WebSocketTestServer {
.addServlet(servlet("DispatcherServlet", DispatcherServlet.class, servletFactory).addMapping("/"))
.addServletContextAttribute(WebSocketDeploymentInfo.ATTRIBUTE_NAME, new WebSocketDeploymentInfo());
for (final Filter filter : filters) {
String filterName = filter.getClass().getName();
servletBuilder.addFilter(new FilterInfo(filterName, filter.getClass(), new FilterInstanceFactory(filter)));
for (DispatcherType type : DispatcherType.values()) {
servletBuilder.addFilterUrlMapping(filterName, "/*", type);
}
}
this.manager = defaultContainer().addDeployment(servletBuilder);
this.manager.deploy();
@@ -117,4 +127,25 @@ public class UndertowTestServer implements WebSocketTestServer {
}
}
private static class FilterInstanceFactory implements InstanceFactory<Filter> {
private final Filter filter;
private FilterInstanceFactory(Filter filter) {
this.filter = filter;
}
@Override
public InstanceHandle<Filter> createInstance() throws InstantiationException {
return new InstanceHandle<Filter>() {
@Override
public Filter getInstance() {
return filter;
}
@Override
public void release() {}
};
}
}
}

View File

@@ -58,24 +58,22 @@ public class WebSocketIntegrationTests extends AbstractWebSocketIntegrationTest
@Override
protected Class<?>[] getAnnotatedConfigClasses() {
return new Class<?>[] {TestWebSocketConfigurer.class};
return new Class<?>[] { TestConfig.class };
}
@Test
public void subProtocolNegotiation() throws Exception {
WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
headers.setSecWebSocketProtocol("foo");
WebSocketSession session = this.webSocketClient.doHandshake(
new AbstractWebSocketHandler() {}, headers, new URI(getWsBaseUrl() + "/ws")).get();
URI url = new URI(getWsBaseUrl() + "/ws");
WebSocketSession session = this.webSocketClient.doHandshake(new TextWebSocketHandler(), headers, url).get();
assertEquals("foo", session.getAcceptedProtocol());
}
@Configuration
@EnableWebSocket
static class TestWebSocketConfigurer implements WebSocketConfigurer {
static class TestConfig implements WebSocketConfigurer {
@Autowired
private DefaultHandshakeHandler handshakeHandler; // can't rely on classpath for server detection
@@ -83,17 +81,13 @@ public class WebSocketIntegrationTests extends AbstractWebSocketIntegrationTest
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
this.handshakeHandler.setSupportedProtocols("foo", "bar", "baz");
registry.addHandler(serverHandler(), "/ws").setHandshakeHandler(this.handshakeHandler);
registry.addHandler(handler(), "/ws").setHandshakeHandler(this.handshakeHandler);
}
@Bean
public TestServerWebSocketHandler serverHandler() {
return new TestServerWebSocketHandler();
public TextWebSocketHandler handler() {
return new TextWebSocketHandler();
}
}
private static class TestServerWebSocketHandler extends TextWebSocketHandler {
}
}

View File

@@ -18,6 +18,8 @@ package org.springframework.web.socket;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.Filter;
/**
* Contract for a test server to use for WebSocket integration tests.
*
@@ -27,7 +29,7 @@ public interface WebSocketTestServer {
int getPort();
void deployConfig(WebApplicationContext cxt);
void deployConfig(WebApplicationContext cxt, Filter... filters);
void undeployConfig();

View File

@@ -57,7 +57,7 @@ public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTes
@Override
protected Class<?>[] getAnnotatedConfigClasses() {
return new Class<?>[] {TestWebSocketConfigurer.class};
return new Class<?>[] { TestConfig.class };
}
@Test
@@ -65,7 +65,7 @@ public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTes
WebSocketSession session = this.webSocketClient.doHandshake(
new AbstractWebSocketHandler() {}, getWsBaseUrl() + "/ws").get();
TestWebSocketHandler serverHandler = this.wac.getBean(TestWebSocketHandler.class);
TestHandler serverHandler = this.wac.getBean(TestHandler.class);
assertTrue(serverHandler.connectLatch.await(2, TimeUnit.SECONDS));
session.close();
@@ -76,7 +76,7 @@ public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTes
WebSocketSession session = this.webSocketClient.doHandshake(
new AbstractWebSocketHandler() {}, getWsBaseUrl() + "/sockjs/websocket").get();
TestWebSocketHandler serverHandler = this.wac.getBean(TestWebSocketHandler.class);
TestHandler serverHandler = this.wac.getBean(TestHandler.class);
assertTrue(serverHandler.connectLatch.await(2, TimeUnit.SECONDS));
session.close();
@@ -85,7 +85,7 @@ public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTes
@Configuration
@EnableWebSocket
static class TestWebSocketConfigurer implements WebSocketConfigurer {
static class TestConfig implements WebSocketConfigurer {
@Autowired
private HandshakeHandler handshakeHandler; // can't rely on classpath for server detection
@@ -99,12 +99,12 @@ public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTes
}
@Bean
public TestWebSocketHandler serverHandler() {
return new TestWebSocketHandler();
public TestHandler serverHandler() {
return new TestHandler();
}
}
private static class TestWebSocketHandler extends AbstractWebSocketHandler {
private static class TestHandler extends AbstractWebSocketHandler {
private CountDownLatch connectLatch = new CountDownLatch(1);