WebSocketUpgradeHandler should not require ContextHandler (#10768)

* WebSocketUpgradeHandler should not require a ContextHandler
* Exposing the ServerWebSocketContainer as attribute also when creating the WebSocketUpgradeHandler with only the Server, to allow dynamic configuration of WebSocket endpoints.

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
Co-authored-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
Lachlan 2023-11-21 05:30:19 +11:00 committed by GitHub
parent ecb90e8d0f
commit b8ece59544
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 212 additions and 172 deletions

View File

@ -18,7 +18,9 @@ import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.compression.DeflaterPool;
import org.eclipse.jetty.util.compression.InflaterPool;
@ -28,7 +30,7 @@ import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry;
/**
* A collection of components which are the resources needed for websockets such as
* {@link ByteBufferPool}, {@link WebSocketExtensionRegistry}, and {@link DecoratedObjectFactory}.
*
* <p>
* These components should be accessed through {@link WebSocketServerComponents#getWebSocketComponents} so that
* the instance can be shared by being stored as a bean on the ContextHandler.
*/
@ -62,28 +64,58 @@ public class WebSocketServerComponents extends WebSocketComponents
*/
public static WebSocketComponents ensureWebSocketComponents(Server server, ContextHandler contextHandler)
{
ContextHandler.ScopedContext context = contextHandler.getContext();
WebSocketComponents components = (WebSocketComponents)context.getAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE);
return ensureWebSocketComponents(server, contextHandler.getContext(), contextHandler);
}
/**
* <p>
* This ensures a {@link WebSocketComponents} is available on the {@link Server} attribute {@link #WEBSOCKET_COMPONENTS_ATTRIBUTE}.
* </p>
* <p>
* This should be called when the server is starting.
* </p>
* <p>
* Server attributes can be set with {@link #WEBSOCKET_BUFFER_POOL_ATTRIBUTE}, {@link #WEBSOCKET_INFLATER_POOL_ATTRIBUTE}
* and {@link #WEBSOCKET_DEFLATER_POOL_ATTRIBUTE} to override the {@link ByteBufferPool}, {@link DeflaterPool} or
* {@link InflaterPool} used by the components, otherwise this will try to use the pools shared on the {@link Server}.
* </p>
* @param server the server.
* @return the WebSocketComponents that was created or found.
*/
public static WebSocketComponents ensureWebSocketComponents(Server server)
{
return ensureWebSocketComponents(server, server.getContext(), server);
}
/**
* @param server the server.
* @param attributes the attributes where the websocket components can be found.
* @param container the container to manage the lifecycle of the WebSocketComponents instance.
* @return the WebSocketComponents that was created or found.
*/
private static WebSocketComponents ensureWebSocketComponents(Server server, Attributes attributes, ContainerLifeCycle container)
{
WebSocketComponents components = (WebSocketComponents)attributes.getAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE);
if (components != null)
return components;
InflaterPool inflaterPool = (InflaterPool)context.getAttribute(WEBSOCKET_INFLATER_POOL_ATTRIBUTE);
InflaterPool inflaterPool = (InflaterPool)attributes.getAttribute(WEBSOCKET_INFLATER_POOL_ATTRIBUTE);
if (inflaterPool == null)
inflaterPool = InflaterPool.ensurePool(server);
DeflaterPool deflaterPool = (DeflaterPool)context.getAttribute(WEBSOCKET_DEFLATER_POOL_ATTRIBUTE);
DeflaterPool deflaterPool = (DeflaterPool)attributes.getAttribute(WEBSOCKET_DEFLATER_POOL_ATTRIBUTE);
if (deflaterPool == null)
deflaterPool = DeflaterPool.ensurePool(server);
ByteBufferPool bufferPool = (ByteBufferPool)context.getAttribute(WEBSOCKET_BUFFER_POOL_ATTRIBUTE);
ByteBufferPool bufferPool = (ByteBufferPool)attributes.getAttribute(WEBSOCKET_BUFFER_POOL_ATTRIBUTE);
if (bufferPool == null)
bufferPool = server.getByteBufferPool();
Executor executor = (Executor)context.getAttribute("org.eclipse.jetty.server.Executor");
Executor executor = (Executor)attributes.getAttribute("org.eclipse.jetty.server.Executor");
if (executor == null)
executor = server.getThreadPool();
DecoratedObjectFactory objectFactory = (DecoratedObjectFactory)context.getAttribute(DecoratedObjectFactory.ATTR);
DecoratedObjectFactory objectFactory = (DecoratedObjectFactory)attributes.getAttribute(DecoratedObjectFactory.ATTR);
WebSocketComponents serverComponents = new WebSocketServerComponents(inflaterPool, deflaterPool, bufferPool, objectFactory, executor);
if (objectFactory != null)
serverComponents.unmanage(objectFactory);
@ -100,18 +132,18 @@ public class WebSocketServerComponents extends WebSocketComponents
serverComponents.unmanage(executor);
// Set to be managed as persistent attribute and bean on ContextHandler.
contextHandler.addManaged(serverComponents);
contextHandler.setAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE, serverComponents);
container.addManaged(serverComponents);
attributes.setAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE, serverComponents);
// Stop the WebSocketComponents when the ContextHandler stops and remove the WebSocketComponents attribute.
contextHandler.addEventListener(new LifeCycle.Listener()
container.addEventListener(new LifeCycle.Listener()
{
@Override
public void lifeCycleStopping(LifeCycle event)
{
contextHandler.removeAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE);
contextHandler.removeBean(serverComponents);
contextHandler.removeEventListener(this);
attributes.removeAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE);
container.removeBean(serverComponents);
container.removeEventListener(this);
}
@Override
@ -126,7 +158,17 @@ public class WebSocketServerComponents extends WebSocketComponents
public static WebSocketComponents getWebSocketComponents(ContextHandler contextHandler)
{
WebSocketComponents components = (WebSocketComponents)contextHandler.getAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE);
return getWebSocketComponents(contextHandler.getContext());
}
public static WebSocketComponents getWebSocketComponents(Server server)
{
return getWebSocketComponents(server.getContext());
}
private static WebSocketComponents getWebSocketComponents(Attributes attributes)
{
WebSocketComponents components = (WebSocketComponents)attributes.getAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE);
if (components == null)
throw new IllegalStateException("WebSocketComponents has not been created");

