do not set WebSocketMapping in WSUpgradeFilter if already set

the WSUpgradeFilter now has to be registered at "/" or "/*"

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2019-01-22 18:17:33 +11:00
parent 3c2f728574
commit 15c6f5250d
3 changed files with 62 additions and 20 deletions

View File

@ -37,6 +37,7 @@ import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ThreadClassLoaderScope; import org.eclipse.jetty.util.thread.ThreadClassLoaderScope;
import org.eclipse.jetty.websocket.core.WebSocketResources;
import org.eclipse.jetty.websocket.servlet.WebSocketMapping; import org.eclipse.jetty.websocket.servlet.WebSocketMapping;
import org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter; import org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter;
@ -81,14 +82,20 @@ public class JavaxWebSocketServletContainerInitializer implements ServletContain
return null; return null;
} }
public static JavaxWebSocketServerContainer configureContext(ServletContextHandler context) public static JavaxWebSocketServerContainer configureContext(ServletContextHandler context) throws ServletException
throws ServletException
{ {
WebSocketMapping mapping = WebSocketMapping.ensureMapping(context.getServletContext()); WebSocketResources resources = WebSocketResources.ensureWebSocketResources(context.getServletContext());
FilterHolder upgradeFilter = WebSocketUpgradeFilter.ensureFilter(context.getServletContext()); FilterHolder filterHolder = WebSocketUpgradeFilter.ensureFilter(context.getServletContext());
WebSocketUpgradeFilter upgradeFilter = ((WebSocketUpgradeFilter)filterHolder.getFilter());
if (upgradeFilter.getMapping() == null)
upgradeFilter.setMapping(new WebSocketMapping(resources));
JavaxWebSocketServerContainer container = JavaxWebSocketServerContainer.ensureContainer(context.getServletContext()); JavaxWebSocketServerContainer container = JavaxWebSocketServerContainer.ensureContainer(context.getServletContext());
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("configureContext {} {} {}",mapping,upgradeFilter,container); LOG.debug("configureContext {} {} {} {}", upgradeFilter.getMapping(), resources, upgradeFilter, container);
return container; return container;
} }

View File

