Merge branch `jetty-9.4.x` into `jetty-10.0.x`
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com> # Conflicts: # jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java # jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BinaryStreamTest.java # jetty-websocket/javax-websocket-server/src/test/java/org/eclipse/jetty/websocket/javax/server/browser/JsrBrowserDebugTool.java # jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/NativeWebSocketServletContainerInitializer.java # jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java
This commit is contained in:
commit
22b054e0ef
|
@ -722,6 +722,16 @@ public class ServletContextHandler extends ContextHandler
|
|||
_objFactory.destroy(filter);
|
||||
}
|
||||
|
||||
public static ServletContextHandler getServletContextHandler(ServletContext context)
|
||||
{
|
||||
ContextHandler handler = getContextHandler(context);
|
||||
if (handler == null)
|
||||
return null;
|
||||
if (handler instanceof ServletContextHandler)
|
||||
return (ServletContextHandler) handler;
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static class JspPropertyGroup implements JspPropertyGroupDescriptor
|
||||
{
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.servlet.listener;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import javax.servlet.ServletContainerInitializer;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
/**
|
||||
* Utility Methods for manual execution of {@link javax.servlet.ServletContainerInitializer} when
|
||||
* using Embedded Jetty.
|
||||
*/
|
||||
public final class ContainerInitializer
|
||||
{
|
||||
/**
|
||||
* Utility Method to allow for manual execution of {@link javax.servlet.ServletContainerInitializer} when
|
||||
* using Embedded Jetty.
|
||||
*
|
||||
* <pre>
|
||||
* ServletContextHandler context = new ServletContextHandler();
|
||||
* ServletContainerInitializer corpSci = new MyCorporateSCI();
|
||||
* context.addEventListener(ContainerInitializer.asContextListener(corpSci));
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* The {@link ServletContainerInitializer} will have its {@link ServletContainerInitializer#onStartup(Set, ServletContext)}
|
||||
* method called with the manually configured list of {@code Set<Class<?>> c} set.
|
||||
* In other words, this usage does not perform bytecode or annotation scanning against the classes in
|
||||
* your {@code ServletContextHandler} or {@code WebAppContext}.
|
||||
* </p>
|
||||
*
|
||||
* @param sci the {@link ServletContainerInitializer} to call
|
||||
* @return the {@link ServletContextListener} wrapping the SCI
|
||||
* @see ServletContainerInitializerServletContextListener#addClasses(Class[])
|
||||
* @see ServletContainerInitializerServletContextListener#addClasses(String...)
|
||||
*/
|
||||
public static ServletContainerInitializerServletContextListener asContextListener(ServletContainerInitializer sci)
|
||||
{
|
||||
return new ServletContainerInitializerServletContextListener(sci);
|
||||
}
|
||||
|
||||
public static class ServletContainerInitializerServletContextListener implements ServletContextListener
|
||||
{
|
||||
private final ServletContainerInitializer sci;
|
||||
private Set<String> classNames;
|
||||
private Set<Class<?>> classes = new HashSet<>();
|
||||
private Consumer<ServletContext> afterStartupConsumer;
|
||||
|
||||
public ServletContainerInitializerServletContextListener(ServletContainerInitializer sci)
|
||||
{
|
||||
this.sci = sci;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add classes to be passed to the {@link ServletContainerInitializer#onStartup(Set, ServletContext)} call.
|
||||
* <p>
|
||||
* Note that these classes will be loaded using the context classloader for the ServletContext
|
||||
* initialization phase.
|
||||
* </p>
|
||||
*
|
||||
* @param classNames the class names to load and pass into the {@link ServletContainerInitializer#onStartup(Set, ServletContext)} call
|
||||
* @return this configured {@link ServletContainerInitializerServletContextListener} instance.
|
||||
*/
|
||||
public ServletContainerInitializerServletContextListener addClasses(String... classNames)
|
||||
{
|
||||
if (this.classNames == null)
|
||||
{
|
||||
this.classNames = new HashSet<>();
|
||||
}
|
||||
this.classNames.addAll(Arrays.asList(classNames));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add classes to be passed to the {@link ServletContainerInitializer#onStartup(Set, ServletContext)} call.
|
||||
* <p>
|
||||
* Note that these classes will exist on the classloader that was used to call this method.
|
||||
* If you want the classes to be loaded using the context classloader for the ServletContext
|
||||
* then use the String form of the classes via the {@link #addClasses(String...)} method.
|
||||
* </p>
|
||||
*
|
||||
* @param classes the classes to pass into the {@link ServletContainerInitializer#onStartup(Set, ServletContext)} call
|
||||
* @return this configured {@link ServletContainerInitializerServletContextListener} instance.
|
||||
*/
|
||||
public ServletContainerInitializerServletContextListener addClasses(Class<?>... classes)
|
||||
{
|
||||
this.classes.addAll(Arrays.asList(classes));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a optional consumer to execute once the {@link ServletContainerInitializer#onStartup(Set, ServletContext)} has
|
||||
* been called successfully.
|
||||
* <p>
|
||||
* This would be for actions to perform on a ServletContext once this specific SCI has completed
|
||||
* its execution. Actions that would require specific configurations that the SCI provides to be present on the
|
||||
* ServletContext to function properly.
|
||||
* </p>
|
||||
* <p>
|
||||
* This consumer is typically used for Embedded Jetty users to configure Jetty for their specific needs.
|
||||
* </p>
|
||||
*
|
||||
* @param consumer the consumer to execute after the SCI has executed
|
||||
* @return this configured {@link ServletContainerInitializerServletContextListener} instance.
|
||||
*/
|
||||
public ServletContainerInitializerServletContextListener afterStartup(Consumer<ServletContext> consumer)
|
||||
{
|
||||
this.afterStartupConsumer = consumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
ServletContext servletContext = sce.getServletContext();
|
||||
try
|
||||
{
|
||||
sci.onStartup(getClasses(), servletContext);
|
||||
if (afterStartupConsumer != null)
|
||||
{
|
||||
afterStartupConsumer.accept(servletContext);
|
||||
}
|
||||
}
|
||||
catch (RuntimeException rte)
|
||||
{
|
||||
throw rte;
|
||||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
throw new RuntimeException(cause);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Class<?>> getClasses()
|
||||
{
|
||||
if (classNames != null && !classNames.isEmpty())
|
||||
{
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
for (String className : classNames)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> clazz = cl.loadClass(className);
|
||||
classes.add(clazz);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw new RuntimeException("Unable to find class: " + className, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.jsr356.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.handler.DefaultHandler;
|
||||
import org.eclipse.jetty.server.handler.HandlerList;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.api.util.WSURI;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class RestartContextTest
|
||||
{
|
||||
private Server server;
|
||||
private WebSocketClient client;
|
||||
|
||||
@BeforeEach
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartStopStart_ServletContextListener() throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
|
||||
ServerConnector connector = new ServerConnector(server);
|
||||
connector.setPort(0);
|
||||
server.addConnector(connector);
|
||||
|
||||
// Setup Context
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
WebSocketServerContainerInitializer.configure(context, null);
|
||||
// late initialization via my own ServletContextListener
|
||||
context.addEventListener(new AddEndpointListener());
|
||||
|
||||
// Setup handler tree
|
||||
HandlerList handlers = new HandlerList();
|
||||
handlers.addHandler(context);
|
||||
handlers.addHandler(new DefaultHandler());
|
||||
|
||||
// Add handler tree to server
|
||||
server.setHandler(handlers);
|
||||
|
||||
// Start server
|
||||
server.start();
|
||||
|
||||
// verify functionality
|
||||
verifyWebSocketEcho(server.getURI().resolve("/echo"));
|
||||
|
||||
// Stop server
|
||||
server.stop();
|
||||
|
||||
// Start server (again)
|
||||
server.start();
|
||||
|
||||
// verify functionality (again)
|
||||
verifyWebSocketEcho(server.getURI().resolve("/echo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartStopStart_Configurator() throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
|
||||
ServerConnector connector = new ServerConnector(server);
|
||||
connector.setPort(0);
|
||||
server.addConnector(connector);
|
||||
|
||||
// Setup Context
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
WebSocketServerContainerInitializer.configure(context, (servletContext, serverContainer) -> {
|
||||
// Add endpoint via configurator
|
||||
serverContainer.addEndpoint(EchoEndpoint.class);
|
||||
});
|
||||
|
||||
// Setup handler tree
|
||||
HandlerList handlers = new HandlerList();
|
||||
handlers.addHandler(context);
|
||||
handlers.addHandler(new DefaultHandler());
|
||||
|
||||
// Add handler tree to server
|
||||
server.setHandler(handlers);
|
||||
|
||||
// Start server
|
||||
server.start();
|
||||
|
||||
// verify functionality
|
||||
verifyWebSocketEcho(server.getURI().resolve("/echo"));
|
||||
|
||||
// Stop server
|
||||
server.stop();
|
||||
|
||||
// Start server (again)
|
||||
server.start();
|
||||
|
||||
// verify functionality (again)
|
||||
verifyWebSocketEcho(server.getURI().resolve("/echo"));
|
||||
}
|
||||
|
||||
private void verifyWebSocketEcho(URI endpointUri) throws URISyntaxException, IOException, ExecutionException, InterruptedException
|
||||
{
|
||||
ClientEndpoint endpoint = new ClientEndpoint();
|
||||
Future<Session> fut = client.connect(endpoint, WSURI.toWebsocket(endpointUri));
|
||||
try(Session session = fut.get())
|
||||
{
|
||||
session.getRemote().sendString("Test Echo");
|
||||
String msg = endpoint.messages.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("msg", msg, is("Test Echo"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class AddEndpointListener implements ServletContextListener
|
||||
{
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
ServerContainer container = (ServerContainer) sce.getServletContext().getAttribute(javax.websocket.server.ServerContainer.class.getName());
|
||||
try
|
||||
{
|
||||
container.addEndpoint(EchoEndpoint.class);
|
||||
}
|
||||
catch (DeploymentException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ServerEndpoint("/echo")
|
||||
public static class EchoEndpoint
|
||||
{
|
||||
@OnMessage
|
||||
public String onMessage(String msg)
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
@WebSocket
|
||||
public static class ClientEndpoint
|
||||
{
|
||||
public LinkedBlockingQueue<String> messages = new LinkedBlockingQueue<>();
|
||||
|
||||
@OnWebSocketMessage
|
||||
public void onMessage(String msg)
|
||||
{
|
||||
this.messages.offer(msg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,11 +22,9 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
|
@ -51,7 +49,7 @@ import org.eclipse.jetty.websocket.servlet.WebSocketMapping;
|
|||
@ManagedObject("JSR356 Server Container")
|
||||
public class JavaxWebSocketServerContainer extends JavaxWebSocketClientContainer implements javax.websocket.server.ServerContainer, LifeCycle.Listener
|
||||
{
|
||||
public static final String JAVAX_WEBSOCKET_CONTAINER_ATTRIBUTE = ServerContainer.class.getName();
|
||||
public static final String JAVAX_WEBSOCKET_CONTAINER_ATTRIBUTE = javax.websocket.server.ServerContainer.class.getName();
|
||||
private static final Logger LOG = Log.getLogger(JavaxWebSocketServerContainer.class);
|
||||
|
||||
public static JavaxWebSocketServerContainer ensureContainer(ServletContext servletContext)
|
||||
|
|
|
@ -27,11 +27,13 @@ import javax.servlet.annotation.HandlesTypes;
|
|||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.Endpoint;
|
||||
import javax.websocket.server.ServerApplicationConfig;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.listener.ContainerInitializer;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -43,8 +45,13 @@ import org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter;
|
|||
@HandlesTypes({ ServerApplicationConfig.class, ServerEndpoint.class, Endpoint.class })
|
||||
public class JavaxWebSocketServletContainerInitializer implements ServletContainerInitializer
|
||||
{
|
||||
/**
|
||||
* The ServletContext attribute key name for the
|
||||
* ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
|
||||
*/
|
||||
public static final String ATTR_JAVAX_SERVER_CONTAINER = javax.websocket.server.ServerContainer.class.getName();
|
||||
|
||||
public static final String ENABLE_KEY = "org.eclipse.jetty.websocket.javax";
|
||||
public static final String DEPRECATED_ENABLE_KEY = "org.eclipse.jetty.websocket.jsr356";
|
||||
public static final String HTTPCLIENT_ATTRIBUTE = "org.eclipse.jetty.websocket.javax.HttpClient";
|
||||
private static final Logger LOG = Log.getLogger(JavaxWebSocketServletContainerInitializer.class);
|
||||
|
||||
|
@ -81,32 +88,89 @@ public class JavaxWebSocketServletContainerInitializer implements ServletContain
|
|||
return null;
|
||||
}
|
||||
|
||||
public static JavaxWebSocketServerContainer configureContext(ServletContextHandler context)
|
||||
public interface Configurator
|
||||
{
|
||||
WebSocketComponents components = WebSocketComponents.ensureWebSocketComponents(context.getServletContext());
|
||||
FilterHolder filterHolder = WebSocketUpgradeFilter.ensureFilter(context.getServletContext());
|
||||
WebSocketMapping mapping = WebSocketMapping.ensureMapping(context.getServletContext(), WebSocketMapping.DEFAULT_KEY);
|
||||
JavaxWebSocketServerContainer container = JavaxWebSocketServerContainer.ensureContainer(context.getServletContext());
|
||||
void accept(ServletContext servletContext, ServerContainer serverContainer) throws DeploymentException;
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("configureContext {} {} {} {}", mapping, components, filterHolder, container);
|
||||
/**
|
||||
* Configure the {@link ServletContextHandler} to call {@link JavaxWebSocketServletContainerInitializer#onStartup(Set, ServletContext)}
|
||||
* during the {@link ServletContext} initialization phase.
|
||||
*
|
||||
* @param context the context to add listener to
|
||||
* @param configurator the lambda that is called to allow the {@link ServerContainer} to
|
||||
* be configured during the {@link ServletContext} initialization phase
|
||||
*/
|
||||
public static void configure(ServletContextHandler context, Configurator configurator)
|
||||
{
|
||||
// In this embedded-jetty usage, allow ServletContext.addListener() to
|
||||
// add other ServletContextListeners (such as the ContextDestroyListener) after
|
||||
// the initialization phase is over. (important for this SCI to function)
|
||||
context.getServletContext().setExtendedListenerTypes(true);
|
||||
|
||||
return container;
|
||||
context.addEventListener(ContainerInitializer.asContextListener(new JavaxWebSocketServletContainerInitializer())
|
||||
.afterStartup((servletContext) ->
|
||||
{
|
||||
ServerContainer serverContainer = (ServerContainer)servletContext.getAttribute(ATTR_JAVAX_SERVER_CONTAINER);
|
||||
if (configurator != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
configurator.accept(servletContext, serverContainer);
|
||||
}
|
||||
catch (DeploymentException e)
|
||||
{
|
||||
throw new RuntimeException("Failed to deploy WebSocket Endpoint", e);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately initialize the {@link ServletContext} with the default (and empty) {@link ServerContainer}.
|
||||
*
|
||||
* <p>
|
||||
* This method is typically called from {@link #onStartup(Set, ServletContext)} itself or from
|
||||
* another dependent {@link ServletContainerInitializer} that requires minimal setup to
|
||||
* be performed.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method SHOULD NOT BE CALLED by users of Jetty.
|
||||
* Use the {@link #configure(ServletContextHandler, Configurator)} method instead.
|
||||
* </p>
|
||||
* <p>
|
||||
* There is no enablement check here, and no automatic deployment of endpoints at this point
|
||||
* in time. It merely sets up the {@link ServletContext} so with the basics needed to start
|
||||
* configuring for `javax.websocket.server` based endpoints.
|
||||
* </p>
|
||||
*
|
||||
* @param context the context to work with
|
||||
* @return the default {@link ServerContainer} for this context
|
||||
*/
|
||||
public static JavaxWebSocketServerContainer initialize(ServletContextHandler context)
|
||||
{
|
||||
JavaxWebSocketServerContainer serverContainer = (JavaxWebSocketServerContainer) context.getAttribute(ATTR_JAVAX_SERVER_CONTAINER);
|
||||
if(serverContainer == null)
|
||||
{
|
||||
WebSocketComponents components = WebSocketComponents.ensureWebSocketComponents(context.getServletContext());
|
||||
FilterHolder filterHolder = WebSocketUpgradeFilter.ensureFilter(context.getServletContext());
|
||||
WebSocketMapping mapping = WebSocketMapping.ensureMapping(context.getServletContext(), WebSocketMapping.DEFAULT_KEY);
|
||||
serverContainer = JavaxWebSocketServerContainer.ensureContainer(context.getServletContext());
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("configureContext {} {} {} {}", mapping, components, filterHolder, serverContainer);
|
||||
}
|
||||
return serverContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartup(Set<Class<?>> c, ServletContext context) throws ServletException
|
||||
{
|
||||
Boolean enableKey = isEnabledViaContext(context, ENABLE_KEY);
|
||||
Boolean deprecatedEnabledKey = isEnabledViaContext(context, DEPRECATED_ENABLE_KEY);
|
||||
if (deprecatedEnabledKey != null)
|
||||
LOG.warn("Deprecated parameter used: " + DEPRECATED_ENABLE_KEY);
|
||||
|
||||
boolean websocketEnabled = true;
|
||||
if (enableKey != null)
|
||||
websocketEnabled = enableKey;
|
||||
else if (deprecatedEnabledKey != null)
|
||||
websocketEnabled = deprecatedEnabledKey;
|
||||
|
||||
if (!websocketEnabled)
|
||||
{
|
||||
|
@ -114,7 +178,8 @@ public class JavaxWebSocketServletContainerInitializer implements ServletContain
|
|||
return;
|
||||
}
|
||||
|
||||
JavaxWebSocketServerContainer container = configureContext(ServletContextHandler.getServletContextHandler(context,"Javax WebSocket SCI"));
|
||||
ServletContextHandler servletContextHandler = ServletContextHandler.getServletContextHandler(context,"Javax WebSocket SCI");
|
||||
JavaxWebSocketServerContainer container = initialize(servletContextHandler);
|
||||
|
||||
try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(context.getClassLoader()))
|
||||
{
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.net.URI;
|
|||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.websocket.ClientEndpoint;
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.ContainerProvider;
|
||||
|
@ -32,7 +31,6 @@ import javax.websocket.OnMessage;
|
|||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
|
||||
import org.eclipse.jetty.security.ConstraintMapping;
|
||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||
|
@ -110,10 +108,12 @@ public class WebSocketServerExamplesTest
|
|||
_context.setSecurityHandler(getSecurityHandler("user", "password", "testRealm"));
|
||||
_server.setHandler(_context);
|
||||
|
||||
ServerContainer serverContainer = JavaxWebSocketServletContainerInitializer.configureContext(_context);
|
||||
serverContainer.addEndpoint(MyAuthedSocket.class);
|
||||
serverContainer.addEndpoint(StreamingEchoSocket.class);
|
||||
serverContainer.addEndpoint(GetHttpSessionSocket.class);
|
||||
JavaxWebSocketServletContainerInitializer.configure(_context, (context, container) ->
|
||||
{
|
||||
container.addEndpoint(MyAuthedSocket.class);
|
||||
container.addEndpoint(StreamingEchoSocket.class);
|
||||
container.addEndpoint(GetHttpSessionSocket.class);
|
||||
});
|
||||
|
||||
_server.start();
|
||||
System.setProperty("org.eclipse.jetty.websocket.port", Integer.toString(connector.getLocalPort()));
|
||||
|
@ -125,11 +125,12 @@ public class WebSocketServerExamplesTest
|
|||
_server.stop();
|
||||
}
|
||||
|
||||
private static SecurityHandler getSecurityHandler(String username, String password, String realm) {
|
||||
private static SecurityHandler getSecurityHandler(String username, String password, String realm)
|
||||
{
|
||||
|
||||
HashLoginService loginService = new HashLoginService();
|
||||
UserStore userStore = new UserStore();
|
||||
userStore.addUser(username, Credential.getCredential(password), new String[] {"websocket"});
|
||||
userStore.addUser(username, Credential.getCredential(password), new String[]{"websocket"});
|
||||
loginService.setUserStore(userStore);
|
||||
loginService.setName(realm);
|
||||
|
||||
|
@ -154,11 +155,11 @@ public class WebSocketServerExamplesTest
|
|||
public void testMyAuthedSocket() throws Exception
|
||||
{
|
||||
//HttpClient is configured for BasicAuthentication with the XmlHttpClientProvider
|
||||
URI uri = URI.create("ws://localhost:"+connector.getLocalPort()+"/secured/socket");
|
||||
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/secured/socket");
|
||||
WebSocketContainer clientContainer = ContainerProvider.getWebSocketContainer();
|
||||
|
||||
ClientSocket clientEndpoint = new ClientSocket();
|
||||
try(Session session = clientContainer.connectToServer(clientEndpoint, uri))
|
||||
try (Session session = clientContainer.connectToServer(clientEndpoint, uri))
|
||||
{
|
||||
session.getBasicRemote().sendText("hello world");
|
||||
}
|
||||
|
@ -171,11 +172,11 @@ public class WebSocketServerExamplesTest
|
|||
@Test
|
||||
public void testStreamingEchoSocket() throws Exception
|
||||
{
|
||||
URI uri = URI.create("ws://localhost:"+connector.getLocalPort()+"/echo");
|
||||
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/echo");
|
||||
WebSocketContainer clientContainer = ContainerProvider.getWebSocketContainer();
|
||||
|
||||
ClientSocket clientEndpoint = new ClientSocket();
|
||||
try(Session session = clientContainer.connectToServer(clientEndpoint, uri))
|
||||
try (Session session = clientContainer.connectToServer(clientEndpoint, uri))
|
||||
{
|
||||
session.getBasicRemote().sendText("hello world");
|
||||
}
|
||||
|
@ -188,11 +189,11 @@ public class WebSocketServerExamplesTest
|
|||
@Test
|
||||
public void testGetHttpSessionSocket() throws Exception
|
||||
{
|
||||
URI uri = URI.create("ws://localhost:"+connector.getLocalPort()+"/example");
|
||||
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/example");
|
||||
WebSocketContainer clientContainer = ContainerProvider.getWebSocketContainer();
|
||||
|
||||
ClientSocket clientEndpoint = new ClientSocket();
|
||||
try(Session session = clientContainer.connectToServer(clientEndpoint, uri))
|
||||
try (Session session = clientContainer.connectToServer(clientEndpoint, uri))
|
||||
{
|
||||
session.getBasicRemote().sendText("hello world");
|
||||
}
|
||||
|
|
|
@ -19,14 +19,10 @@
|
|||
package org.eclipse.jetty.websocket.javax.server.browser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.websocket.DeploymentException;
|
||||
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -37,7 +33,6 @@ import org.eclipse.jetty.servlet.ServletHolder;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServerContainer;
|
||||
import org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServletContainerInitializer;
|
||||
|
||||
/**
|
||||
|
@ -68,7 +63,6 @@ public class JsrBrowserDebugTool
|
|||
JsrBrowserDebugTool tool = new JsrBrowserDebugTool();
|
||||
tool.setupServer(port);
|
||||
tool.server.start();
|
||||
tool.server.dumpStdErr();
|
||||
LOG.info("Server available at {}", tool.server.getURI());
|
||||
tool.server.join();
|
||||
}
|
||||
|
@ -80,13 +74,10 @@ public class JsrBrowserDebugTool
|
|||
|
||||
private Server server;
|
||||
|
||||
private JavaxWebSocketServerContainer setupServer(int port)
|
||||
throws DeploymentException, ServletException, URISyntaxException, MalformedURLException, IOException
|
||||
private void setupServer(int port) throws URISyntaxException, IOException
|
||||
{
|
||||
server = new Server();
|
||||
|
||||
server.setDumpAfterStart(true);
|
||||
|
||||
HttpConfiguration httpConf = new HttpConfiguration();
|
||||
httpConf.setSendServerVersion(true);
|
||||
|
||||
|
@ -107,10 +98,9 @@ public class JsrBrowserDebugTool
|
|||
holder.setInitParameter("dirAllowed", "true");
|
||||
server.setHandler(context);
|
||||
|
||||
JavaxWebSocketServerContainer container = JavaxWebSocketServletContainerInitializer.configureContext(context);
|
||||
container.addEndpoint(JsrBrowserSocket.class);
|
||||
JavaxWebSocketServletContainerInitializer.configure(context,
|
||||
(servletContext, container) -> container.addEndpoint(JsrBrowserSocket.class));
|
||||
|
||||
LOG.info("{} setup on port {}", this.getClass().getName(), port);
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.eclipse.jetty.websocket.javax.tests;
|
|||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.websocket.OnMessage;
|
||||
|
@ -168,7 +167,7 @@ public class LocalServer extends ContainerLifeCycle implements LocalFuzzer.Provi
|
|||
{
|
||||
servletContextHandler = new ServletContextHandler(server, "/", true, false);
|
||||
servletContextHandler.setContextPath("/");
|
||||
serverContainer = JavaxWebSocketServletContainerInitializer.configureContext(servletContextHandler);
|
||||
JavaxWebSocketServletContainerInitializer.configure(servletContextHandler, null);
|
||||
serverContainer.addSessionListener(trackingListener);
|
||||
configureServletContextHandler(servletContextHandler);
|
||||
return servletContextHandler;
|
||||
|
@ -283,6 +282,15 @@ public class LocalServer extends ContainerLifeCycle implements LocalFuzzer.Provi
|
|||
|
||||
public ServerContainer getServerContainer()
|
||||
{
|
||||
if (!servletContextHandler.isRunning())
|
||||
{
|
||||
throw new IllegalStateException("Cannot access ServerContainer when ServletContextHandler isn't running");
|
||||
}
|
||||
|
||||
if (serverContainer == null)
|
||||
{
|
||||
serverContainer = (JavaxWebSocketServerContainer)servletContextHandler.getAttribute(JavaxWebSocketServerContainer.JAVAX_WEBSOCKET_CONTAINER_ATTRIBUTE);
|
||||
}
|
||||
return serverContainer;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,16 +21,12 @@ package org.eclipse.jetty.websocket.javax.tests.quotes;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.websocket.core.CloseStatus;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.core.OpCode;
|
||||
import org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServletContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.javax.tests.Fuzzer;
|
||||
import org.eclipse.jetty.websocket.javax.tests.LocalServer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
|
@ -69,16 +65,9 @@ public class QuotesDecoderTextStreamTest
|
|||
@BeforeAll
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
server = new LocalServer()
|
||||
{
|
||||
@Override
|
||||
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
|
||||
{
|
||||
ServerContainer container = JavaxWebSocketServletContainerInitializer.configureContext(context);
|
||||
container.addEndpoint(QuotesEchoStringSocket.class);
|
||||
}
|
||||
};
|
||||
server = new LocalServer();
|
||||
server.start();
|
||||
server.getServerContainer().addEndpoint(QuotesEchoStringSocket.class);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.eclipse.jetty.websocket.javax.tests.server;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.websocket.EndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -45,14 +44,14 @@ public abstract class AbstractJavaxWebSocketServerFrameHandlerTest
|
|||
server = new Server();
|
||||
context = new ServletContextHandler();
|
||||
server.setHandler(context);
|
||||
container = JavaxWebSocketServletContainerInitializer.configureContext(context);
|
||||
JavaxWebSocketServletContainerInitializer.configure(context, null);
|
||||
server.start();
|
||||
container = (JavaxWebSocketServerContainer)context.getServletContext().getAttribute(JavaxWebSocketServerContainer.JAVAX_WEBSOCKET_CONTAINER_ATTRIBUTE);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopContainer() throws Exception
|
||||
{
|
||||
container.stop();
|
||||
server.stop();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ package org.eclipse.jetty.websocket.javax.tests.server;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
|
@ -30,7 +30,6 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.websocket.javax.common.util.InvalidSignatureException;
|
||||
import org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServerContainer;
|
||||
import org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServletContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.javax.tests.server.sockets.InvalidCloseIntSocket;
|
||||
import org.eclipse.jetty.websocket.javax.tests.server.sockets.InvalidErrorErrorSocket;
|
||||
|
@ -98,14 +97,14 @@ public class DeploymentExceptionTest
|
|||
{
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setServer(server);
|
||||
JavaxWebSocketServerContainer container = JavaxWebSocketServletContainerInitializer.configureContext(context);
|
||||
context.addBean(container);
|
||||
JavaxWebSocketServletContainerInitializer.configure(context, null);
|
||||
|
||||
contexts.addHandler(context);
|
||||
try
|
||||
{
|
||||
context.start();
|
||||
Exception e = assertThrows(DeploymentException.class, () -> container.addEndpoint(pojo));
|
||||
ServerContainer serverContainer = (ServerContainer)context.getServletContext().getAttribute(ServerContainer.class.getName());
|
||||
Exception e = assertThrows(DeploymentException.class, () -> serverContainer.addEndpoint(pojo));
|
||||
assertThat(e.getCause(), instanceOf(InvalidSignatureException.class));
|
||||
}
|
||||
finally
|
||||
|
|
|
@ -24,14 +24,12 @@ import java.lang.management.MemoryUsage;
|
|||
import java.net.URI;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.websocket.ContainerProvider;
|
||||
import javax.websocket.Endpoint;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.MessageHandler;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -79,10 +77,12 @@ public class MemoryUsageTest
|
|||
connector = new ServerConnector(server);
|
||||
server.addConnector(connector);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler(server, "/", true, false);
|
||||
ServerContainer container = JavaxWebSocketServletContainerInitializer.configureContext(context);
|
||||
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(BasicEndpoint.class, "/").build();
|
||||
container.addEndpoint(config);
|
||||
ServletContextHandler contextHandler = new ServletContextHandler(server, "/", true, false);
|
||||
JavaxWebSocketServletContainerInitializer.configure(contextHandler, (context, container) ->
|
||||
{
|
||||
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(BasicEndpoint.class, "/").build();
|
||||
container.addEndpoint(config);
|
||||
});
|
||||
|
||||
server.start();
|
||||
|
||||
|
|
|
@ -21,21 +21,17 @@ package org.eclipse.jetty.websocket.javax.tests.server;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.websocket.OnError;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.core.CloseStatus;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.core.OpCode;
|
||||
import org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServletContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.javax.tests.Fuzzer;
|
||||
import org.eclipse.jetty.websocket.javax.tests.LocalServer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
|
@ -111,17 +107,10 @@ public class PartialEchoTest
|
|||
@BeforeAll
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
server = new LocalServer()
|
||||
{
|
||||
@Override
|
||||
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
|
||||
{
|
||||
ServerContainer container = JavaxWebSocketServletContainerInitializer.configureContext(context);
|
||||
container.addEndpoint(PartialTextSocket.class);
|
||||
container.addEndpoint(PartialTextSessionSocket.class);
|
||||
}
|
||||
};
|
||||
server = new LocalServer();
|
||||
server.start();
|
||||
server.getServerContainer().addEndpoint(PartialTextSocket.class);
|
||||
server.getServerContainer().addEndpoint(PartialTextSessionSocket.class);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.net.HttpURLConnection;
|
|||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -141,6 +140,12 @@ public class WebSocketServerContainerExecutorTest
|
|||
}
|
||||
}
|
||||
|
||||
private Executor getJavaxServerContainerExecutor(ServletContextHandler servletContextHandler)
|
||||
{
|
||||
JavaxWebSocketServerContainer serverContainer = (JavaxWebSocketServerContainer)servletContextHandler.getServletContext().getAttribute(JavaxWebSocketServerContainer.JAVAX_WEBSOCKET_CONTAINER_ATTRIBUTE);
|
||||
return serverContainer.getExecutor();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientExecutor() throws Exception
|
||||
{
|
||||
|
@ -160,15 +165,16 @@ public class WebSocketServerContainerExecutorTest
|
|||
|
||||
// Using JSR356 Server Techniques to connectToServer()
|
||||
contextHandler.addServlet(ServerConnectServlet.class, "/connect");
|
||||
javax.websocket.server.ServerContainer container = JavaxWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
container.addEndpoint(EchoSocket.class);
|
||||
JavaxWebSocketServletContainerInitializer.configure(contextHandler, (context, container) ->
|
||||
container.addEndpoint(EchoSocket.class));
|
||||
|
||||
try
|
||||
{
|
||||
server.start();
|
||||
String response = GET(server.getURI().resolve("/connect"));
|
||||
assertThat("Response", response, startsWith("Connected to ws://"));
|
||||
|
||||
Executor containerExecutor = ((JavaxWebSocketServerContainer)container).getExecutor();
|
||||
Executor containerExecutor = getJavaxServerContainerExecutor(contextHandler);
|
||||
assertThat(containerExecutor, sameInstance(executor));
|
||||
}
|
||||
finally
|
||||
|
@ -189,15 +195,15 @@ public class WebSocketServerContainerExecutorTest
|
|||
|
||||
// Using JSR356 Server Techniques to connectToServer()
|
||||
contextHandler.addServlet(ServerConnectServlet.class, "/connect");
|
||||
javax.websocket.server.ServerContainer container = JavaxWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
container.addEndpoint(EchoSocket.class);
|
||||
JavaxWebSocketServletContainerInitializer.configure(contextHandler, (context, container) ->
|
||||
container.addEndpoint(EchoSocket.class));
|
||||
try
|
||||
{
|
||||
server.start();
|
||||
String response = GET(server.getURI().resolve("/connect"));
|
||||
assertThat("Response", response, startsWith("Connected to ws://"));
|
||||
|
||||
Executor containerExecutor = ((JavaxWebSocketServerContainer)container).getExecutor();
|
||||
Executor containerExecutor = getJavaxServerContainerExecutor(contextHandler);
|
||||
assertThat(containerExecutor, sameInstance(executor));
|
||||
}
|
||||
finally
|
||||
|
|
|
@ -238,6 +238,7 @@ public interface RemoteEndpoint
|
|||
* Get the InetSocketAddress for the established connection.
|
||||
*
|
||||
* @return the InetSocketAddress for the established connection. (or null, if there is none)
|
||||
* @deprecated use {@link #getRemoteAddress()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
InetSocketAddress getInetSocketAddress();
|
||||
|
|
|
@ -19,13 +19,12 @@
|
|||
package org.eclipse.jetty.websocket.server.config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContainerInitializer;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.listener.ContainerInitializer;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketComponents;
|
||||
|
@ -40,7 +39,56 @@ public class JettyWebSocketServletContainerInitializer implements ServletContain
|
|||
{
|
||||
private static final Logger LOG = Log.getLogger(JettyWebSocketServletContainerInitializer.class);
|
||||
|
||||
public static JettyWebSocketServerContainer configureContext(ServletContextHandler context)
|
||||
public interface Configurator
|
||||
{
|
||||
void accept(ServletContext servletContext, JettyWebSocketServerContainer container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ServletContextHandler} to call the {@link JettyWebSocketServletContainerInitializer}
|
||||
* during the {@link ServletContext} initialization phase.
|
||||
*
|
||||
* @param context the context to add listener to.
|
||||
* @param configurator a lambda that is called to allow the {@link WebSocketMapping} to
|
||||
* be configured during {@link ServletContext} initialization phase
|
||||
*/
|
||||
public static void configure(ServletContextHandler context, Configurator configurator)
|
||||
{
|
||||
context.addEventListener(
|
||||
ContainerInitializer
|
||||
.asContextListener(new JettyWebSocketServletContainerInitializer())
|
||||
.afterStartup((servletContext) ->
|
||||
{
|
||||
if (configurator != null)
|
||||
{
|
||||
JettyWebSocketServerContainer container = (JettyWebSocketServerContainer)servletContext
|
||||
.getAttribute(JettyWebSocketServerContainer.JETTY_WEBSOCKET_CONTAINER_ATTRIBUTE);
|
||||
configurator.accept(servletContext, container);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately initialize the {@link ServletContextHandler} with the default {@link JettyWebSocketServerContainer}.
|
||||
*
|
||||
* <p>
|
||||
* This method is typically called from {@link #onStartup(Set, ServletContext)} itself or from
|
||||
* another dependent {@link ServletContainerInitializer} that requires minimal setup to
|
||||
* be performed.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method SHOULD NOT BE CALLED by users of Jetty.
|
||||
* Use the {@link #configure(ServletContextHandler, Configurator)} method instead.
|
||||
* </p>
|
||||
* <p>
|
||||
* This will return the default {@link JettyWebSocketServerContainer} if already initialized,
|
||||
* and not create a new {@link JettyWebSocketServerContainer} each time it is called.
|
||||
* </p>
|
||||
*
|
||||
* @param context the context to work with
|
||||
* @return the default {@link JettyWebSocketServerContainer}
|
||||
*/
|
||||
public static JettyWebSocketServerContainer initialize(ServletContextHandler context)
|
||||
{
|
||||
WebSocketComponents components = WebSocketComponents.ensureWebSocketComponents(context.getServletContext());
|
||||
FilterHolder filterHolder = WebSocketUpgradeFilter.ensureFilter(context.getServletContext());
|
||||
|
@ -54,9 +102,9 @@ public class JettyWebSocketServletContainerInitializer implements ServletContain
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onStartup(Set<Class<?>> c, ServletContext context) throws ServletException
|
||||
public void onStartup(Set<Class<?>> c, ServletContext context)
|
||||
{
|
||||
ServletContextHandler contextHandler = ServletContextHandler.getServletContextHandler(context,"Jetty WebSocket SCI");
|
||||
JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
ServletContextHandler contextHandler = ServletContextHandler.getServletContextHandler(context, "Jetty WebSocket SCI");
|
||||
JettyWebSocketServletContainerInitializer.initialize(contextHandler);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,10 @@
|
|||
package org.eclipse.jetty.websocket.server.browser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -92,7 +90,8 @@ public class BrowserDebugTool
|
|||
return connector.getLocalPort();
|
||||
}
|
||||
|
||||
public void prepare(int port) throws IOException, URISyntaxException {
|
||||
public void prepare(int port)
|
||||
{
|
||||
server = new Server();
|
||||
connector = new ServerConnector(server);
|
||||
connector.setPort(port);
|
||||
|
@ -100,7 +99,7 @@ public class BrowserDebugTool
|
|||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
|
||||
JettyWebSocketServletContainerInitializer.configureContext(context);
|
||||
JettyWebSocketServletContainerInitializer.configure(context, null);
|
||||
|
||||
context.setContextPath("/");
|
||||
Resource staticResourceBase = findStaticResources();
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebSocket(maxTextMessageSize = 100*1024)
|
||||
public class AnnoMaxMessageEndpoint
|
||||
{
|
||||
@OnWebSocketMessage
|
||||
public void onMessage(Session session, String msg) throws IOException
|
||||
{
|
||||
session.getRemote().sendString(msg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebSocket
|
||||
public class ConnectMessageEndpoint
|
||||
{
|
||||
@OnWebSocketConnect
|
||||
public void onConnect(Session session) throws IOException
|
||||
{
|
||||
session.getRemote().sendString("Greeting from onConnect");
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
|
|||
import org.eclipse.jetty.websocket.api.WriteCallback;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebSocket
|
||||
public class EchoSocket extends EventSocket
|
||||
{
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebSocket
|
||||
public class GetAuthHeaderEndpoint
|
||||
{
|
||||
@OnWebSocketConnect
|
||||
public void onConnect(Session session) throws IOException
|
||||
{
|
||||
String authHeaderName = "Authorization";
|
||||
String authHeaderValue = session.getUpgradeRequest().getHeader(authHeaderName);
|
||||
session.getRemote().sendString("Header[" + authHeaderName + "]=" + authHeaderValue);
|
||||
}
|
||||
}
|
|
@ -36,7 +36,6 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
|||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.JettyUpgradeListener;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -66,25 +65,26 @@ public class JettyWebSocketExtensionConfigTest
|
|||
contextHandler.setContextPath("/");
|
||||
server.setHandler(contextHandler);
|
||||
|
||||
JettyWebSocketServerContainer container = JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
container.addMapping("/", (req, resp)->
|
||||
{
|
||||
assertEquals(req.getExtensions().stream().filter(e -> e.getName().equals("permessage-deflate")).count(), 1);
|
||||
assertEquals(resp.getExtensions().stream().filter(e -> e.getName().equals("permessage-deflate")).count(), 1);
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler,
|
||||
(context, container) -> container.addMapping("/", (req, resp) ->
|
||||
{
|
||||
assertEquals(req.getExtensions().stream().filter(e -> e.getName().equals("permessage-deflate")).count(), 1);
|
||||
assertEquals(resp.getExtensions().stream().filter(e -> e.getName().equals("permessage-deflate")).count(), 1);
|
||||
|
||||
ExtensionConfig nonRequestedExtension = ExtensionConfig.parse("identity");
|
||||
assertNotNull(nonRequestedExtension);
|
||||
ExtensionConfig nonRequestedExtension = ExtensionConfig.parse("identity");
|
||||
assertNotNull(nonRequestedExtension);
|
||||
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
()->resp.setExtensions(List.of(nonRequestedExtension)),
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> resp.setExtensions(List.of(nonRequestedExtension)),
|
||||
"should not allow extensions not requested");
|
||||
|
||||
// Check identity extension was not added because it was not requested
|
||||
assertEquals(resp.getExtensions().stream().filter(config -> config.getName().equals("identity")).count(), 0);
|
||||
assertEquals(resp.getExtensions().stream().filter(e -> e.getName().equals("permessage-deflate")).count(), 1);
|
||||
// Check identity extension was not added because it was not requested
|
||||
assertEquals(resp.getExtensions().stream().filter(config -> config.getName().equals("identity")).count(), 0);
|
||||
assertEquals(resp.getExtensions().stream().filter(e -> e.getName().equals("permessage-deflate")).count(), 1);
|
||||
|
||||
return new EchoSocket();
|
||||
}));
|
||||
|
||||
return new EchoSocket();
|
||||
});
|
||||
server.start();
|
||||
|
||||
client = new WebSocketClient();
|
||||
|
@ -101,7 +101,7 @@ public class JettyWebSocketExtensionConfigTest
|
|||
@Test
|
||||
public void testJettyExtensionConfig() throws Exception
|
||||
{
|
||||
URI uri = URI.create("ws://localhost:"+connector.getLocalPort()+"/filterPath");
|
||||
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/filterPath");
|
||||
EventSocket socket = new EventSocket();
|
||||
|
||||
UpgradeRequest request = new ClientUpgradeRequest();
|
||||
|
@ -115,7 +115,7 @@ public class JettyWebSocketExtensionConfigTest
|
|||
{
|
||||
|
||||
String extensions = response.getHeaders().get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS);
|
||||
if("permessage-deflate".equals(extensions))
|
||||
if ("permessage-deflate".equals(extensions))
|
||||
correctResponseExtensions.countDown();
|
||||
else
|
||||
throw new IllegalStateException("Unexpected Negotiated Extensions: " + extensions);
|
||||
|
@ -123,7 +123,7 @@ public class JettyWebSocketExtensionConfigTest
|
|||
};
|
||||
|
||||
CompletableFuture<Session> connect = client.connect(socket, uri, request, listener);
|
||||
try(Session session = connect.get(5, TimeUnit.SECONDS))
|
||||
try (Session session = connect.get(5, TimeUnit.SECONDS))
|
||||
{
|
||||
session.getRemote().sendString("hello world");
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.eclipse.jetty.server.ServerConnector;
|
|||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -54,8 +53,8 @@ public class JettyWebSocketFilterTest
|
|||
contextHandler.setContextPath("/");
|
||||
server.setHandler(contextHandler);
|
||||
|
||||
JettyWebSocketServerContainer container = JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
container.addMapping("/", (req, resp)->new EchoSocket());
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler, (context, container) ->
|
||||
container.addMapping("/", (req, resp) -> new EchoSocket()));
|
||||
server.start();
|
||||
|
||||
client = new WebSocketClient();
|
||||
|
|
|
@ -32,7 +32,6 @@ import org.eclipse.jetty.websocket.api.Session;
|
|||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -75,8 +74,9 @@ public class JettyWebSocketNegotiationTest
|
|||
@Test
|
||||
public void testBadRequest() throws Exception
|
||||
{
|
||||
JettyWebSocketServerContainer container = JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
container.addMapping("/", (req, resp)->new EchoSocket());
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler,
|
||||
(context, container) -> container.addMapping("/", (req, resp)->new EchoSocket()));
|
||||
|
||||
|
||||
URI uri = URI.create("ws://localhost:"+connector.getLocalPort()+"/filterPath");
|
||||
EventSocket socket = new EventSocket();
|
||||
|
@ -93,12 +93,12 @@ public class JettyWebSocketNegotiationTest
|
|||
@Test
|
||||
public void testServerError() throws Exception
|
||||
{
|
||||
JettyWebSocketServerContainer container = JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
container.addMapping("/", (req, resp)->
|
||||
{
|
||||
resp.setAcceptedSubProtocol("errorSubProtocol");
|
||||
return new EchoSocket();
|
||||
});
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler, (context, container) ->
|
||||
container.addMapping("/", (req, resp) ->
|
||||
{
|
||||
resp.setAcceptedSubProtocol("errorSubProtocol");
|
||||
return new EchoSocket();
|
||||
}));
|
||||
|
||||
URI uri = URI.create("ws://localhost:"+connector.getLocalPort()+"/filterPath");
|
||||
EventSocket socket = new EventSocket();
|
||||
|
|
|
@ -66,7 +66,7 @@ public class JettyWebSocketServletTest
|
|||
|
||||
contextHandler.addServlet(MyWebSocketServlet.class, "/servletPath");
|
||||
|
||||
JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler, null);
|
||||
server.start();
|
||||
|
||||
client = new WebSocketClient();
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebSocket
|
||||
public class ParamsEndpoint
|
||||
{
|
||||
@OnWebSocketConnect
|
||||
public void onConnect(Session session) throws IOException
|
||||
{
|
||||
Map<String, List<String>> params = session.getUpgradeRequest().getParameterMap();
|
||||
StringBuilder msg = new StringBuilder();
|
||||
|
||||
for (String key : params.keySet())
|
||||
{
|
||||
msg.append("Params[").append(key).append("]=");
|
||||
msg.append(params.get(key).stream().collect(Collectors.joining(", ", "[", "]")));
|
||||
msg.append("\n");
|
||||
}
|
||||
|
||||
session.getRemote().sendString(msg.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class SimpleStatusServlet extends HttpServlet
|
||||
{
|
||||
private final int statusCode;
|
||||
|
||||
public SimpleStatusServlet(int statusCode)
|
||||
{
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
resp.setStatus(this.statusCode);
|
||||
}
|
||||
}
|
|
@ -85,7 +85,7 @@ public class SuspendResumeTest
|
|||
server.setHandler(contextHandler);
|
||||
contextHandler.addServlet(new ServletHolder(new UpgradeServlet()), "/suspend");
|
||||
|
||||
JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler, null);
|
||||
|
||||
server.start();
|
||||
client.start();
|
||||
|
|
|
@ -73,7 +73,7 @@ public class WebSocketServletExamplesTest
|
|||
_context.addServlet(MyAdvancedEchoServlet.class, "/advancedEcho");
|
||||
_context.addServlet(MyAuthedServlet.class, "/authed");
|
||||
|
||||
JettyWebSocketServletContainerInitializer.configureContext(_context);
|
||||
JettyWebSocketServletContainerInitializer.configure(_context, null);
|
||||
_server.start();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.eclipse.jetty.server.ServerConnector;
|
|||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.core.OpCode;
|
||||
|
@ -97,7 +96,7 @@ public class WebSocketStatsTest
|
|||
contextHandler.addServlet(MyWebSocketServlet.class, "/testPath");
|
||||
server.setHandler(contextHandler);
|
||||
|
||||
JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler, null);
|
||||
client = new WebSocketClient();
|
||||
|
||||
server.start();
|
||||
|
|
|
@ -90,7 +90,7 @@ public class BadNetworkTest
|
|||
handlers.addHandler(context);
|
||||
handlers.addHandler(new DefaultHandler());
|
||||
server.setHandler(handlers);
|
||||
JettyWebSocketServletContainerInitializer.configureContext(context);
|
||||
JettyWebSocketServletContainerInitializer.configure(context, null);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ public class ClientCloseTest
|
|||
handlers.addHandler(context);
|
||||
handlers.addHandler(new DefaultHandler());
|
||||
server.setHandler(handlers);
|
||||
JettyWebSocketServletContainerInitializer.configureContext(context);
|
||||
JettyWebSocketServletContainerInitializer.configure(context, null);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.eclipse.jetty.websocket.client.WebSocketClient;
|
|||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.tests.EchoSocket;
|
||||
import org.eclipse.jetty.websocket.tests.EventSocket;
|
||||
|
@ -83,8 +82,9 @@ public class ClientConfigTest
|
|||
contextHandler.setContextPath("/");
|
||||
server.setHandler(contextHandler);
|
||||
|
||||
JettyWebSocketServerContainer container = JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
container.addMapping("/", (req, resp)->serverSocket);
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler,
|
||||
(context, container) -> container.addMapping("/", (req, resp) -> serverSocket));
|
||||
|
||||
server.start();
|
||||
|
||||
client = new WebSocketClient();
|
||||
|
|
|
@ -0,0 +1,399 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.client;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.EnumSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeException;
|
||||
import org.eclipse.jetty.websocket.api.util.WSURI;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter;
|
||||
import org.eclipse.jetty.websocket.tests.CloseTrackingEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.EchoSocket;
|
||||
import org.eclipse.jetty.websocket.tests.GetAuthHeaderEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleStatusServlet;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* Various connect condition testing
|
||||
*/
|
||||
@SuppressWarnings("Duplicates")
|
||||
public class ClientConnectTest
|
||||
{
|
||||
private Server server;
|
||||
private WebSocketClient client;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <E extends Throwable> E assertExpectedError(ExecutionException e, CloseTrackingEndpoint wsocket, Matcher<Throwable> errorMatcher)
|
||||
{
|
||||
// Validate thrown cause
|
||||
Throwable cause = e.getCause();
|
||||
|
||||
assertThat("ExecutionException.cause", cause, errorMatcher);
|
||||
|
||||
// Validate websocket captured cause
|
||||
Throwable capcause = wsocket.error.get();
|
||||
assertThat("Error", capcause, notNullValue());
|
||||
assertThat("Error", capcause, errorMatcher);
|
||||
|
||||
// Validate that websocket didn't see an open event
|
||||
assertThat("Open Latch", wsocket.openLatch.getCount(), is(1L));
|
||||
|
||||
// Return the captured cause
|
||||
return (E)capcause;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.setConnectTimeout(TimeUnit.SECONDS.toMillis(3));
|
||||
client.setIdleTimeout(Duration.ofSeconds(10));
|
||||
client.start();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
|
||||
ServerConnector connector = new ServerConnector(server);
|
||||
connector.setPort(0);
|
||||
server.addConnector(connector);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
|
||||
JettyWebSocketServletContainerInitializer.configure(context,
|
||||
(servletContext, configuration) ->
|
||||
{
|
||||
configuration.setIdleTimeout(Duration.ofSeconds(10));
|
||||
configuration.addMapping("/echo", (req, resp) ->
|
||||
{
|
||||
if (req.hasSubProtocol("echo"))
|
||||
resp.setAcceptedSubProtocol("echo");
|
||||
return new EchoSocket();
|
||||
});
|
||||
configuration.addMapping("/get-auth-header", (req, resp) -> new GetAuthHeaderEndpoint());
|
||||
});
|
||||
|
||||
context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
|
||||
context.addServlet(new ServletHolder(new SimpleStatusServlet(404)), "/bogus");
|
||||
context.addServlet(new ServletHolder(new SimpleStatusServlet(200)), "/a-okay");
|
||||
context.addServlet(new ServletHolder(new InvalidUpgradeServlet()), "/invalid-upgrade/*");
|
||||
|
||||
server.setHandler(context);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpgradeRequest() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
client.setIdleTimeout(Duration.ofSeconds(10));
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/echo"));
|
||||
ClientUpgradeRequest request = new ClientUpgradeRequest();
|
||||
request.setSubProtocols("echo");
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
try (Session sess = future.get(30, TimeUnit.SECONDS))
|
||||
{
|
||||
assertThat("Connect.UpgradeRequest", sess.getUpgradeRequest(), notNullValue());
|
||||
assertThat("Connect.UpgradeResponse", sess.getUpgradeResponse(), notNullValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpgradeWithAuthorizationHeader() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/get-auth-header"));
|
||||
ClientUpgradeRequest request = new ClientUpgradeRequest();
|
||||
// actual value for this test is irrelevant, its important that this
|
||||
// header actually be sent with a value (the value specified)
|
||||
String authHeaderValue = "Basic YWxhZGRpbjpvcGVuc2VzYW1l";
|
||||
request.setHeader("Authorization", authHeaderValue);
|
||||
Future<Session> future = client.connect(cliSock, wsUri, request);
|
||||
|
||||
try (Session sess = future.get(5, TimeUnit.SECONDS))
|
||||
{
|
||||
// Test client side
|
||||
String cliAuthValue = sess.getUpgradeRequest().getHeader("Authorization");
|
||||
assertThat("Client Request Authorization Value", cliAuthValue, is(authHeaderValue));
|
||||
|
||||
// wait for response from server
|
||||
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Message", received, containsString("Header[Authorization]=" + authHeaderValue));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHandshake() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/bogus"));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
// The attempt to get upgrade response future should throw error
|
||||
ExecutionException e = assertThrows(ExecutionException.class,
|
||||
() -> future.get(5, TimeUnit.SECONDS));
|
||||
|
||||
UpgradeException ue = assertExpectedError(e, cliSock, instanceOf(UpgradeException.class));
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI(), notNullValue());
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI().toASCIIString(), is(wsUri.toASCIIString()));
|
||||
assertThat("UpgradeException.responseStatusCode", ue.getResponseStatusCode(), is(404));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHandshake_GetOK() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/a-okay"));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
// The attempt to get upgrade response future should throw error
|
||||
ExecutionException e = assertThrows(ExecutionException.class,
|
||||
() -> future.get(5, TimeUnit.SECONDS));
|
||||
|
||||
UpgradeException ue = assertExpectedError(e, cliSock, instanceOf(UpgradeException.class));
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI(), notNullValue());
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI().toASCIIString(), is(wsUri.toASCIIString()));
|
||||
assertThat("UpgradeException.responseStatusCode", ue.getResponseStatusCode(), is(200));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHandshake_GetOK_WithSecWebSocketAccept() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/invalid-upgrade/only-accept"));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
// The attempt to get upgrade response future should throw error
|
||||
ExecutionException e = assertThrows(ExecutionException.class,
|
||||
() -> future.get(5, TimeUnit.SECONDS));
|
||||
|
||||
UpgradeException ue = assertExpectedError(e, cliSock, instanceOf(UpgradeException.class));
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI(), notNullValue());
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI().toASCIIString(), is(wsUri.toASCIIString()));
|
||||
assertThat("UpgradeException.responseStatusCode", ue.getResponseStatusCode(), is(200));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHandshake_SwitchingProtocols_InvalidConnectionHeader() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/invalid-upgrade/close-connection"));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
// The attempt to get upgrade response future should throw error
|
||||
ExecutionException e = assertThrows(ExecutionException.class,
|
||||
() -> future.get(5, TimeUnit.SECONDS));
|
||||
|
||||
UpgradeException ue = assertExpectedError(e, cliSock, instanceOf(UpgradeException.class));
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI(), notNullValue());
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI().toASCIIString(), is(wsUri.toASCIIString()));
|
||||
assertThat("UpgradeException.responseStatusCode", ue.getResponseStatusCode(), is(101));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHandshake_SwitchingProtocols_NoConnectionHeader() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/invalid-upgrade/missing-connection"));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
// The attempt to get upgrade response future should throw error
|
||||
ExecutionException e = assertThrows(ExecutionException.class,
|
||||
() -> future.get(5, TimeUnit.SECONDS));
|
||||
|
||||
UpgradeException ue = assertExpectedError(e, cliSock, instanceOf(UpgradeException.class));
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI(), notNullValue());
|
||||
assertThat("UpgradeException.requestURI", ue.getRequestURI().toASCIIString(), is(wsUri.toASCIIString()));
|
||||
assertThat("UpgradeException.responseStatusCode", ue.getResponseStatusCode(), is(101));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadUpgrade() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/invalid-upgrade/rubbish-accept"));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
// The attempt to get upgrade response future should throw error
|
||||
ExecutionException e = assertThrows(ExecutionException.class,
|
||||
() -> future.get(5, TimeUnit.SECONDS));
|
||||
|
||||
UpgradeException ue = assertExpectedError(e, cliSock, instanceOf(UpgradeException.class));
|
||||
assertThat("UpgradeException.responseStatusCode", ue.getResponseStatusCode(), is(101));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionNotAccepted() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
try (ServerSocket serverSocket = new ServerSocket())
|
||||
{
|
||||
InetAddress addr = InetAddress.getByName("localhost");
|
||||
InetSocketAddress endpoint = new InetSocketAddress(addr, 0);
|
||||
serverSocket.bind(endpoint, 1);
|
||||
int port = serverSocket.getLocalPort();
|
||||
|
||||
URI wsUri = URI.create(String.format("ws://%s:%d/", addr.getHostAddress(), port));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
// Intentionally not accept incoming socket.
|
||||
// serverSocket.accept();
|
||||
|
||||
try
|
||||
{
|
||||
future.get(8, TimeUnit.SECONDS);
|
||||
fail("Should have Timed Out");
|
||||
}
|
||||
catch (ExecutionException e)
|
||||
{
|
||||
// Passing Path (active session wait timeout)
|
||||
assertExpectedError(e, cliSock, instanceOf(UpgradeException.class));
|
||||
}
|
||||
catch (TimeoutException e)
|
||||
{
|
||||
// Passing Path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionRefused() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
// Intentionally bad port with nothing listening on it
|
||||
URI wsUri = new URI("ws://127.0.0.1:1");
|
||||
|
||||
try
|
||||
{
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
// The attempt to get upgrade response future should throw error
|
||||
future.get(5, TimeUnit.SECONDS);
|
||||
fail("Expected ExecutionException -> ConnectException");
|
||||
}
|
||||
catch (ConnectException e)
|
||||
{
|
||||
Throwable t = cliSock.error.get();
|
||||
assertThat("Error Queue[0]", t, instanceOf(ConnectException.class));
|
||||
}
|
||||
catch (ExecutionException e)
|
||||
{
|
||||
assertExpectedError(e, cliSock,
|
||||
anyOf(
|
||||
instanceOf(UpgradeException.class),
|
||||
instanceOf(SocketTimeoutException.class),
|
||||
instanceOf(ConnectException.class)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionTimeout_Concurrent() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
try (ServerSocket serverSocket = new ServerSocket())
|
||||
{
|
||||
InetAddress addr = InetAddress.getByName("localhost");
|
||||
InetSocketAddress endpoint = new InetSocketAddress(addr, 0);
|
||||
serverSocket.bind(endpoint, 1);
|
||||
int port = serverSocket.getLocalPort();
|
||||
URI wsUri = URI.create(String.format("ws://%s:%d/", addr.getHostAddress(), port));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
// Accept the connection, but do nothing on it (no response, no upgrade, etc)
|
||||
serverSocket.accept();
|
||||
|
||||
// The attempt to get upgrade response future should throw error
|
||||
Exception e = assertThrows(Exception.class,
|
||||
() -> future.get(5, TimeUnit.SECONDS));
|
||||
|
||||
if (e instanceof ExecutionException)
|
||||
{
|
||||
assertExpectedError((ExecutionException)e, cliSock, anyOf(
|
||||
instanceOf(ConnectException.class),
|
||||
instanceOf(UpgradeException.class)
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
assertThat("Should have been a TimeoutException", e, instanceOf(TimeoutException.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,7 +83,7 @@ public class ClientSessionsTest
|
|||
handlers.addHandler(context);
|
||||
handlers.addHandler(new DefaultHandler());
|
||||
server.setHandler(handlers);
|
||||
JettyWebSocketServletContainerInitializer.configureContext(context);
|
||||
JettyWebSocketServletContainerInitializer.configure(context, null);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.client;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketCore;
|
||||
|
||||
public class InvalidUpgradeServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
{
|
||||
String pathInfo = req.getPathInfo();
|
||||
if (pathInfo.contains("only-accept"))
|
||||
{
|
||||
// Force 200 response, no response body content, incomplete websocket response headers, no actual upgrade for this test
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
String key = req.getHeader(HttpHeader.SEC_WEBSOCKET_KEY.toString());
|
||||
resp.setHeader(HttpHeader.SEC_WEBSOCKET_ACCEPT.toString(), WebSocketCore.hashKey(key));
|
||||
}
|
||||
else if (pathInfo.contains("close-connection"))
|
||||
{
|
||||
// Force 101 response, with invalid Connection header, invalid handshake
|
||||
resp.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
|
||||
String key = req.getHeader(HttpHeader.SEC_WEBSOCKET_KEY.toString());
|
||||
resp.setHeader(HttpHeader.CONNECTION.toString(), "close");
|
||||
resp.setHeader(HttpHeader.SEC_WEBSOCKET_ACCEPT.toString(), WebSocketCore.hashKey(key));
|
||||
}
|
||||
else if (pathInfo.contains("missing-connection"))
|
||||
{
|
||||
// Force 101 response, with no Connection header, invalid handshake
|
||||
resp.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
|
||||
String key = req.getHeader(HttpHeader.SEC_WEBSOCKET_KEY.toString());
|
||||
// Intentionally leave out Connection header
|
||||
resp.setHeader(HttpHeader.SEC_WEBSOCKET_ACCEPT.toString(), WebSocketCore.hashKey(key));
|
||||
}
|
||||
else if (pathInfo.contains("rubbish-accept"))
|
||||
{
|
||||
// Force 101 response, with no Connection header, invalid handshake
|
||||
resp.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
|
||||
resp.setHeader(HttpHeader.SEC_WEBSOCKET_ACCEPT.toString(), "rubbish");
|
||||
}
|
||||
else
|
||||
{
|
||||
resp.setStatus(500);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -86,7 +86,7 @@ public class SlowClientTest
|
|||
handlers.addHandler(new DefaultHandler());
|
||||
|
||||
server.setHandler(handlers);
|
||||
JettyWebSocketServletContainerInitializer.configureContext(context);
|
||||
JettyWebSocketServletContainerInitializer.configure(context, null);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,333 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.client;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.util.WSURI;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter;
|
||||
import org.eclipse.jetty.websocket.tests.AnnoMaxMessageEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.CloseTrackingEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.ConnectMessageEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.EchoSocket;
|
||||
import org.eclipse.jetty.websocket.tests.ParamsEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.util.FutureWriteCallback;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class WebSocketClientTest
|
||||
{
|
||||
private Server server;
|
||||
private WebSocketClient client;
|
||||
|
||||
@BeforeEach
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
|
||||
ServerConnector connector = new ServerConnector(server);
|
||||
connector.setPort(0);
|
||||
server.addConnector(connector);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
|
||||
JettyWebSocketServletContainerInitializer.configure(context,
|
||||
(servletContext, configuration) ->
|
||||
{
|
||||
configuration.setIdleTimeout(Duration.ofSeconds(10));
|
||||
configuration.addMapping("/echo", (req, resp) ->
|
||||
{
|
||||
if (req.hasSubProtocol("echo"))
|
||||
resp.setAcceptedSubProtocol("echo");
|
||||
return new EchoSocket();
|
||||
});
|
||||
configuration.addMapping("/anno-max-message", (req, resp) -> new AnnoMaxMessageEndpoint());
|
||||
configuration.addMapping("/connect-msg", (req, resp) -> new ConnectMessageEndpoint());
|
||||
configuration.addMapping("/get-params", (req, resp) -> new ParamsEndpoint());
|
||||
});
|
||||
|
||||
context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
|
||||
server.setHandler(context);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddExtension_NotInstalled() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
client.setIdleTimeout(Duration.ofSeconds(10));
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/echo"));
|
||||
ClientUpgradeRequest request = new ClientUpgradeRequest();
|
||||
request.setSubProtocols("echo");
|
||||
request.addExtensions("x-bad");
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
{
|
||||
// Should trigger failure on bad extension
|
||||
client.connect(cliSock, wsUri, request);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicEcho_FromClient() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
client.setIdleTimeout(Duration.ofSeconds(10));
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/echo"));
|
||||
ClientUpgradeRequest request = new ClientUpgradeRequest();
|
||||
request.setSubProtocols("echo");
|
||||
Future<Session> future = client.connect(cliSock, wsUri, request);
|
||||
|
||||
try (Session sess = future.get(30, TimeUnit.SECONDS))
|
||||
{
|
||||
assertThat("Session", sess, notNullValue());
|
||||
assertThat("Session.open", sess.isOpen(), is(true));
|
||||
assertThat("Session.upgradeRequest", sess.getUpgradeRequest(), notNullValue());
|
||||
assertThat("Session.upgradeResponse", sess.getUpgradeResponse(), notNullValue());
|
||||
|
||||
Collection<Session> sessions = client.getOpenSessions();
|
||||
assertThat("client.sessions.size", sessions.size(), is(1));
|
||||
|
||||
RemoteEndpoint remote = cliSock.getSession().getRemote();
|
||||
remote.sendString("Hello World!");
|
||||
|
||||
// wait for response from server
|
||||
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Message", received, containsString("Hello World"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicEcho_UsingCallback() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
client.setIdleTimeout(Duration.ofSeconds(10));
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/echo"));
|
||||
ClientUpgradeRequest request = new ClientUpgradeRequest();
|
||||
request.setSubProtocols("echo");
|
||||
Future<Session> future = client.connect(cliSock, wsUri, request);
|
||||
|
||||
try (Session sess = future.get(5, TimeUnit.SECONDS))
|
||||
{
|
||||
assertThat("Session", sess, notNullValue());
|
||||
assertThat("Session.open", sess.isOpen(), is(true));
|
||||
assertThat("Session.upgradeRequest", sess.getUpgradeRequest(), notNullValue());
|
||||
assertThat("Session.upgradeResponse", sess.getUpgradeResponse(), notNullValue());
|
||||
|
||||
Collection<Session> sessions = client.getOpenSessions();
|
||||
assertThat("client.sessions.size", sessions.size(), is(1));
|
||||
|
||||
FutureWriteCallback callback = new FutureWriteCallback();
|
||||
|
||||
cliSock.getSession().getRemote().sendString("Hello World!", callback);
|
||||
callback.get(5, TimeUnit.SECONDS);
|
||||
|
||||
// wait for response from server
|
||||
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Message", received, containsString("Hello World"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicEcho_FromServer() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
client.setIdleTimeout(Duration.ofSeconds(10));
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/connect-msg"));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
try (Session sess = future.get(5, TimeUnit.SECONDS))
|
||||
{
|
||||
// Validate connect
|
||||
assertThat("Session", sess, notNullValue());
|
||||
assertThat("Session.open", sess.isOpen(), is(true));
|
||||
assertThat("Session.upgradeRequest", sess.getUpgradeRequest(), notNullValue());
|
||||
assertThat("Session.upgradeResponse", sess.getUpgradeResponse(), notNullValue());
|
||||
|
||||
// wait for message from server
|
||||
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Message", received, containsString("Greeting from onConnect"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalRemoteAddress() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
client.setIdleTimeout(Duration.ofSeconds(10));
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/echo"));
|
||||
ClientUpgradeRequest request = new ClientUpgradeRequest();
|
||||
request.setSubProtocols("echo");
|
||||
Future<Session> future = client.connect(cliSock, wsUri, request);
|
||||
|
||||
try (Session sess = future.get(5, TimeUnit.SECONDS))
|
||||
{
|
||||
Assertions.assertTrue(cliSock.openLatch.await(1, TimeUnit.SECONDS));
|
||||
|
||||
InetSocketAddress local = (InetSocketAddress)cliSock.getSession().getLocalAddress();
|
||||
InetSocketAddress remote = (InetSocketAddress)cliSock.getSession().getRemoteAddress();
|
||||
|
||||
assertThat("Local Socket Address", local, notNullValue());
|
||||
assertThat("Remote Socket Address", remote, notNullValue());
|
||||
|
||||
// Hard to validate (in a portable unit test) the local address that was used/bound in the low level Jetty Endpoint
|
||||
assertThat("Local Socket Address / Host", local.getAddress().getHostAddress(), notNullValue());
|
||||
assertThat("Local Socket Address / Port", local.getPort(), greaterThan(0));
|
||||
|
||||
String uriHostAddress = InetAddress.getByName(wsUri.getHost()).getHostAddress();
|
||||
assertThat("Remote Socket Address / Host", remote.getAddress().getHostAddress(), is(uriHostAddress));
|
||||
assertThat("Remote Socket Address / Port", remote.getPort(), greaterThan(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that <code>@WebSocket(maxTextMessageSize = 100*1024)</code> behaves as expected.
|
||||
*
|
||||
* @throws Exception on test failure
|
||||
*/
|
||||
@Test
|
||||
public void testMaxMessageSize() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
client.setMaxTextMessageSize(100 * 1024);
|
||||
client.setIdleTimeout(Duration.ofSeconds(10));
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/anno-max-message"));
|
||||
Future<Session> future = client.connect(cliSock, wsUri);
|
||||
|
||||
try (Session sess = future.get(5, TimeUnit.SECONDS))
|
||||
{
|
||||
assertThat("Session", sess, notNullValue());
|
||||
assertThat("Session.open", sess.isOpen(), is(true));
|
||||
|
||||
// Create string that is larger than default size of 64k
|
||||
// but smaller than maxMessageSize of 100k
|
||||
int size = 80 * 1024;
|
||||
byte buf[] = new byte[size];
|
||||
Arrays.fill(buf,(byte)'x');
|
||||
String msg = StringUtil.toUTF8String(buf,0,buf.length);
|
||||
|
||||
sess.getRemote().sendString(msg);
|
||||
|
||||
// wait for message from server
|
||||
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Message", received.length(), is(size));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameterMap() throws Exception
|
||||
{
|
||||
CloseTrackingEndpoint cliSock = new CloseTrackingEndpoint();
|
||||
|
||||
client.setMaxTextMessageSize(100 * 1024);
|
||||
client.setIdleTimeout(Duration.ofSeconds(10));
|
||||
|
||||
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/get-params?snack=cashews&amount=handful&brand=off"));
|
||||
ClientUpgradeRequest request = new ClientUpgradeRequest();
|
||||
Future<Session> future = client.connect(cliSock, wsUri, request);
|
||||
|
||||
try (Session sess = future.get(5, TimeUnit.SECONDS))
|
||||
{
|
||||
UpgradeRequest req = sess.getUpgradeRequest();
|
||||
assertThat("Upgrade Request", req, notNullValue());
|
||||
|
||||
Map<String, List<String>> parameterMap = req.getParameterMap();
|
||||
assertThat("Parameter Map", parameterMap, notNullValue());
|
||||
|
||||
assertThat("Parameter[snack]", parameterMap.get("snack"), is(Arrays.asList(new String[]{"cashews"})));
|
||||
assertThat("Parameter[amount]", parameterMap.get("amount"), is(Arrays.asList(new String[]{"handful"})));
|
||||
assertThat("Parameter[brand]", parameterMap.get("brand"), is(Arrays.asList(new String[]{"off"})));
|
||||
|
||||
assertThat("Parameter[cost]", parameterMap.get("cost"), nullValue());
|
||||
|
||||
// wait for message from server indicating what it sees
|
||||
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Parameter[snack]", received, containsString("Params[snack]=[cashews]"));
|
||||
assertThat("Parameter[amount]", received, containsString("Params[amount]=[handful]"));
|
||||
assertThat("Parameter[brand]", received, containsString("Params[brand]=[off]"));
|
||||
assertThat("Parameter[cost]", received, not(containsString("Params[cost]=")));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -89,7 +89,7 @@ public class ServerCloseTest
|
|||
handlers.addHandler(new DefaultHandler());
|
||||
|
||||
server.setHandler(handlers);
|
||||
JettyWebSocketServletContainerInitializer.configureContext(context);
|
||||
JettyWebSocketServletContainerInitializer.configure(context, null);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
|
|
@ -42,7 +42,6 @@ import org.eclipse.jetty.websocket.client.WebSocketClient;
|
|||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
|
@ -187,12 +186,14 @@ public class ServerConfigTest
|
|||
contextHandler.addServlet(new ServletHolder(new WebSocketSessionConfigServlet()), "/sessionConfig");
|
||||
server.setHandler(contextHandler);
|
||||
|
||||
JettyWebSocketServerContainer container = JettyWebSocketServletContainerInitializer.configureContext(contextHandler);
|
||||
container.setIdleTimeout(Duration.ofMillis(idleTimeout));
|
||||
container.setMaxTextMessageSize(maxMessageSize);
|
||||
container.setMaxBinaryMessageSize(maxMessageSize);
|
||||
container.setInputBufferSize(inputBufferSize);
|
||||
container.addMapping("/containerConfig", (req, resp)->standardEndpoint);
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler, (context, container) -> {
|
||||
container.setIdleTimeout(Duration.ofMillis(idleTimeout));
|
||||
container.setMaxTextMessageSize(maxMessageSize);
|
||||
container.setMaxBinaryMessageSize(maxMessageSize);
|
||||
container.setInputBufferSize(inputBufferSize);
|
||||
container.addMapping("/containerConfig", (req, resp)->standardEndpoint);
|
||||
});
|
||||
|
||||
server.start();
|
||||
|
||||
client = new WebSocketClient();
|
||||
|
|
|
@ -86,7 +86,7 @@ public class SlowServerTest
|
|||
handlers.addHandler(new DefaultHandler());
|
||||
|
||||
server.setHandler(handlers);
|
||||
JettyWebSocketServletContainerInitializer.configureContext(context);
|
||||
JettyWebSocketServletContainerInitializer.configure(context, null);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package org.eclipse.jetty.websocket.tests.util;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.eclipse.jetty.util.FutureCallback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WriteCallback;
|
||||
|
||||
/**
|
||||
* Allows events to a {@link WriteCallback} to drive a {@link Future} for the user.
|
||||
*/
|
||||
public class FutureWriteCallback extends FutureCallback implements WriteCallback
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(FutureWriteCallback.class);
|
||||
|
||||
@Override
|
||||
public void writeFailed(Throwable cause)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(".writeFailed",cause);
|
||||
failed(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSuccess()
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(".writeSuccess");
|
||||
succeeded();
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ package org.eclipse.jetty.websocket.servlet;
|
|||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
|
@ -90,6 +89,22 @@ public class WebSocketUpgradeFilter implements Filter, Dumpable
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the default WebSocketUpgradeFilter.
|
||||
*
|
||||
* <p>
|
||||
* This will return the default {@link WebSocketUpgradeFilter} on the
|
||||
* provided {@link ServletContext}, creating the filter if necessary.
|
||||
* </p>
|
||||
* <p>
|
||||
* The default {@link WebSocketUpgradeFilter} is also available via
|
||||
* the {@link ServletContext} attribute named {@code org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter}
|
||||
* </p>
|
||||
*
|
||||
* @param servletContext the {@link ServletContext} to use
|
||||
* @return the configured default {@link WebSocketUpgradeFilter} instance
|
||||
* @throws ServletException if the filer cannot be configured
|
||||
*/
|
||||
public static FilterHolder ensureFilter(ServletContext servletContext)
|
||||
{
|
||||
FilterHolder existingFilter = WebSocketUpgradeFilter.getFilter(servletContext);
|
||||
|
|
Loading…
Reference in New Issue