View File

@ -33,9 +33,14 @@ import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents;
* necessary for the upgrade (which vary upon the HTTP protocol version),
* otherwise the request handling is forwarded to the {@link Handler} child
* of this {@link Handler}.</p>
* {@link WebSocketUpgradeHandler} must be a {@link #getDescendant(Class)
* <p>{@code WebSocketUpgradeHandler} may be a {@link #getDescendant(Class)
* descendant} of a {@link ContextHandler}, typically as a direct child, but
* possibly also further down the handlers tree.
* possibly also further down the {@link Handler}'s tree, to enable WebSocket
* upgrades for that {@link ContextHandler} only.</p>
* <p>{@code WebSocketUpgradeHandler} may be a {@link #getDescendant(Class)
* descendant} of the {@link Server}, typically as a direct child, but
* possibly also further down the {@link Handler}'s tree, to enable WebSocket
* upgrades for possibly multiple {@link ContextHandler}s.</p>
* <p>Typical usage:</p>
* <pre>{@code
* Server server = ...;
@ -43,18 +48,15 @@ import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents;
* ContextHandler context = new ContextHandler("/app");
*
* // Create the WebSocketUpgradeHandler.
* WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context);
*
* // Link WebSocketUpgradeHandler as a child of ContextHandler.
* context.setHandler(wsHandler);
*
* // Configure the WebSocketUpgradeHandler.
* wsHandler.configure(container ->
* WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
* {
* // Map upgrade requests to "/app/ws" to an echo WebSocket endpoint.
* container.addMapping("/ws", (upgradeRequest, upgradeResponse, callback) -> new EchoEndPoint());
* });
*
* // Link WebSocketUpgradeHandler as a child of ContextHandler.
* context.setHandler(wsHandler);
*
* server.setHandler(context);
* server.start();
* }</pre>
@ -71,15 +73,16 @@ import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents;
public class WebSocketUpgradeHandler extends Handler.Wrapper
{
/**
* <p>Creates a new {@link WebSocketUpgradeHandler}.</p>
* <p>The {@link WebSocketUpgradeHandler} is not yet linked to the given
* <p>Creates a new {@code WebSocketUpgradeHandler}.</p>
* <p>The {@code WebSocketUpgradeHandler} is not yet linked to the given
* {@link ContextHandler}, therefore the caller code must ensure that
* the returned {@link WebSocketUpgradeHandler} is a descendant of the
* the returned {@code WebSocketUpgradeHandler} is a descendant of the
* given {@link ContextHandler}.</p>
*
* @param server the {@link Server} object used to lookup common WebSocket components
* @param context the {@link ContextHandler} ancestor of the returned {@link WebSocketUpgradeHandler}
* @return a new {@link WebSocketUpgradeHandler}
* @param context the {@link ContextHandler} ancestor of the returned {@code WebSocketUpgradeHandler}
* @return a new {@code WebSocketUpgradeHandler}
* @see #from(Server, ContextHandler, Consumer)
*/
public static WebSocketUpgradeHandler from(Server server, ContextHandler context)
{
@ -87,17 +90,20 @@ public class WebSocketUpgradeHandler extends Handler.Wrapper
}
/**
* <p>Creates a new {@link WebSocketUpgradeHandler}.</p>
* <p>The {@link WebSocketUpgradeHandler} is not yet linked to the given
* <p>Creates a new {@code WebSocketUpgradeHandler}.</p>
* <p>The {@code WebSocketUpgradeHandler} is not yet linked to the given
* {@link ContextHandler}, therefore the caller code must ensure that
* the returned {@link WebSocketUpgradeHandler} is a descendant of the
* the returned {@code WebSocketUpgradeHandler} is a descendant of the
* given {@link ContextHandler}.</p>
* <p>The configurator parameter is invoked every time this {@code WebSocketUpgradeHandler}
* is started, so that the endpoint configuration (removed during the
* stopping phase) can be re-applied upon restart.</p>
*
* @param server the {@link Server} object used to lookup common WebSocket components
* @param context the {@link ContextHandler} ancestor of the returned {@link WebSocketUpgradeHandler}
* @param context the {@link ContextHandler} ancestor of the returned {@code WebSocketUpgradeHandler}
* @param configurator a {@link Consumer} that is called to allow the {@link ServerWebSocketContainer} to
* be configured during the starting phase of the {@link WebSocketUpgradeHandler}.
* @return a new {@link WebSocketUpgradeHandler}
* be configured during the starting phase of the {@code WebSocketUpgradeHandler}
* @return a new {@code WebSocketUpgradeHandler}
*/
public static WebSocketUpgradeHandler from(Server server, ContextHandler context, Consumer<ServerWebSocketContainer> configurator)
{
@ -107,7 +113,49 @@ public class WebSocketUpgradeHandler extends Handler.Wrapper
container.addBean(mappings);
WebSocketUpgradeHandler wsHandler = new WebSocketUpgradeHandler(container, configurator);
context.getContext().setAttribute(WebSocketContainer.class.getName(), wsHandler._container);
context.getContext().setAttribute(WebSocketContainer.class.getName(), container);
return wsHandler;
}
/**
* <p>Creates a new {@code WebSocketUpgradeHandler}.</p>
* <p>The {@code WebSocketUpgradeHandler} is not yet linked to the given
* {@link Server}, therefore the caller code must ensure that
* the returned {@code WebSocketUpgradeHandler} is a descendant of the
* given {@link Server}.</p>
*
* @param server the {@link Server} object used to lookup common WebSocket components
* @return a new {@code WebSocketUpgradeHandler}
* @see #from(Server, Consumer)
*/
public static WebSocketUpgradeHandler from(Server server)
{
return from(server, container -> {});
}
/**
* <p>Creates a new {@code WebSocketUpgradeHandler}.</p>
* <p>The {@code WebSocketUpgradeHandler} is not yet linked to the given
* {@link Server}, therefore the caller code must ensure that
* the returned {@code WebSocketUpgradeHandler} is a descendant of the
* given {@link Server}.</p>
* <p>The configurator parameter is invoked every time this {@code WebSocketUpgradeHandler}
* is started, so that the endpoint configuration (removed during the
* stopping phase) can be re-applied upon restart.</p>
*
* @param server the {@link Server} object used to lookup common WebSocket components
* @param configurator a {@link Consumer} that is called to allow the {@link ServerWebSocketContainer} to
* be configured during the starting phase of the {@code WebSocketUpgradeHandler}
* @return a new {@code WebSocketUpgradeHandler}
*/
public static WebSocketUpgradeHandler from(Server server, Consumer<ServerWebSocketContainer> configurator)
{
WebSocketComponents components = WebSocketServerComponents.ensureWebSocketComponents(server);
WebSocketMappings mappings = new WebSocketMappings(components);
ServerWebSocketContainer container = new ServerWebSocketContainer(mappings);
WebSocketUpgradeHandler wsHandler = new WebSocketUpgradeHandler(container, configurator);
server.getContext().setAttribute(WebSocketContainer.class.getName(), container);
return wsHandler;
}
@ -115,9 +163,9 @@ public class WebSocketUpgradeHandler extends Handler.Wrapper
private final Consumer<ServerWebSocketContainer> _configurator;
/**
* <p>Creates a new {@link WebSocketUpgradeHandler} with the given {@link ServerWebSocketContainer}.</p>
* <p>Creates a new {@code WebSocketUpgradeHandler} with the given {@link ServerWebSocketContainer}.</p>
*
* @param container the {@link ServerWebSocketContainer} of this {@link WebSocketUpgradeHandler}
* @param container the {@link ServerWebSocketContainer} of this {@code WebSocketUpgradeHandler}
*/
public WebSocketUpgradeHandler(ServerWebSocketContainer container)
{
@ -125,13 +173,14 @@ public class WebSocketUpgradeHandler extends Handler.Wrapper
}
/**
* <p>Creates a new {@link WebSocketUpgradeHandler} with the given {@link ServerWebSocketContainer}
* <p>Creates a new {@code WebSocketUpgradeHandler} with the given {@link ServerWebSocketContainer}
* and the given configurator.</p>
* <p>The configurator is invoked every time this {@link WebSocketUpgradeHandler} is started,
* <p>The configurator is invoked every time this {@code WebSocketUpgradeHandler} is started,
* see {@link #from(Server, ContextHandler, Consumer)}.</p>
*
* @param container the {@link ServerWebSocketContainer} of this {@link WebSocketUpgradeHandler}
* @param configurator the code to configure the {@link ServerWebSocketContainer}
* @param container the {@link ServerWebSocketContainer} of this {@code WebSocketUpgradeHandler}
* @param configurator a {@link Consumer} that is called to allow the {@link ServerWebSocketContainer} to
* be configured during the starting phase of the {@code WebSocketUpgradeHandler}
*/
public WebSocketUpgradeHandler(ServerWebSocketContainer container, Consumer<ServerWebSocketContainer> configurator)
{
@ -142,12 +191,13 @@ public class WebSocketUpgradeHandler extends Handler.Wrapper
/**
* <p>Configures the {@link ServerWebSocketContainer} associated with this
* {@link WebSocketUpgradeHandler}.</p>
* <p>This configuration is applied immediately and lost after a server restart.</p>
* {@code WebSocketUpgradeHandler}.</p>
* <p>This configuration is applied immediately and lost after a restart.</p>
*
* @param configurator the configuration code
* @return this {@link WebSocketUpgradeHandler}
* @deprecated use {@link #getServerWebSocketContainer()} or {@link #from(Server, ContextHandler, Consumer)}.
* @return this {@code WebSocketUpgradeHandler}
* @deprecated use {@link #from(Server, ContextHandler, Consumer)},
* {@link #from(Server, Consumer)} or {@link #getServerWebSocketContainer()}
*/
@Deprecated
public WebSocketUpgradeHandler configure(Consumer<ServerWebSocketContainer> configurator)

View File

@ -21,7 +21,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
@ -54,13 +53,10 @@ public class ConcurrentConnectTest
connector.setPort(0);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
container.addMapping("/", (rq, rs, cb) -> new EchoSocket()));
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
uri = new URI("ws://localhost:" + connector.getLocalPort());

View File

@ -21,7 +21,6 @@ import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.JettyUpgradeListener;
@ -48,13 +47,10 @@ public class ConnectionHeaderTest
connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
container.addMapping("/echo", (rq, rs, cb) -> new EchoSocket()));
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client = new WebSocketClient();