@ -29,6 +29,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.core.WebSocketResources;
/** /**
* ServletContext configuration for Jetty Native WebSockets API. * ServletContext configuration for Jetty Native WebSockets API.
@ -72,9 +73,10 @@ public class JettyWebSocketServletContainerInitializer implements ServletContain
@Override @Override
public void onStartup(Set<Class<?>> c, ServletContext servletContext) throws ServletException public void onStartup(Set<Class<?>> c, ServletContext servletContext) throws ServletException
{ {
WebSocketResources resources = WebSocketResources.ensureWebSocketResources(servletContext);
JettyServerFrameHandlerFactory factory = JettyServerFrameHandlerFactory.ensureFactory(servletContext); JettyServerFrameHandlerFactory factory = JettyServerFrameHandlerFactory.ensureFactory(servletContext);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("onStartup {}", factory); LOG.debug("onStartup {} {}", resources, factory);
} }
} }

View File

@ -33,9 +33,9 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedObject;
@ -43,8 +43,6 @@ import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.core.FrameHandler; import org.eclipse.jetty.websocket.core.FrameHandler;
import org.eclipse.jetty.websocket.core.server.Handshaker;
import org.eclipse.jetty.websocket.core.server.WebSocketNegotiator;
/** /**
* Inline Servlet Filter to capture WebSocket upgrade requests. * Inline Servlet Filter to capture WebSocket upgrade requests.
@ -78,25 +76,57 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
{ {
private static final Logger LOG = Log.getLogger(WebSocketUpgradeFilter.class); private static final Logger LOG = Log.getLogger(WebSocketUpgradeFilter.class);
public static FilterHolder ensureFilter(ServletContext servletContext) throws ServletException
public static FilterHolder getFilter(ServletContext servletContext)
{ {
ServletHandler servletHandler = ContextHandler.getContextHandler(servletContext).getChildHandlerByClass(ServletHandler.class); ServletHandler servletHandler = ContextHandler.getContextHandler(servletContext).getChildHandlerByClass(ServletHandler.class);
for (FilterHolder holder : servletHandler.getFilters()) for (FilterHolder holder : servletHandler.getFilters())
{ {
if (holder.getClassName().equals(WebSocketUpgradeFilter.class.getName())) if (holder.getClassName().equals(WebSocketUpgradeFilter.class.getName()) ||
return holder; (holder.getHeldClass() != null && WebSocketUpgradeFilter.class.isAssignableFrom(holder.getHeldClass())))
if (holder.getHeldClass()!=null && WebSocketUpgradeFilter.class.isAssignableFrom(holder.getHeldClass())) {
return holder; for (FilterMapping mapping : servletHandler.getFilterMappings())
{
if (mapping.getFilterName().equals(holder.getName()))
{
for (String path : mapping.getPathSpecs())
{
if (path.equals("/") || path.equals("/*"))
return holder;
}
}
}
}
} }
return null;
}
public static WebSocketMapping getMapping(ServletContext servletContext)
{
FilterHolder existingFilter = WebSocketUpgradeFilter.getFilter(servletContext);
if (existingFilter == null)
return null;
return ((WebSocketUpgradeFilter)existingFilter.getFilter()).getMapping();
}
public static FilterHolder ensureFilter(ServletContext servletContext)
{
FilterHolder existingFilter = WebSocketUpgradeFilter.getFilter(servletContext);
if (existingFilter != null)
return existingFilter;
String name = "WebSocketUpgradeFilter"; String name = "WebSocketUpgradeFilter";
// TODO this should be registered at pathSpec "/" (NOTE: also remove from getFilter)
String pathSpec = "/*"; String pathSpec = "/*";
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST); EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST);
FilterHolder holder = new FilterHolder(new WebSocketUpgradeFilter()); FilterHolder holder = new FilterHolder(new WebSocketUpgradeFilter());
holder.setName(name); holder.setName(name);
holder.setAsyncSupported(true); holder.setAsyncSupported(true);
ServletHandler servletHandler = ContextHandler.getContextHandler(servletContext).getChildHandlerByClass(ServletHandler.class);
servletHandler.addFilterWithMapping(holder, pathSpec, dispatcherTypes); servletHandler.addFilterWithMapping(holder, pathSpec, dispatcherTypes);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Adding {} mapped to {} in {}", holder, pathSpec, servletContext); LOG.debug("Adding {} mapped to {} in {}", holder, pathSpec, servletContext);
@ -106,10 +136,6 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
private final FrameHandler.ConfigurationCustomizer defaultCustomizer = new FrameHandler.ConfigurationCustomizer(); private final FrameHandler.ConfigurationCustomizer defaultCustomizer = new FrameHandler.ConfigurationCustomizer();
private WebSocketMapping mapping; private WebSocketMapping mapping;
public WebSocketUpgradeFilter()
{
}
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{ {
@ -141,6 +167,11 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
Dumpable.dumpObjects(out, indent, this, mapping); Dumpable.dumpObjects(out, indent, this, mapping);
} }
public void setMapping(WebSocketMapping mapping)
{
this.mapping = mapping;
}
@ManagedAttribute(value = "factory", readonly = true) @ManagedAttribute(value = "factory", readonly = true)
public WebSocketMapping getMapping() public WebSocketMapping getMapping()
{ {
@ -151,7 +182,9 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
public void init(FilterConfig config) throws ServletException public void init(FilterConfig config) throws ServletException
{ {
final ServletContext context = config.getServletContext(); final ServletContext context = config.getServletContext();
mapping = WebSocketMapping.ensureMapping(context);
if (mapping == null)
throw new IllegalStateException("no websocket mapping set in container");
String max = config.getInitParameter("maxIdleTime"); String max = config.getInitParameter("maxIdleTime");
if (max != null) if (max != null)