Always add the default WebSocketUpgradeFilter as the first filter.

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2020-11-18 21:27:25 +11:00
parent aba2c93eae
commit 6a83a261e1
6 changed files with 73 additions and 28 deletions

View File

@ -1084,6 +1084,23 @@ public class ServletHandler extends ScopedHandler
}
}
/**
* Convenience method to add a preconstructed FilterHolder
*
* @param filter the filter holder
*/
public void prependFilter(FilterHolder filter)
{
if (filter == null)
return;
try (AutoLock l = lock())
{
if (!containsFilterHolder(filter))
setFilters(ArrayUtil.prependToArray(filter, getFilters(), FilterHolder.class));
}
}
/**
* Convenience method to add a preconstructed FilterMapping
*

View File

@ -311,7 +311,7 @@ public class JettyWebSocketFilterTest
@Test
public void testDefaultWebSocketUpgradeFilterOrdering() throws Exception
{
String timeoutFromAltFilter = "5999";
String defaultIdleTimeout = Long.toString(WebSocketConstants.DEFAULT_IDLE_TIMEOUT.toMillis());
JettyWebSocketWebApp webApp = new JettyWebSocketWebApp("wsuf-ordering1");
Path webXml = MavenTestingUtils.getTestResourcePath("wsuf-ordering1.xml");
webApp.copyWebXml(webXml);
@ -339,13 +339,13 @@ public class JettyWebSocketFilterTest
}
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(socket.textMessages.poll(), is("hello world"));
assertThat(socket.textMessages.poll(), is(timeoutFromAltFilter));
assertThat(socket.textMessages.poll(), is(defaultIdleTimeout));
}
@Test
public void testWebSocketUpgradeFilterOrdering() throws Exception
{
String defaultIdleTimeout = Long.toString(WebSocketConstants.DEFAULT_IDLE_TIMEOUT.toMillis());
String timeoutFromAltFilter = "5999";
JettyWebSocketWebApp webApp = new JettyWebSocketWebApp("wsuf-ordering2");
Path webXml = MavenTestingUtils.getTestResourcePath("wsuf-ordering2.xml");
webApp.copyWebXml(webXml);
@ -373,7 +373,7 @@ public class JettyWebSocketFilterTest
}
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(socket.textMessages.poll(), is("hello world"));
assertThat(socket.textMessages.poll(), is(defaultIdleTimeout));
assertThat(socket.textMessages.poll(), is(timeoutFromAltFilter));
}
@WebListener

View File

@ -1,3 +1,21 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.websocket.tests;
import java.io.File;

View File

@ -2,11 +2,11 @@
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
metadata-complete="false"
version="4.0">
<filter>
<filter>
<filter-name>wsuf-alt</filter-name>
<filter-class>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-class>
<init-param>

View File

@ -2,21 +2,11 @@
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
metadata-complete="false"
version="4.0">
<!-- Make sure the default filter is first. -->
<filter>
<filter-name>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-name>
<filter-class>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- The custom filter is then tried after. -->
<!-- Add the custom filter first. -->
<filter>
<filter-name>wsuf-alt</filter-name>
<filter-class>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-class>
@ -29,4 +19,14 @@
<filter-name>wsuf-alt</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- The default filter is overridden so it is tried after. -->
<filter>
<filter-name>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-name>
<filter-class>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>org.eclipse.jetty.websocket.util.server.WebSocketUpgradeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

View File

@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.Dumpable;
@ -78,12 +79,12 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
private static final AutoLock LOCK = new AutoLock();
/**
* Return any {@link WebSocketUpgradeFilter} already present on the {@link ServletContext}.
* Return the default {@link WebSocketUpgradeFilter} if present on the {@link ServletContext}.
*
* @param servletContext the {@link ServletContext} to use.
* @return the configured default {@link WebSocketUpgradeFilter} instance.
*/
private static FilterHolder getFilter(ServletContext servletContext)
public static FilterHolder getFilter(ServletContext servletContext)
{
ContextHandler contextHandler = Objects.requireNonNull(ContextHandler.getContextHandler(servletContext));
ServletHandler servletHandler = contextHandler.getChildHandlerByClass(ServletHandler.class);
@ -111,14 +112,23 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
if (existingFilter != null)
return existingFilter;
ContextHandler contextHandler = Objects.requireNonNull(ContextHandler.getContextHandler(servletContext));
ServletHandler servletHandler = contextHandler.getChildHandlerByClass(ServletHandler.class);
final String pathSpec = "/*";
FilterHolder holder = new FilterHolder(new WebSocketUpgradeFilter());
holder.setName(WebSocketUpgradeFilter.class.getName());
holder.setAsyncSupported(true);
ContextHandler contextHandler = Objects.requireNonNull(ContextHandler.getContextHandler(servletContext));
ServletHandler servletHandler = contextHandler.getChildHandlerByClass(ServletHandler.class);
servletHandler.addFilterWithMapping(holder, pathSpec, EnumSet.of(DispatcherType.REQUEST));
FilterMapping mapping = new FilterMapping();
mapping.setFilterName(holder.getName());
mapping.setPathSpec(pathSpec);
mapping.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST));
// Add the default WebSocketUpgradeFilter as the first filter in the list.
servletHandler.prependFilter(holder);
servletHandler.prependFilterMapping(mapping);
if (LOG.isDebugEnabled())
LOG.debug("Adding {} mapped to {} in {}", holder, pathSpec, servletContext);
return holder;