View File

@ -24,7 +24,6 @@ import java.util.function.Consumer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
@ -52,13 +51,10 @@ public class DemandWithBlockingStreamsTest
{
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context);
context.setHandler(wsHandler);
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server);
configurer.accept(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client.start();

View File

@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.logging.StacklessLogging;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
@ -59,9 +58,7 @@ public class ErrorCloseTest
ServerConnector connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
{
container.addMapping("/", (rq, rs, cb) -> serverSocket);
container.addSessionListener(new WebSocketSessionListener()
@ -73,9 +70,8 @@ public class ErrorCloseTest
}
});
});
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
serverUri = new URI("ws://localhost:" + connector.getLocalPort() + "/");

View File

@ -20,7 +20,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@ -67,13 +66,10 @@ public class ExplicitDemandTest
connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
container.addMapping("/suspend", (rq, rs, cb) -> serverSocket));
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client.start();

View File

@ -18,7 +18,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@ -46,13 +45,10 @@ public class GracefulCloseTest
ServerConnector connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
container.addMapping("/", (rq, rs, cb) -> serverEndpoint));
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
serverUri = WSURI.toWebsocket(server.getURI());

View File

@ -20,7 +20,6 @@ import java.util.function.Consumer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
@ -95,13 +94,10 @@ public class JettyOnCloseTest
connector.setPort(0);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
container.addMapping("/", (rq, rs, cb) -> serverEndpoint));
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client = new WebSocketClient();

