All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.websocket.server.WebSocketUpgradeHandler Maven / Gradle / Ivy

//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.websocket.server;

import java.util.function.Consumer;

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.thread.Invocable;
import org.eclipse.jetty.websocket.api.WebSocketContainer;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.server.WebSocketMappings;
import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents;

/**
 * 

A {@link Handler} that may perform the upgrade from HTTP to WebSocket.

*

The upgrade is performed only if the request matches all the requisites * 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}.

*

{@code WebSocketUpgradeHandler} may be a {@link #getDescendant(Class) * descendant} of a {@link ContextHandler}, typically as a direct child, but * possibly also further down the {@link Handler}'s tree, to enable WebSocket * upgrades for that {@link ContextHandler} only.

*

{@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.

*

Typical usage:

*
{@code
 * Server server = ...;
 *
 * ContextHandler context = new ContextHandler("/app");
 *
 * // Create the WebSocketUpgradeHandler.
 * 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();
 * }
*

A {@link WebSocketUpgradeHandler} is associated with a {@link ServerWebSocketContainer} * that is exported as a request context attribute and can be retrieved in this way: *

{@code
 * public boolean process(Request request)
 * {
 *     // Retrieve the WebSocket container from the context attributes.
 *     ServerWebSocketContainer container = (ServerWebSocketContainer)request.getContext().getAttribute(WebSocketContainer.class.getName());
 * }
 * }
*/ public class WebSocketUpgradeHandler extends Handler.Wrapper { /** *

Creates a new {@code WebSocketUpgradeHandler}.

*

The {@code WebSocketUpgradeHandler} is not yet linked to the given * {@link ContextHandler}, therefore the caller code must ensure that * the returned {@code WebSocketUpgradeHandler} is a descendant of the * given {@link ContextHandler}.

* * @param server the {@link Server} object used to lookup common WebSocket components * @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) { return from(server, context, null); } /** *

Creates a new {@code WebSocketUpgradeHandler}.

*

The {@code WebSocketUpgradeHandler} is not yet linked to the given * {@link ContextHandler}, therefore the caller code must ensure that * the returned {@code WebSocketUpgradeHandler} is a descendant of the * given {@link ContextHandler}.

*

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.

* * @param server the {@link Server} object used to lookup common WebSocket components * @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 {@code WebSocketUpgradeHandler} * @return a new {@code WebSocketUpgradeHandler} */ public static WebSocketUpgradeHandler from(Server server, ContextHandler context, Consumer configurator) { WebSocketComponents components = WebSocketServerComponents.ensureWebSocketComponents(server, context); WebSocketMappings mappings = new WebSocketMappings(components); ServerWebSocketContainer container = new ServerWebSocketContainer(mappings); container.addBean(mappings); WebSocketUpgradeHandler wsHandler = new WebSocketUpgradeHandler(container, configurator); context.getContext().setAttribute(WebSocketContainer.class.getName(), container); return wsHandler; } /** *

Creates a new {@code WebSocketUpgradeHandler}.

*

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}.

* * @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 -> {}); } /** *

Creates a new {@code WebSocketUpgradeHandler}.

*

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}.

*

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.

* * @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 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; } private final ServerWebSocketContainer _container; private final Consumer _configurator; /** *

Creates a new {@code WebSocketUpgradeHandler} with the given {@link ServerWebSocketContainer}.

* * @param container the {@link ServerWebSocketContainer} of this {@code WebSocketUpgradeHandler} */ public WebSocketUpgradeHandler(ServerWebSocketContainer container) { this(container, null); } /** *

Creates a new {@code WebSocketUpgradeHandler} with the given {@link ServerWebSocketContainer} * and the given configurator.

*

The configurator is invoked every time this {@code WebSocketUpgradeHandler} is started, * see {@link #from(Server, ContextHandler, Consumer)}.

* * @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 configurator) { _container = container; _configurator = configurator; addManaged(container); } /** *

Configures the {@link ServerWebSocketContainer} associated with this * {@code WebSocketUpgradeHandler}.

*

This configuration is applied immediately and lost after a restart.

* * @param configurator the configuration code * @return this {@code WebSocketUpgradeHandler} * @deprecated use {@link #from(Server, ContextHandler, Consumer)}, * {@link #from(Server, Consumer)} or {@link #getServerWebSocketContainer()} */ @Deprecated public WebSocketUpgradeHandler configure(Consumer configurator) { configurator.accept(_container); return this; } public ServerWebSocketContainer getServerWebSocketContainer() { return _container; } @Override protected void doStart() throws Exception { if (_configurator != null) _configurator.accept(_container); super.doStart(); } @Override public boolean handle(Request request, Response response, Callback callback) throws Exception { if (handle(_container, request, response, callback)) return true; return super.handle(request, response, callback); } protected boolean handle(ServerWebSocketContainer container, Request request, Response response, Callback callback) { try { return container.handle(request, response, callback); } catch (Throwable x) { Response.writeError(request, response, callback, x); return true; } } @Override public InvocationType getInvocationType() { if (isDynamic()) return InvocationType.BLOCKING; Handler handler = getHandler(); InvocationType handlerInvocationType = handler == null ? InvocationType.NON_BLOCKING : handler.getInvocationType(); return Invocable.combine(handlerInvocationType, _container.getInvocationType()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy