Skip to content

Commit

Permalink
Issue #5378 - guard against concurrent requests lazily initializing t…
Browse files Browse the repository at this point in the history
…he filter

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
  • Loading branch information
lachlan-roberts committed Oct 7, 2020
1 parent 5e1e93d commit c10bb59
Showing 1 changed file with 26 additions and 17 deletions.
Expand Up @@ -21,6 +21,7 @@
import java.io.IOException;
import java.time.Duration;
import java.util.EnumSet;
import java.util.Objects;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
Expand All @@ -37,6 +38,7 @@
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.thread.AutoLock;
import org.eclipse.jetty.websocket.core.Configuration;
import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents;
import org.eclipse.jetty.websocket.util.server.internal.WebSocketMapping;
Expand Down Expand Up @@ -74,10 +76,12 @@
public class WebSocketUpgradeFilter implements Filter, Dumpable
{
private static final Logger LOG = LoggerFactory.getLogger(WebSocketUpgradeFilter.class);
private static final AutoLock LOCK = new AutoLock();

private static FilterHolder getFilter(ServletContext servletContext)
{
ServletHandler servletHandler = ContextHandler.getContextHandler(servletContext).getChildHandlerByClass(ServletHandler.class);
ContextHandler contextHandler = Objects.requireNonNull(ContextHandler.getContextHandler(servletContext));
ServletHandler servletHandler = contextHandler.getChildHandlerByClass(ServletHandler.class);

for (FilterHolder holder : servletHandler.getFilters())
{
Expand Down Expand Up @@ -105,22 +109,27 @@ private static FilterHolder getFilter(ServletContext servletContext)
*/
public static FilterHolder ensureFilter(ServletContext servletContext)
{
FilterHolder existingFilter = WebSocketUpgradeFilter.getFilter(servletContext);
if (existingFilter != null)
return existingFilter;

final String name = "WebSocketUpgradeFilter";
final String pathSpec = "/*";
FilterHolder holder = new FilterHolder(new WebSocketUpgradeFilter());
holder.setName(name);
holder.setInitParameter(MAPPING_ATTRIBUTE_INIT_PARAM, WebSocketMapping.DEFAULT_KEY);

holder.setAsyncSupported(true);
ServletHandler servletHandler = ContextHandler.getContextHandler(servletContext).getChildHandlerByClass(ServletHandler.class);
servletHandler.addFilterWithMapping(holder, pathSpec, EnumSet.of(DispatcherType.REQUEST));
if (LOG.isDebugEnabled())
LOG.debug("Adding {} mapped to {} in {}", holder, pathSpec, servletContext);
return holder;
// Lock in case two concurrent requests are initializing the filter lazily.
try (AutoLock l = LOCK.lock())
{
FilterHolder existingFilter = WebSocketUpgradeFilter.getFilter(servletContext);
if (existingFilter != null)
return existingFilter;

final String name = "WebSocketUpgradeFilter";
final String pathSpec = "/*";
FilterHolder holder = new FilterHolder(new WebSocketUpgradeFilter());
holder.setName(name);
holder.setInitParameter(MAPPING_ATTRIBUTE_INIT_PARAM, WebSocketMapping.DEFAULT_KEY);

holder.setAsyncSupported(true);
ContextHandler contextHandler = Objects.requireNonNull(ContextHandler.getContextHandler(servletContext));
ServletHandler servletHandler = contextHandler.getChildHandlerByClass(ServletHandler.class);
servletHandler.addFilterWithMapping(holder, pathSpec, EnumSet.of(DispatcherType.REQUEST));
if (LOG.isDebugEnabled())
LOG.debug("Adding {} mapped to {} in {}", holder, pathSpec, servletContext);
return holder;
}
}

public static final String MAPPING_ATTRIBUTE_INIT_PARAM = "org.eclipse.jetty.websocket.util.server.internal.WebSocketMapping.key";
Expand Down

0 comments on commit c10bb59

Please sign in to comment.