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 committed by Simone Bordet
parent 49a32eb1b0
commit f3693219f8
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"; public static final String ENABLE_KEY = "org.eclipse.jetty.websocket.jsr356";
private static final Logger LOG = Log.getLogger(WebSocketServerContainerInitializer.class); 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) public static ServerContainer configureContext(ServletContextHandler context)
{ {
// Create Filter // Create Filter
WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context); WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
// Store reference to the WebSocketUpgradeFilter
context.setAttribute(WebSocketUpgradeFilter.class.getName(),filter);
// Create the Jetty ServerContainer implementation // Create the Jetty ServerContainer implementation
ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),context.getServer().getThreadPool()); ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),context.getServer().getThreadPool());
context.addBean(jettyContainer); context.addBean(jettyContainer);
@ -64,6 +65,26 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
return jettyContainer; 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 @Override
public void onStartup(Set<Class<?>> c, ServletContext context) throws ServletException public void onStartup(Set<Class<?>> c, ServletContext context) throws ServletException
{ {
@ -111,7 +132,7 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
ServletContextHandler jettyContext = (ServletContextHandler)handler; ServletContextHandler jettyContext = (ServletContextHandler)handler;
// Create the Jetty ServerContainer implementation // 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 // 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); 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.io.IOException;
import java.util.EnumSet; import java.util.EnumSet;
import javax.servlet.DispatcherType; import javax.servlet.DispatcherType;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
import javax.servlet.FilterConfig; import javax.servlet.FilterConfig;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
@ -58,16 +61,48 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
public static WebSocketUpgradeFilter configureContext(ServletContextHandler context) public static WebSocketUpgradeFilter configureContext(ServletContextHandler context)
{ {
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
WebSocketUpgradeFilter filter = new WebSocketUpgradeFilter(policy); WebSocketUpgradeFilter filter = new WebSocketUpgradeFilter(policy);
FilterHolder fholder = new FilterHolder(filter);
fholder.setName("Jetty_WebSocketUpgradeFilter"); String name = "Jetty_WebSocketUpgradeFilter";
fholder.setDisplayName("WebSocket Upgrade Filter");
String pathSpec = "/*"; 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()) 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 // Store reference to the WebSocketUpgradeFilter
context.setAttribute(WebSocketUpgradeFilter.class.getName(),filter); context.setAttribute(WebSocketUpgradeFilter.class.getName(),filter);