444517 - Ensure WebSocketUpgradeFilter is always first in filter chain

* Using Servlet 3.1's ServletContext.addFilter() mechanisms with its
    FilterRegistration to encourage the WebSocketUpgradeFilter to be
    first in the filter chain.
    Note: this is possible, but can be overridden by another call
    to the same ServletContext.addFilter() using the same techniques
    to put something in front of the WebSocketUpgradeFilter.
This commit is contained in:
Joakim Erdfelt 2014-09-18 11:11:31 -07:00
parent 2a25402de0
commit 9b7b54ea0b
2 changed files with 67 additions and 11 deletions

View File

@ -45,15 +45,16 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
public static final String ENABLE_KEY = "org.eclipse.jetty.websocket.jsr356";
private static final Logger LOG = Log.getLogger(WebSocketServerContainerInitializer.class);
/**
* Jetty Native approach.
* <p>
* Note: this will add the Upgrade filter to the existing list, with no regard for order. It will just be tacked onto the end of the list.
*/
public static ServerContainer configureContext(ServletContextHandler context)
{
// Create Filter
WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
// Store reference to the WebSocketUpgradeFilter
context.setAttribute(WebSocketUpgradeFilter.class.getName(),filter);
// Create the Jetty ServerContainer implementation
ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),context.getServer().getThreadPool());
context.addBean(jettyContainer);
@ -64,6 +65,26 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
return jettyContainer;
}
/**
* Servlet 3.1 approach.
* <p>
* This will use Servlet 3.1 techniques on the {@link ServletContext} to add a filter at the start of the filter chain.
*/
public static ServerContainer configureContext(ServletContext context, ServletContextHandler jettyContext)
{
// Create Filter
WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
// Create the Jetty ServerContainer implementation
ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),jettyContext.getServer().getThreadPool());
jettyContext.addBean(jettyContainer);
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
return jettyContainer;
}
@Override
public void onStartup(Set<Class<?>> c, ServletContext context) throws ServletException
{
@ -111,7 +132,7 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
ServletContextHandler jettyContext = (ServletContextHandler)handler;
// Create the Jetty ServerContainer implementation
ServerContainer jettyContainer = configureContext(jettyContext);
ServerContainer jettyContainer = configureContext(context, jettyContext);
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);

View File

@ -20,10 +20,13 @@ package org.eclipse.jetty.websocket.server;
import java.io.IOException;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@ -58,16 +61,48 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
public static WebSocketUpgradeFilter configureContext(ServletContextHandler context)
{
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
WebSocketUpgradeFilter filter = new WebSocketUpgradeFilter(policy);
FilterHolder fholder = new FilterHolder(filter);
fholder.setName("Jetty_WebSocketUpgradeFilter");
fholder.setDisplayName("WebSocket Upgrade Filter");
String name = "Jetty_WebSocketUpgradeFilter";
String pathSpec = "/*";
context.addFilter(fholder,pathSpec,EnumSet.of(DispatcherType.REQUEST));
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST);
FilterHolder fholder = new FilterHolder(filter);
fholder.setName(name);
context.addFilter(fholder,pathSpec,dispatcherTypes);
if (LOG.isDebugEnabled())
LOG.debug("Adding {} mapped to {} to {}",filter,pathSpec,context);
{
LOG.debug("Adding [{}] {} mapped to {} to {}",name,filter,pathSpec,context);
}
// Store reference to the WebSocketUpgradeFilter
context.setAttribute(WebSocketUpgradeFilter.class.getName(),filter);
return filter;
}
public static WebSocketUpgradeFilter configureContext(ServletContext context)
{
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
WebSocketUpgradeFilter filter = new WebSocketUpgradeFilter(policy);
String name = "Jetty_Dynamic_WebSocketUpgradeFilter";
String pathSpec = "/*";
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST);
boolean isMatchAfter = false;
String urlPatterns[] =
{
pathSpec
};
FilterRegistration.Dynamic dyn = context.addFilter(name,filter);
dyn.addMappingForUrlPatterns(dispatcherTypes,isMatchAfter,urlPatterns);
if (LOG.isDebugEnabled())
{
LOG.debug("Adding [{}] {} mapped to {} to {}",name,filter,pathSpec,context);
}
// Store reference to the WebSocketUpgradeFilter
context.setAttribute(WebSocketUpgradeFilter.class.getName(),filter);