View File

@ -24,7 +24,6 @@ import org.eclipse.jetty.client.Response;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.ExtensionConfig;
import org.eclipse.jetty.websocket.api.Session;
@ -56,9 +55,7 @@ public class JettyWebSocketExtensionConfigTest
connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
container.addMapping("/", (rq, rs, cb) ->
{
assertEquals(rq.getExtensions().stream().filter(e -> e.getName().equals("permessage-deflate")).count(), 1);
@ -77,9 +74,8 @@ public class JettyWebSocketExtensionConfigTest
return new EchoSocket();
}));
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client = new WebSocketClient();

View File

@ -26,7 +26,6 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.logging.StacklessLogging;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.internal.HttpChannelState;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
@ -54,12 +53,9 @@ public class JettyWebSocketNegotiationTest
connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, configurator);
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, configurator);
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client = new WebSocketClient();

View File

@ -21,7 +21,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
@ -51,18 +50,15 @@ public class LargeDeflateTest
_connector = new ServerConnector(_server);
_server.addConnector(_connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(_server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(_server, container ->
{
container.setIdleTimeout(Duration.ofDays(1));
container.setMaxFrameSize(Integer.MAX_VALUE);
container.setMaxBinaryMessageSize(Integer.MAX_VALUE);
container.addMapping("/", (rq, rs, cb) -> _serverSocket);
});
context.setHandler(wsHandler);
_server.setHandler(context);
_server.setHandler(wsHandler);
_server.start();
_client = new WebSocketClient();

View File

@ -21,7 +21,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@ -61,17 +60,14 @@ public class MaxOutgoingFramesTest
connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
{
container.addMapping("/", (rq, rs, cb) -> serverSocket);
WebSocketComponents components = WebSocketServerComponents.getWebSocketComponents(context);
WebSocketComponents components = WebSocketServerComponents.getWebSocketComponents(server);
components.getExtensionRegistry().register(BlockingOutgoingExtension.class.getName(), BlockingOutgoingExtension.class);
});
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client = new WebSocketClient();

View File

@ -19,7 +19,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
@ -46,16 +45,13 @@ public class SimpleEchoTest
_connector = new ServerConnector(_server);
_server.addConnector(_connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(_server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(_server, container ->
{
container.setIdleTimeout(Duration.ZERO);
container.addMapping("/", (rq, rs, cb) -> new EchoSocket());
});
context.setHandler(wsHandler);
_server.setHandler(context);
_server.setHandler(wsHandler);
_server.start();
_client = new WebSocketClient();

View File

@ -20,7 +20,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.Callback;
@ -54,13 +53,10 @@ public class SingleOnMessageTest
ServerConnector connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
container.addMapping("/", (rq, rs, cb) -> serverSocket));
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
serverUri = WSURI.toWebsocket(server.getURI());

View File

@ -21,7 +21,6 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
@ -50,13 +49,10 @@ public class UpgradeRequestResponseTest
server.addConnector(connector);
serverSocket = new EchoSocket();
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
container.addMapping("/", (rq, rs, cb) -> serverSocket));
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client = new WebSocketClient();

View File

@ -25,7 +25,6 @@ import org.eclipse.jetty.io.IncludeExcludeConnectionStatistics;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
@ -74,20 +73,17 @@ public class WebSocketStatsTest
connector.addBean(wsCloseListener);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
{
container.setAutoFragment(false);
container.addMapping("/", (rq, rs, cb) -> new EchoSocket());
});
context.setHandler(wsHandler);
// Setup JMX.
MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
server.addBean(mbeanContainer);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client = new WebSocketClient();

View File

@ -20,7 +20,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
@ -51,13 +50,10 @@ public class WebSocketStopTest
connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context, container ->
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container ->
container.addMapping("/", (rq, rs, cb) -> serverSocket));
context.setHandler(wsHandler);
server.setHandler(context);
server.setHandler(wsHandler);
server.start();
client.start();

View File

@ -47,25 +47,16 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
public class DynamicServerConfigurationTest
{
private Server server;
private final Server server = new Server();
private HttpClient httpClient;
private WebSocketClient wsClient;
public void start(Handler handler) throws Exception
{
server = new Server();
ServerConnector connector = new ServerConnector(server);
server.addConnector(connector);
ContextHandler context = new ContextHandler("/ctx");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context);
context.setHandler(wsHandler);
wsHandler.setHandler(handler);
server.setHandler(context);
server.setHandler(handler);
server.start();
httpClient = new HttpClient();
@ -81,32 +72,37 @@ public class DynamicServerConfigurationTest
}
@Test
public void testDynamicConfiguration() throws Exception
public void testDynamicConfigurationWithServer() throws Exception
{
start(new Handler.Abstract()
{
@Override
public boolean handle(Request request, Response response, org.eclipse.jetty.util.Callback callback) throws Exception
{
String pathInContext = Request.getPathInContext(request);
if ("/config".equals(pathInContext))
{
ServerWebSocketContainer container = (ServerWebSocketContainer)request.getContext().getAttribute(WebSocketContainer.class.getName());
container.addMapping("/ws", (rq, rs, cb) -> new EchoSocket());
}
callback.succeeded();
return true;
}
});
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server);
wsHandler.setHandler(new DynamicConfigurationHandler());
start(wsHandler);
testDynamicConfiguration("");
}
@Test
public void testDynamicConfigurationWithContextHandler() throws Exception
{
ContextHandler context = new ContextHandler("/ctx");
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context);
context.setHandler(wsHandler);
wsHandler.setHandler(new DynamicConfigurationHandler());
start(context);
testDynamicConfiguration("/ctx");
}
private void testDynamicConfiguration(String contextPath) throws Exception
{
// There are not yet any configured WebSocket mapping, so the connect() must fail.
URI wsUri = WSURI.toWebsocket(server.getURI().resolve("/ctx/ws"));
URI wsUri = WSURI.toWebsocket(server.getURI().resolve(contextPath + "/ws"));
Future<Session> future = wsClient.connect(new EventSocket(), wsUri);
ExecutionException x = assertThrows(ExecutionException.class, future::get);
assertInstanceOf(UpgradeException.class, x.getCause());
// Make one HTTP request to dynamically configure.
ContentResponse response = httpClient.GET(server.getURI().resolve("/ctx/config"));
ContentResponse response = httpClient.GET(server.getURI().resolve(contextPath + "/config"));
assertEquals(HttpStatus.OK_200, response.getStatus());
// Try again WebSocket, must succeed.
@ -120,4 +116,20 @@ public class DynamicServerConfigurationTest
assertEquals("OK", reply);
}
}
private static class DynamicConfigurationHandler extends Handler.Abstract
{
@Override
public boolean handle(Request request, Response response, org.eclipse.jetty.util.Callback callback)
{
String pathInContext = Request.getPathInContext(request);
if ("/config".equals(pathInContext))
{
ServerWebSocketContainer container = (ServerWebSocketContainer)request.getContext().getAttribute(WebSocketContainer.class.getName());
container.addMapping("/ws", (rq, rs, cb) -> new EchoSocket());
}
callback.succeeded();
return true;
}
}
}