Drop server-specific RequestUpgradeStrategy implementations
StandardWebSocketUpgradeStrategy is the common replacement on Tomcat, Undertow and all EE servers. JettyRequestUpgradeStrategy remains the preferred choice on Jetty. Closes gh-33744
This commit is contained in:
parent
342369355d
commit
3f3341bb1d
|
|
@ -123,7 +123,6 @@ dependencies {
|
|||
api("org.freemarker:freemarker:2.3.33")
|
||||
api("org.glassfish.external:opendmk_jmxremote_optional_jar:1.0-b01-ea")
|
||||
api("org.glassfish:jakarta.el:4.0.2")
|
||||
api("org.glassfish.tyrus:tyrus-container-servlet:2.1.3")
|
||||
api("org.graalvm.sdk:graal-sdk:22.3.1")
|
||||
api("org.hamcrest:hamcrest:2.2")
|
||||
api("org.hibernate:hibernate-core:7.0.0.Beta2")
|
||||
|
|
|
|||
|
|
@ -12,19 +12,11 @@ dependencies {
|
|||
optional("jakarta.servlet:jakarta.servlet-api")
|
||||
optional("jakarta.websocket:jakarta.websocket-api")
|
||||
optional("jakarta.websocket:jakarta.websocket-client-api")
|
||||
optional("org.apache.tomcat:tomcat-websocket") {
|
||||
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
|
||||
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
|
||||
}
|
||||
optional("org.eclipse.jetty.ee10:jetty-ee10-webapp") {
|
||||
exclude group: "jakarta.servlet", module: "jakarta.servlet-api"
|
||||
}
|
||||
optional("org.eclipse.jetty.websocket:jetty-websocket-jetty-api")
|
||||
optional("org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server")
|
||||
optional("org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jetty-server") {
|
||||
exclude group: "jakarta.servlet", module: "jakarta.servlet-api"
|
||||
}
|
||||
optional("org.glassfish.tyrus:tyrus-container-servlet")
|
||||
optional("org.eclipse.jetty.websocket:jetty-websocket-jetty-api")
|
||||
optional("org.eclipse.jetty:jetty-client")
|
||||
testImplementation(testFixtures(project(":spring-core")))
|
||||
testImplementation(testFixtures(project(":spring-web")))
|
||||
testImplementation("io.projectreactor.netty:reactor-netty-http")
|
||||
|
|
|
|||
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.socket.server.standard;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.websocket.Endpoint;
|
||||
import jakarta.websocket.Extension;
|
||||
import jakarta.websocket.WebSocketContainer;
|
||||
import jakarta.websocket.server.ServerContainer;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.socket.WebSocketExtension;
|
||||
import org.springframework.web.socket.WebSocketHandler;
|
||||
import org.springframework.web.socket.adapter.standard.StandardToWebSocketExtensionAdapter;
|
||||
import org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter;
|
||||
import org.springframework.web.socket.adapter.standard.StandardWebSocketSession;
|
||||
import org.springframework.web.socket.adapter.standard.WebSocketToStandardExtensionAdapter;
|
||||
import org.springframework.web.socket.server.HandshakeFailureException;
|
||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
|
||||
/**
|
||||
* A base class for {@link RequestUpgradeStrategy} implementations that build
|
||||
* on the standard WebSocket API for Java (JSR-356).
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public abstract class AbstractStandardUpgradeStrategy implements RequestUpgradeStrategy {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Nullable
|
||||
private volatile List<WebSocketExtension> extensions;
|
||||
|
||||
|
||||
protected ServerContainer getContainer(HttpServletRequest request) {
|
||||
ServletContext servletContext = request.getServletContext();
|
||||
String attrName = "jakarta.websocket.server.ServerContainer";
|
||||
ServerContainer container = (ServerContainer) servletContext.getAttribute(attrName);
|
||||
Assert.notNull(container, "No 'jakarta.websocket.server.ServerContainer' ServletContext attribute. " +
|
||||
"Are you running in a Servlet container that supports JSR-356?");
|
||||
return container;
|
||||
}
|
||||
|
||||
protected final HttpServletRequest getHttpServletRequest(ServerHttpRequest request) {
|
||||
Assert.isInstanceOf(ServletServerHttpRequest.class, request, "ServletServerHttpRequest required");
|
||||
return ((ServletServerHttpRequest) request).getServletRequest();
|
||||
}
|
||||
|
||||
protected final HttpServletResponse getHttpServletResponse(ServerHttpResponse response) {
|
||||
Assert.isInstanceOf(ServletServerHttpResponse.class, response, "ServletServerHttpResponse required");
|
||||
return ((ServletServerHttpResponse) response).getServletResponse();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<WebSocketExtension> getSupportedExtensions(ServerHttpRequest request) {
|
||||
List<WebSocketExtension> extensions = this.extensions;
|
||||
if (extensions == null) {
|
||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||
extensions = getInstalledExtensions(getContainer(servletRequest));
|
||||
this.extensions = extensions;
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
protected List<WebSocketExtension> getInstalledExtensions(WebSocketContainer container) {
|
||||
List<WebSocketExtension> result = new ArrayList<>();
|
||||
for (Extension extension : container.getInstalledExtensions()) {
|
||||
result.add(new StandardToWebSocketExtensionAdapter(extension));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
|
||||
@Nullable String selectedProtocol, List<WebSocketExtension> selectedExtensions,
|
||||
@Nullable Principal user, WebSocketHandler wsHandler, Map<String, Object> attrs)
|
||||
throws HandshakeFailureException {
|
||||
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
InetSocketAddress localAddr = null;
|
||||
try {
|
||||
localAddr = request.getLocalAddress();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Ignore
|
||||
}
|
||||
InetSocketAddress remoteAddr = null;
|
||||
try {
|
||||
remoteAddr = request.getRemoteAddress();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
StandardWebSocketSession session = new StandardWebSocketSession(headers, attrs, localAddr, remoteAddr, user);
|
||||
StandardWebSocketHandlerAdapter endpoint = new StandardWebSocketHandlerAdapter(wsHandler, session);
|
||||
|
||||
List<Extension> extensions = new ArrayList<>();
|
||||
for (WebSocketExtension extension : selectedExtensions) {
|
||||
extensions.add(new WebSocketToStandardExtensionAdapter(extension));
|
||||
}
|
||||
|
||||
upgradeInternal(request, response, selectedProtocol, extensions, endpoint);
|
||||
}
|
||||
|
||||
protected abstract void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||
@Nullable String selectedProtocol, List<Extension> selectedExtensions, Endpoint endpoint)
|
||||
throws HandshakeFailureException;
|
||||
|
||||
}
|
||||
|
|
@ -1,248 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.socket.server.standard;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.websocket.DeploymentException;
|
||||
import jakarta.websocket.Endpoint;
|
||||
import jakarta.websocket.EndpointConfig;
|
||||
import jakarta.websocket.Extension;
|
||||
import jakarta.websocket.WebSocketContainer;
|
||||
import org.glassfish.tyrus.core.ComponentProviderService;
|
||||
import org.glassfish.tyrus.core.RequestContext;
|
||||
import org.glassfish.tyrus.core.TyrusEndpointWrapper;
|
||||
import org.glassfish.tyrus.core.TyrusUpgradeResponse;
|
||||
import org.glassfish.tyrus.core.TyrusWebSocketEngine;
|
||||
import org.glassfish.tyrus.core.Version;
|
||||
import org.glassfish.tyrus.server.TyrusServerContainer;
|
||||
import org.glassfish.tyrus.spi.WebSocketEngine.UpgradeInfo;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.socket.WebSocketExtension;
|
||||
import org.springframework.web.socket.server.HandshakeFailureException;
|
||||
|
||||
import static org.glassfish.tyrus.spi.WebSocketEngine.UpgradeStatus.SUCCESS;
|
||||
|
||||
/**
|
||||
* A base class for {@code RequestUpgradeStrategy} implementations on top of
|
||||
* JSR-356 based servers which include Tyrus as their WebSocket engine.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Brian Clozel
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
* @see <a href="https://tyrus.java.net/">Project Tyrus</a>
|
||||
*/
|
||||
public abstract class AbstractTyrusRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy {
|
||||
|
||||
private static final String[] SUPPORTED_VERSIONS =
|
||||
StringUtils.tokenizeToStringArray(Version.getSupportedWireProtocolVersions(), ",");
|
||||
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
private static final Constructor<?> constructor;
|
||||
|
||||
private static final boolean constructorWithBooleanArgument;
|
||||
|
||||
private static final Method registerMethod;
|
||||
|
||||
private static final Method unRegisterMethod;
|
||||
|
||||
static {
|
||||
try {
|
||||
constructor = getEndpointConstructor();
|
||||
int parameterCount = constructor.getParameterCount();
|
||||
constructorWithBooleanArgument = (parameterCount == 10);
|
||||
if (!constructorWithBooleanArgument && parameterCount != 9) {
|
||||
throw new IllegalStateException("Expected TyrusEndpointWrapper constructor with 9 or 10 arguments");
|
||||
}
|
||||
registerMethod = TyrusWebSocketEngine.class.getDeclaredMethod("register", TyrusEndpointWrapper.class);
|
||||
unRegisterMethod = TyrusWebSocketEngine.class.getDeclaredMethod("unregister", TyrusEndpointWrapper.class);
|
||||
ReflectionUtils.makeAccessible(registerMethod);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("No compatible Tyrus version found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static Constructor<?> getEndpointConstructor() {
|
||||
for (Constructor<?> current : TyrusEndpointWrapper.class.getConstructors()) {
|
||||
Class<?>[] types = current.getParameterTypes();
|
||||
if (Endpoint.class == types[0] && EndpointConfig.class == types[1]) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No compatible Tyrus version found");
|
||||
}
|
||||
|
||||
|
||||
private final ComponentProviderService componentProvider = ComponentProviderService.create();
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getSupportedVersions() {
|
||||
return SUPPORTED_VERSIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<WebSocketExtension> getInstalledExtensions(WebSocketContainer container) {
|
||||
try {
|
||||
return super.getInstalledExtensions(container);
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||
@Nullable String selectedProtocol, List<Extension> extensions, Endpoint endpoint)
|
||||
throws HandshakeFailureException {
|
||||
|
||||
HttpServletRequest servletRequest = getHttpServletRequest(request);
|
||||
HttpServletResponse servletResponse = getHttpServletResponse(response);
|
||||
|
||||
TyrusServerContainer serverContainer = (TyrusServerContainer) getContainer(servletRequest);
|
||||
TyrusWebSocketEngine engine = (TyrusWebSocketEngine) serverContainer.getWebSocketEngine();
|
||||
Object tyrusEndpoint = null;
|
||||
boolean success;
|
||||
|
||||
try {
|
||||
// Shouldn't matter for processing but must be unique
|
||||
String path = "/" + random.nextLong();
|
||||
tyrusEndpoint = createTyrusEndpoint(endpoint, path, selectedProtocol, extensions, serverContainer, engine);
|
||||
register(engine, tyrusEndpoint);
|
||||
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
RequestContext requestContext = createRequestContext(servletRequest, path, headers);
|
||||
TyrusUpgradeResponse upgradeResponse = new TyrusUpgradeResponse();
|
||||
UpgradeInfo upgradeInfo = engine.upgrade(requestContext, upgradeResponse);
|
||||
success = SUCCESS.equals(upgradeInfo.getStatus());
|
||||
if (success) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Successful request upgrade: " + upgradeResponse.getHeaders());
|
||||
}
|
||||
handleSuccess(servletRequest, servletResponse, upgradeInfo, upgradeResponse);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
unregisterTyrusEndpoint(engine, tyrusEndpoint);
|
||||
throw new HandshakeFailureException("Error during handshake: " + request.getURI(), ex);
|
||||
}
|
||||
|
||||
unregisterTyrusEndpoint(engine, tyrusEndpoint);
|
||||
if (!success) {
|
||||
throw new HandshakeFailureException("Unexpected handshake failure: " + request.getURI());
|
||||
}
|
||||
}
|
||||
|
||||
private Object createTyrusEndpoint(Endpoint endpoint, String endpointPath, @Nullable String protocol,
|
||||
List<Extension> extensions, WebSocketContainer container, TyrusWebSocketEngine engine)
|
||||
throws DeploymentException {
|
||||
|
||||
ServerEndpointRegistration endpointConfig = new ServerEndpointRegistration(endpointPath, endpoint);
|
||||
endpointConfig.setSubprotocols(Collections.singletonList(protocol));
|
||||
endpointConfig.setExtensions(extensions);
|
||||
return createEndpoint(endpointConfig, this.componentProvider, container, engine);
|
||||
}
|
||||
|
||||
private RequestContext createRequestContext(HttpServletRequest request, String endpointPath, HttpHeaders headers) {
|
||||
RequestContext context =
|
||||
RequestContext.Builder.create()
|
||||
.requestURI(URI.create(endpointPath))
|
||||
.userPrincipal(request.getUserPrincipal())
|
||||
.secure(request.isSecure())
|
||||
.remoteAddr(request.getRemoteAddr())
|
||||
.build();
|
||||
headers.forEach((header, value) -> context.getHeaders().put(header, value));
|
||||
return context;
|
||||
}
|
||||
|
||||
private void unregisterTyrusEndpoint(TyrusWebSocketEngine engine, @Nullable Object tyrusEndpoint) {
|
||||
if (tyrusEndpoint != null) {
|
||||
try {
|
||||
unregister(engine, tyrusEndpoint);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object createEndpoint(ServerEndpointRegistration registration, ComponentProviderService provider,
|
||||
WebSocketContainer container, TyrusWebSocketEngine engine) throws DeploymentException {
|
||||
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(engine);
|
||||
Object sessionListener = accessor.getPropertyValue("sessionListener");
|
||||
Object clusterContext = accessor.getPropertyValue("clusterContext");
|
||||
try {
|
||||
if (constructorWithBooleanArgument) {
|
||||
// Tyrus 1.11+
|
||||
return constructor.newInstance(registration.getEndpoint(), registration, provider, container,
|
||||
"/", registration.getConfigurator(), sessionListener, clusterContext, null, Boolean.TRUE);
|
||||
}
|
||||
else {
|
||||
return constructor.newInstance(registration.getEndpoint(), registration, provider, container,
|
||||
"/", registration.getConfigurator(), sessionListener, clusterContext, null);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to register " + registration, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void register(TyrusWebSocketEngine engine, Object endpoint) {
|
||||
try {
|
||||
registerMethod.invoke(engine, endpoint);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to register " + endpoint, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregister(TyrusWebSocketEngine engine, Object endpoint) {
|
||||
try {
|
||||
unRegisterMethod.invoke(engine, endpoint);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to unregister " + endpoint, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected abstract void handleSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
UpgradeInfo upgradeInfo, TyrusUpgradeResponse upgradeResponse) throws IOException, ServletException;
|
||||
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.socket.server.standard;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.glassfish.tyrus.core.TyrusUpgradeResponse;
|
||||
import org.glassfish.tyrus.core.Utils;
|
||||
import org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler;
|
||||
import org.glassfish.tyrus.spi.WebSocketEngine.UpgradeInfo;
|
||||
import org.glassfish.tyrus.spi.Writer;
|
||||
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.socket.server.HandshakeFailureException;
|
||||
|
||||
/**
|
||||
* A WebSocket {@code RequestUpgradeStrategy} for Oracle's GlassFish 4.1 and higher.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @author Michael Irwin
|
||||
* @since 4.0
|
||||
*/
|
||||
public class GlassFishRequestUpgradeStrategy extends AbstractTyrusRequestUpgradeStrategy {
|
||||
|
||||
private static final Constructor<?> constructor;
|
||||
|
||||
static {
|
||||
try {
|
||||
ClassLoader classLoader = GlassFishRequestUpgradeStrategy.class.getClassLoader();
|
||||
Class<?> type = classLoader.loadClass("org.glassfish.tyrus.servlet.TyrusServletWriter");
|
||||
constructor = type.getDeclaredConstructor(TyrusHttpUpgradeHandler.class);
|
||||
ReflectionUtils.makeAccessible(constructor);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("No compatible Tyrus version found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
UpgradeInfo upgradeInfo, TyrusUpgradeResponse upgradeResponse) throws IOException, ServletException {
|
||||
|
||||
TyrusHttpUpgradeHandler handler = request.upgrade(TyrusHttpUpgradeHandler.class);
|
||||
Writer servletWriter = newServletWriter(handler);
|
||||
handler.preInit(upgradeInfo, servletWriter, request.getUserPrincipal() != null);
|
||||
|
||||
response.setStatus(upgradeResponse.getStatus());
|
||||
upgradeResponse.getHeaders().forEach((key, value) -> response.addHeader(key, Utils.getHeaderFromList(value)));
|
||||
response.flushBuffer();
|
||||
}
|
||||
|
||||
private Writer newServletWriter(TyrusHttpUpgradeHandler handler) {
|
||||
try {
|
||||
return (Writer) constructor.newInstance(handler);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to instantiate TyrusServletWriter", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,28 +16,39 @@
|
|||
|
||||
package org.springframework.web.socket.server.standard;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.websocket.Endpoint;
|
||||
import jakarta.websocket.Extension;
|
||||
import jakarta.websocket.server.ServerEndpointConfig;
|
||||
import jakarta.websocket.WebSocketContainer;
|
||||
import jakarta.websocket.server.ServerContainer;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.socket.WebSocketExtension;
|
||||
import org.springframework.web.socket.WebSocketHandler;
|
||||
import org.springframework.web.socket.adapter.standard.StandardToWebSocketExtensionAdapter;
|
||||
import org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter;
|
||||
import org.springframework.web.socket.adapter.standard.StandardWebSocketSession;
|
||||
import org.springframework.web.socket.adapter.standard.WebSocketToStandardExtensionAdapter;
|
||||
import org.springframework.web.socket.server.HandshakeFailureException;
|
||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
|
||||
/**
|
||||
* A WebSocket {@code RequestUpgradeStrategy} for the Jakarta WebSocket API 2.1+.
|
||||
*
|
||||
* <p>This strategy serves as a fallback if no specific server has been detected.
|
||||
* It can also be used with Jakarta EE 10 level servers such as Tomcat 10.1 and
|
||||
* Undertow 2.3 directly, relying on their built-in Jakarta WebSocket 2.1 support.
|
||||
*
|
||||
* <p>To modify properties of the underlying {@link jakarta.websocket.server.ServerContainer}
|
||||
* you can use {@link ServletServerContainerFactoryBean} in XML configuration or,
|
||||
* when using Java configuration, access the container instance through the
|
||||
|
|
@ -48,10 +59,13 @@ import org.springframework.web.socket.server.HandshakeFailureException;
|
|||
* @since 6.0
|
||||
* @see jakarta.websocket.server.ServerContainer#upgradeHttpToWebSocket
|
||||
*/
|
||||
public class StandardWebSocketUpgradeStrategy extends AbstractStandardUpgradeStrategy {
|
||||
public class StandardWebSocketUpgradeStrategy implements RequestUpgradeStrategy {
|
||||
|
||||
private static final String[] SUPPORTED_VERSIONS = new String[] {"13"};
|
||||
|
||||
@Nullable
|
||||
private volatile List<WebSocketExtension> extensions;
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getSupportedVersions() {
|
||||
|
|
@ -59,10 +73,55 @@ public class StandardWebSocketUpgradeStrategy extends AbstractStandardUpgradeStr
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||
@Nullable String selectedProtocol, List<Extension> selectedExtensions, Endpoint endpoint)
|
||||
public List<WebSocketExtension> getSupportedExtensions(ServerHttpRequest request) {
|
||||
List<WebSocketExtension> extensions = this.extensions;
|
||||
if (extensions == null) {
|
||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||
extensions = getInstalledExtensions(getContainer(servletRequest));
|
||||
this.extensions = extensions;
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
protected List<WebSocketExtension> getInstalledExtensions(WebSocketContainer container) {
|
||||
List<WebSocketExtension> result = new ArrayList<>();
|
||||
for (Extension extension : container.getInstalledExtensions()) {
|
||||
result.add(new StandardToWebSocketExtensionAdapter(extension));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
|
||||
@Nullable String selectedProtocol, List<WebSocketExtension> selectedExtensions,
|
||||
@Nullable Principal user, WebSocketHandler wsHandler, Map<String, Object> attrs)
|
||||
throws HandshakeFailureException {
|
||||
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
InetSocketAddress localAddr = null;
|
||||
try {
|
||||
localAddr = request.getLocalAddress();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Ignore
|
||||
}
|
||||
InetSocketAddress remoteAddr = null;
|
||||
try {
|
||||
remoteAddr = request.getRemoteAddress();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
StandardWebSocketSession session = new StandardWebSocketSession(headers, attrs, localAddr, remoteAddr, user);
|
||||
StandardWebSocketHandlerAdapter endpoint = new StandardWebSocketHandlerAdapter(wsHandler, session);
|
||||
|
||||
List<Extension> extensions = new ArrayList<>();
|
||||
for (WebSocketExtension extension : selectedExtensions) {
|
||||
extensions.add(new WebSocketToStandardExtensionAdapter(extension));
|
||||
}
|
||||
|
||||
HttpServletRequest servletRequest = getHttpServletRequest(request);
|
||||
HttpServletResponse servletResponse = getHttpServletResponse(response);
|
||||
|
||||
|
|
@ -72,21 +131,35 @@ public class StandardWebSocketUpgradeStrategy extends AbstractStandardUpgradeStr
|
|||
|
||||
ServerEndpointRegistration endpointConfig = new ServerEndpointRegistration(path, endpoint);
|
||||
endpointConfig.setSubprotocols(Collections.singletonList(selectedProtocol));
|
||||
endpointConfig.setExtensions(selectedExtensions);
|
||||
endpointConfig.setExtensions(extensions);
|
||||
|
||||
try {
|
||||
upgradeHttpToWebSocket(servletRequest, servletResponse, endpointConfig, pathParams);
|
||||
getContainer(servletRequest).upgradeHttpToWebSocket(
|
||||
servletRequest, servletResponse, endpointConfig, pathParams);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException(
|
||||
"Servlet request failed to upgrade to WebSocket: " + requestUrl, ex);
|
||||
throw new HandshakeFailureException("Servlet request failed to upgrade to WebSocket: " + requestUrl, ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected void upgradeHttpToWebSocket(HttpServletRequest request, HttpServletResponse response,
|
||||
ServerEndpointConfig endpointConfig, Map<String,String> pathParams) throws Exception {
|
||||
|
||||
getContainer(request).upgradeHttpToWebSocket(request, response, endpointConfig, pathParams);
|
||||
protected ServerContainer getContainer(HttpServletRequest request) {
|
||||
ServletContext servletContext = request.getServletContext();
|
||||
String attrName = "jakarta.websocket.server.ServerContainer";
|
||||
ServerContainer container = (ServerContainer) servletContext.getAttribute(attrName);
|
||||
Assert.notNull(container, "No 'jakarta.websocket.server.ServerContainer' ServletContext attribute. " +
|
||||
"Are you running in a Servlet container that supports JSR-356?");
|
||||
return container;
|
||||
}
|
||||
|
||||
protected final HttpServletRequest getHttpServletRequest(ServerHttpRequest request) {
|
||||
Assert.isInstanceOf(ServletServerHttpRequest.class, request, "ServletServerHttpRequest required");
|
||||
return ((ServletServerHttpRequest) request).getServletRequest();
|
||||
}
|
||||
|
||||
protected final HttpServletResponse getHttpServletResponse(ServerHttpResponse response) {
|
||||
Assert.isInstanceOf(ServletServerHttpResponse.class, response, "ServletServerHttpResponse required");
|
||||
return ((ServletServerHttpResponse) response).getServletResponse();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.socket.server.standard;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.websocket.server.ServerEndpointConfig;
|
||||
import org.apache.tomcat.websocket.server.WsServerContainer;
|
||||
|
||||
/**
|
||||
* A WebSocket {@code RequestUpgradeStrategy} for Apache Tomcat. Compatible with Tomcat 10
|
||||
* and higher, in particular with Tomcat 10.0 (not based on Jakarta WebSocket 2.1 yet).
|
||||
*
|
||||
* <p>To modify properties of the underlying {@link jakarta.websocket.server.ServerContainer}
|
||||
* you can use {@link ServletServerContainerFactoryBean} in XML configuration or,
|
||||
* when using Java configuration, access the container instance through the
|
||||
* "jakarta.websocket.server.ServerContainer" ServletContext attribute.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
* @see org.apache.tomcat.websocket.server.WsServerContainer#upgradeHttpToWebSocket
|
||||
*/
|
||||
public class TomcatRequestUpgradeStrategy extends StandardWebSocketUpgradeStrategy {
|
||||
|
||||
@Override
|
||||
protected void upgradeHttpToWebSocket(HttpServletRequest request, HttpServletResponse response,
|
||||
ServerEndpointConfig endpointConfig, Map<String, String> pathParams) throws Exception {
|
||||
|
||||
((WsServerContainer) getContainer(request)).upgradeHttpToWebSocket(
|
||||
request, response, endpointConfig, pathParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.socket.server.standard;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.undertow.websockets.jsr.ServerWebSocketContainer;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.websocket.server.ServerEndpointConfig;
|
||||
|
||||
/**
|
||||
* A WebSocket {@code RequestUpgradeStrategy} for WildFly and its underlying
|
||||
* Undertow web server. Also compatible with embedded Undertow usage.
|
||||
*
|
||||
* <p>Designed for Undertow 2.2, also compatible with Undertow 2.3
|
||||
* (which implements Jakarta WebSocket 2.1 as well).
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0.1
|
||||
* @see io.undertow.websockets.jsr.ServerWebSocketContainer#doUpgrade
|
||||
*/
|
||||
public class UndertowRequestUpgradeStrategy extends StandardWebSocketUpgradeStrategy {
|
||||
|
||||
private static final String[] SUPPORTED_VERSIONS = new String[] {"13", "8", "7"};
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getSupportedVersions() {
|
||||
return SUPPORTED_VERSIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void upgradeHttpToWebSocket(HttpServletRequest request, HttpServletResponse response,
|
||||
ServerEndpointConfig endpointConfig, Map<String, String> pathParams) throws Exception {
|
||||
|
||||
((ServerWebSocketContainer) getContainer(request)).doUpgrade(
|
||||
request, response, endpointConfig, pathParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,244 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.socket.server.standard;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import jakarta.servlet.AsyncContext;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.glassfish.tyrus.core.TyrusUpgradeResponse;
|
||||
import org.glassfish.tyrus.core.Utils;
|
||||
import org.glassfish.tyrus.spi.Connection;
|
||||
import org.glassfish.tyrus.spi.WebSocketEngine.UpgradeInfo;
|
||||
import org.glassfish.tyrus.spi.Writer;
|
||||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.socket.server.HandshakeFailureException;
|
||||
|
||||
/**
|
||||
* A WebSocket {@code RequestUpgradeStrategy} for Oracle's WebLogic.
|
||||
* Supports 12.1.3 as well as 12.2.1, as of Spring Framework 4.2.3.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public class WebLogicRequestUpgradeStrategy extends AbstractTyrusRequestUpgradeStrategy {
|
||||
|
||||
private static final TyrusMuxableWebSocketHelper webSocketHelper = new TyrusMuxableWebSocketHelper();
|
||||
|
||||
private static final WebLogicServletWriterHelper servletWriterHelper = new WebLogicServletWriterHelper();
|
||||
|
||||
private static final Connection.CloseListener noOpCloseListener = (reason -> {});
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
UpgradeInfo upgradeInfo, TyrusUpgradeResponse upgradeResponse) throws IOException, ServletException {
|
||||
|
||||
response.setStatus(upgradeResponse.getStatus());
|
||||
upgradeResponse.getHeaders().forEach((key, value) -> response.addHeader(key, Utils.getHeaderFromList(value)));
|
||||
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
asyncContext.setTimeout(-1L);
|
||||
|
||||
Object nativeRequest = getNativeRequest(request);
|
||||
BeanWrapper beanWrapper = new BeanWrapperImpl(nativeRequest);
|
||||
Object httpSocket = beanWrapper.getPropertyValue("connection.connectionHandler.rawConnection");
|
||||
Object webSocket = webSocketHelper.newInstance(request, httpSocket);
|
||||
webSocketHelper.upgrade(webSocket, httpSocket, request.getServletContext());
|
||||
|
||||
response.flushBuffer();
|
||||
|
||||
boolean isProtected = request.getUserPrincipal() != null;
|
||||
Writer servletWriter = servletWriterHelper.newInstance(webSocket, isProtected);
|
||||
Connection connection = upgradeInfo.createConnection(servletWriter, noOpCloseListener);
|
||||
new BeanWrapperImpl(webSocket).setPropertyValue("connection", connection);
|
||||
new BeanWrapperImpl(servletWriter).setPropertyValue("connection", connection);
|
||||
webSocketHelper.registerForReadEvent(webSocket);
|
||||
}
|
||||
|
||||
|
||||
private static Class<?> type(String className) throws ClassNotFoundException {
|
||||
return WebLogicRequestUpgradeStrategy.class.getClassLoader().loadClass(className);
|
||||
}
|
||||
|
||||
private static Method method(String className, String method, Class<?>... paramTypes)
|
||||
throws ClassNotFoundException, NoSuchMethodException {
|
||||
|
||||
return type(className).getDeclaredMethod(method, paramTypes);
|
||||
}
|
||||
|
||||
private static Object getNativeRequest(ServletRequest request) {
|
||||
while (request instanceof ServletRequestWrapper wrapper) {
|
||||
request = wrapper.getRequest();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helps to create and invoke {@code weblogic.servlet.internal.MuxableSocketHTTP}.
|
||||
*/
|
||||
private static class TyrusMuxableWebSocketHelper {
|
||||
|
||||
private static final Class<?> type;
|
||||
|
||||
private static final Constructor<?> constructor;
|
||||
|
||||
private static final SubjectHelper subjectHelper;
|
||||
|
||||
private static final Method upgradeMethod;
|
||||
|
||||
private static final Method readEventMethod;
|
||||
|
||||
static {
|
||||
try {
|
||||
type = type("weblogic.websocket.tyrus.TyrusMuxableWebSocket");
|
||||
|
||||
constructor = type.getDeclaredConstructor(
|
||||
type("weblogic.servlet.internal.MuxableSocketHTTP"),
|
||||
type("weblogic.websocket.tyrus.CoherenceServletFilterService"),
|
||||
type("weblogic.servlet.spi.SubjectHandle"));
|
||||
subjectHelper = new SubjectHelper();
|
||||
|
||||
upgradeMethod = type.getMethod("upgrade", type("weblogic.socket.MuxableSocket"), ServletContext.class);
|
||||
readEventMethod = type.getMethod("registerForReadEvent");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("No compatible WebSocket version found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Object newInstance(HttpServletRequest request, @Nullable Object httpSocket) {
|
||||
try {
|
||||
Object[] args = new Object[] {httpSocket, null, subjectHelper.getSubject(request)};
|
||||
return constructor.newInstance(args);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to create TyrusMuxableWebSocket", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void upgrade(Object webSocket, @Nullable Object httpSocket, ServletContext servletContext) {
|
||||
try {
|
||||
upgradeMethod.invoke(webSocket, httpSocket, servletContext);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to upgrade TyrusMuxableWebSocket", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerForReadEvent(Object webSocket) {
|
||||
try {
|
||||
readEventMethod.invoke(webSocket);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to register WebSocket for read event", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class SubjectHelper {
|
||||
|
||||
private final Method securityContextMethod;
|
||||
|
||||
private final Method currentUserMethod;
|
||||
|
||||
private final Method providerMethod;
|
||||
|
||||
private final Method anonymousSubjectMethod;
|
||||
|
||||
public SubjectHelper() {
|
||||
try {
|
||||
String className = "weblogic.servlet.internal.WebAppServletContext";
|
||||
this.securityContextMethod = method(className, "getSecurityContext");
|
||||
|
||||
className = "weblogic.servlet.security.internal.SecurityModule";
|
||||
this.currentUserMethod = method(className, "getCurrentUser",
|
||||
type("weblogic.servlet.security.internal.ServletSecurityContext"),
|
||||
HttpServletRequest.class);
|
||||
|
||||
className = "weblogic.servlet.security.internal.WebAppSecurity";
|
||||
this.providerMethod = method(className, "getProvider");
|
||||
this.anonymousSubjectMethod = this.providerMethod.getReturnType().getDeclaredMethod("getAnonymousSubject");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("No compatible WebSocket version found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getSubject(HttpServletRequest request) {
|
||||
try {
|
||||
ServletContext servletContext = request.getServletContext();
|
||||
Object securityContext = this.securityContextMethod.invoke(servletContext);
|
||||
Object subject = this.currentUserMethod.invoke(null, securityContext, request);
|
||||
if (subject == null) {
|
||||
Object securityProvider = this.providerMethod.invoke(null);
|
||||
subject = this.anonymousSubjectMethod.invoke(securityProvider);
|
||||
}
|
||||
return subject;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to obtain SubjectHandle", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helps to create and invoke {@code weblogic.websocket.tyrus.TyrusServletWriter}.
|
||||
*/
|
||||
private static class WebLogicServletWriterHelper {
|
||||
|
||||
private static final Constructor<?> constructor;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class<?> writerType = type("weblogic.websocket.tyrus.TyrusServletWriter");
|
||||
Class<?> listenerType = type("weblogic.websocket.tyrus.TyrusServletWriter$CloseListener");
|
||||
Class<?> webSocketType = TyrusMuxableWebSocketHelper.type;
|
||||
constructor = writerType.getDeclaredConstructor(webSocketType, listenerType, boolean.class);
|
||||
ReflectionUtils.makeAccessible(constructor);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("No compatible WebSocket version found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Writer newInstance(Object webSocket, boolean isProtected) {
|
||||
try {
|
||||
return (Writer) constructor.newInstance(webSocket, null, isProtected);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to create TyrusServletWriter", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.socket.server.standard;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.websocket.server.ServerContainer;
|
||||
import jakarta.websocket.server.ServerEndpointConfig;
|
||||
|
||||
/**
|
||||
* WebSphere support for upgrading an {@link HttpServletRequest} during a
|
||||
* WebSocket handshake. To modify properties of the underlying
|
||||
* {@link jakarta.websocket.server.ServerContainer} you can use
|
||||
* {@link ServletServerContainerFactoryBean} in XML configuration or, when using
|
||||
* Java configuration, access the container instance through the
|
||||
* "javax.websocket.server.ServerContainer" ServletContext attribute.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.2.1
|
||||
*/
|
||||
public class WebSphereRequestUpgradeStrategy extends StandardWebSocketUpgradeStrategy {
|
||||
|
||||
private static final Method upgradeMethod;
|
||||
|
||||
static {
|
||||
ClassLoader loader = WebSphereRequestUpgradeStrategy.class.getClassLoader();
|
||||
try {
|
||||
Class<?> type = loader.loadClass("com.ibm.websphere.wsoc.WsWsocServerContainer");
|
||||
upgradeMethod = type.getMethod("doUpgrade", HttpServletRequest.class,
|
||||
HttpServletResponse.class, ServerEndpointConfig.class, Map.class);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("No compatible WebSphere version found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void upgradeHttpToWebSocket(HttpServletRequest request, HttpServletResponse response,
|
||||
ServerEndpointConfig endpointConfig, Map<String, String> pathParams) throws Exception {
|
||||
|
||||
ServerContainer container = getContainer(request);
|
||||
upgradeMethod.invoke(container, request, response, endpointConfig, pathParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -37,7 +37,6 @@ import org.springframework.http.server.ServerHttpRequest;
|
|||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.socket.SubProtocolCapable;
|
||||
import org.springframework.web.socket.WebSocketExtension;
|
||||
|
|
@ -47,65 +46,27 @@ import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
|
|||
import org.springframework.web.socket.server.HandshakeFailureException;
|
||||
import org.springframework.web.socket.server.HandshakeHandler;
|
||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.GlassFishRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.StandardWebSocketUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.UndertowRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.WebLogicRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.WebSphereRequestUpgradeStrategy;
|
||||
|
||||
/**
|
||||
* A base class for {@link HandshakeHandler} implementations, independent of the Servlet API.
|
||||
*
|
||||
* <p>Performs initial validation of the WebSocket handshake request - possibly rejecting it
|
||||
* through the appropriate HTTP status code - while also allowing its subclasses to override
|
||||
* various parts of the negotiation process (for example, origin validation, sub-protocol negotiation,
|
||||
* extensions negotiation, etc).
|
||||
* various parts of the negotiation process: for example, origin validation, sub-protocol
|
||||
* negotiation, extensions negotiation, etc.
|
||||
*
|
||||
* <p>If the negotiation succeeds, the actual upgrade is delegated to a server-specific
|
||||
* {@link org.springframework.web.socket.server.RequestUpgradeStrategy}, which will update
|
||||
* the response as necessary and initialize the WebSocket.
|
||||
* the response as necessary and initialize the WebSocket. As of 7.0, this class uses
|
||||
* {@link StandardWebSocketUpgradeStrategy} unless explicitly configured.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.2
|
||||
* @see org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy
|
||||
* @see org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy
|
||||
* @see org.springframework.web.socket.server.standard.UndertowRequestUpgradeStrategy
|
||||
* @see org.springframework.web.socket.server.standard.GlassFishRequestUpgradeStrategy
|
||||
*/
|
||||
public abstract class AbstractHandshakeHandler implements HandshakeHandler, Lifecycle {
|
||||
|
||||
private static final boolean tomcatWsPresent;
|
||||
|
||||
private static final boolean jettyWsPresent;
|
||||
|
||||
private static final boolean undertowWsPresent;
|
||||
|
||||
private static final boolean glassfishWsPresent;
|
||||
|
||||
private static final boolean weblogicWsPresent;
|
||||
|
||||
private static final boolean websphereWsPresent;
|
||||
|
||||
static {
|
||||
ClassLoader classLoader = AbstractHandshakeHandler.class.getClassLoader();
|
||||
tomcatWsPresent = ClassUtils.isPresent(
|
||||
"org.apache.tomcat.websocket.server.WsHttpUpgradeHandler", classLoader);
|
||||
jettyWsPresent = ClassUtils.isPresent(
|
||||
"org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServerContainer", classLoader);
|
||||
undertowWsPresent = ClassUtils.isPresent(
|
||||
"io.undertow.websockets.jsr.ServerWebSocketContainer", classLoader);
|
||||
glassfishWsPresent = ClassUtils.isPresent(
|
||||
"org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler", classLoader);
|
||||
weblogicWsPresent = ClassUtils.isPresent(
|
||||
"weblogic.websocket.tyrus.TyrusServletWriter", classLoader);
|
||||
websphereWsPresent = ClassUtils.isPresent(
|
||||
"com.ibm.websphere.wsoc.WsWsocServerContainer", classLoader);
|
||||
}
|
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final RequestUpgradeStrategy requestUpgradeStrategy;
|
||||
|
|
@ -116,12 +77,10 @@ public abstract class AbstractHandshakeHandler implements HandshakeHandler, Life
|
|||
|
||||
|
||||
/**
|
||||
* Default constructor that auto-detects and instantiates a
|
||||
* {@link RequestUpgradeStrategy} suitable for the runtime container.
|
||||
* @throws IllegalStateException if no {@link RequestUpgradeStrategy} can be found.
|
||||
* Default constructor that uses {@link StandardWebSocketUpgradeStrategy}.
|
||||
*/
|
||||
protected AbstractHandshakeHandler() {
|
||||
this(initRequestUpgradeStrategy());
|
||||
this(new StandardWebSocketUpgradeStrategy());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -394,45 +353,4 @@ public abstract class AbstractHandshakeHandler implements HandshakeHandler, Life
|
|||
return request.getPrincipal();
|
||||
}
|
||||
|
||||
|
||||
private static RequestUpgradeStrategy initRequestUpgradeStrategy() {
|
||||
if (tomcatWsPresent) {
|
||||
return new TomcatRequestUpgradeStrategy();
|
||||
}
|
||||
else if (jettyWsPresent) {
|
||||
return new JettyRequestUpgradeStrategy();
|
||||
}
|
||||
else if (undertowWsPresent) {
|
||||
return new UndertowRequestUpgradeStrategy();
|
||||
}
|
||||
else if (glassfishWsPresent) {
|
||||
return TyrusStrategyDelegate.forGlassFish();
|
||||
}
|
||||
else if (weblogicWsPresent) {
|
||||
return TyrusStrategyDelegate.forWebLogic();
|
||||
}
|
||||
else if (websphereWsPresent) {
|
||||
return new WebSphereRequestUpgradeStrategy();
|
||||
}
|
||||
else {
|
||||
// Let's assume Jakarta WebSocket API 2.1+
|
||||
return new StandardWebSocketUpgradeStrategy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a reachable dependency on Tyrus API.
|
||||
*/
|
||||
private static class TyrusStrategyDelegate {
|
||||
|
||||
public static RequestUpgradeStrategy forGlassFish() {
|
||||
return new GlassFishRequestUpgradeStrategy();
|
||||
}
|
||||
|
||||
public static RequestUpgradeStrategy forWebLogic() {
|
||||
return new WebLogicRequestUpgradeStrategy();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -18,13 +18,17 @@ package org.springframework.web.socket.server.support;
|
|||
|
||||
import jakarta.servlet.ServletContext;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.StandardWebSocketUpgradeStrategy;
|
||||
|
||||
/**
|
||||
* A default {@link org.springframework.web.socket.server.HandshakeHandler} implementation,
|
||||
* extending {@link AbstractHandshakeHandler} with Servlet-specific initialization support.
|
||||
* See {@link AbstractHandshakeHandler}'s javadoc for details on supported servers etc.
|
||||
* As of 7.0, this class prefers {@link JettyRequestUpgradeStrategy} when Jetty WebSocket
|
||||
* is available on the classpath, using {@link StandardWebSocketUpgradeStrategy} otherwise.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
|
|
@ -32,7 +36,13 @@ import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
|||
*/
|
||||
public class DefaultHandshakeHandler extends AbstractHandshakeHandler implements ServletContextAware {
|
||||
|
||||
private static final boolean jettyWsPresent = ClassUtils.isPresent(
|
||||
"org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServerContainer",
|
||||
DefaultHandshakeHandler.class.getClassLoader());
|
||||
|
||||
|
||||
public DefaultHandshakeHandler() {
|
||||
super(jettyWsPresent ? new JettyRequestUpgradeStrategy() : new StandardWebSocketUpgradeStrategy());
|
||||
}
|
||||
|
||||
public DefaultHandshakeHandler(RequestUpgradeStrategy requestUpgradeStrategy) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -20,7 +20,6 @@ import java.lang.annotation.ElementType;
|
|||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
|
@ -34,16 +33,12 @@ import org.junit.jupiter.params.provider.Arguments;
|
|||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.socket.client.WebSocketClient;
|
||||
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
|
||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.UndertowRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.StandardWebSocketUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
|
||||
|
||||
import static org.junit.jupiter.api.Named.named;
|
||||
|
|
@ -57,11 +52,6 @@ import static org.junit.jupiter.params.provider.Arguments.arguments;
|
|||
*/
|
||||
public abstract class AbstractWebSocketIntegrationTests {
|
||||
|
||||
private static final Map<Class<?>, Class<?>> upgradeStrategyConfigTypes = Map.of(
|
||||
JettyWebSocketTestServer.class, JettyUpgradeStrategyConfig.class,
|
||||
TomcatWebSocketTestServer.class, TomcatUpgradeStrategyConfig.class,
|
||||
UndertowTestServer.class, UndertowUpgradeStrategyConfig.class);
|
||||
|
||||
static Stream<Arguments> argumentsFactory() {
|
||||
return Stream.of(
|
||||
arguments(named("Jetty", new JettyWebSocketTestServer()), named("Standard", new StandardWebSocketClient())),
|
||||
|
|
@ -104,7 +94,8 @@ public abstract class AbstractWebSocketIntegrationTests {
|
|||
|
||||
this.wac = new AnnotationConfigWebApplicationContext();
|
||||
this.wac.register(getAnnotatedConfigClasses());
|
||||
this.wac.register(upgradeStrategyConfigTypes.get(this.server.getClass()));
|
||||
this.wac.register(this.server instanceof JettyWebSocketTestServer ? JettyHandshakeHandler.class :
|
||||
StandardHandshakeHandler.class);
|
||||
|
||||
if (this.webSocketClient instanceof Lifecycle) {
|
||||
((Lifecycle) this.webSocketClient).start();
|
||||
|
|
@ -164,46 +155,18 @@ public abstract class AbstractWebSocketIntegrationTests {
|
|||
}
|
||||
|
||||
|
||||
abstract static class AbstractRequestUpgradeStrategyConfig {
|
||||
private static class JettyHandshakeHandler extends DefaultHandshakeHandler {
|
||||
|
||||
@Bean
|
||||
public DefaultHandshakeHandler handshakeHandler() {
|
||||
return new DefaultHandshakeHandler(requestUpgradeStrategy());
|
||||
}
|
||||
|
||||
public abstract RequestUpgradeStrategy requestUpgradeStrategy();
|
||||
}
|
||||
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class JettyUpgradeStrategyConfig extends AbstractRequestUpgradeStrategyConfig {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public RequestUpgradeStrategy requestUpgradeStrategy() {
|
||||
return new JettyRequestUpgradeStrategy();
|
||||
public JettyHandshakeHandler() {
|
||||
super(new JettyRequestUpgradeStrategy());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TomcatUpgradeStrategyConfig extends AbstractRequestUpgradeStrategyConfig {
|
||||
private static class StandardHandshakeHandler extends DefaultHandshakeHandler {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public RequestUpgradeStrategy requestUpgradeStrategy() {
|
||||
return new TomcatRequestUpgradeStrategy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class UndertowUpgradeStrategyConfig extends AbstractRequestUpgradeStrategyConfig {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public RequestUpgradeStrategy requestUpgradeStrategy() {
|
||||
return new UndertowRequestUpgradeStrategy();
|
||||
public StandardHandshakeHandler() {
|
||||
super(new StandardWebSocketUpgradeStrategy());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,15 +18,13 @@ package org.springframework.web.socket;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.glassfish.tyrus.core.TyrusExtension;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.web.socket.adapter.standard.StandardToWebSocketExtensionAdapter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link WebSocketExtension}
|
||||
* Test fixture for {@link WebSocketExtension}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
class WebSocketExtensionTests {
|
||||
|
|
@ -54,11 +52,4 @@ class WebSocketExtensionTests {
|
|||
.containsExactly("x-foo-extension", "x-bar-extension");
|
||||
}
|
||||
|
||||
@Test // gh-26449
|
||||
public void equality() {
|
||||
WebSocketExtension ext1 = new WebSocketExtension("myExtension");
|
||||
WebSocketExtension ext2 = new StandardToWebSocketExtensionAdapter(new TyrusExtension("myExtension"));
|
||||
|
||||
assertThat(ext1).isEqualTo(ext2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,9 +104,9 @@ class WebSocketHandshakeTests extends AbstractWebSocketIntegrationTests {
|
|||
TestWebSocketHandler handler() {
|
||||
return new TestWebSocketHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class TestWebSocketHandler extends AbstractWebSocketHandler {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient;
|
|||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurationSupport;
|
||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.StandardWebSocketUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
|
@ -144,7 +144,7 @@ class WebSocketStompClientIntegrationTests {
|
|||
@Override
|
||||
protected void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
// Can't rely on classpath detection
|
||||
RequestUpgradeStrategy upgradeStrategy = new TomcatRequestUpgradeStrategy();
|
||||
RequestUpgradeStrategy upgradeStrategy = new StandardWebSocketUpgradeStrategy();
|
||||
registry.addEndpoint("/stomp")
|
||||
.setHandshakeHandler(new DefaultHandshakeHandler(upgradeStrategy))
|
||||
.setAllowedOrigins("*");
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry
|
|||
import org.springframework.web.socket.handler.TextWebSocketHandler;
|
||||
import org.springframework.web.socket.server.HandshakeHandler;
|
||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.StandardWebSocketUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
|
@ -143,7 +144,9 @@ abstract class AbstractSockJsIntegrationTests {
|
|||
}
|
||||
|
||||
|
||||
protected abstract Class<?> upgradeStrategyConfigClass();
|
||||
protected Class<?> upgradeStrategyConfigClass() {
|
||||
return StandardWebSocketUpgradeStrategy.class;
|
||||
}
|
||||
|
||||
protected abstract WebSocketTestServer createWebSocketTestServer();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -18,24 +18,15 @@ package org.springframework.web.socket.sockjs.client;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.UndertowTestServer;
|
||||
import org.springframework.web.socket.WebSocketTestServer;
|
||||
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
|
||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
import org.springframework.web.socket.server.standard.UndertowRequestUpgradeStrategy;
|
||||
|
||||
/**
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
class UndertowSockJsIntegrationTests extends AbstractSockJsIntegrationTests {
|
||||
|
||||
@Override
|
||||
protected Class<?> upgradeStrategyConfigClass() {
|
||||
return UndertowTestConfig.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WebSocketTestServer createWebSocketTestServer() {
|
||||
return new UndertowTestServer();
|
||||
|
|
@ -56,13 +47,4 @@ class UndertowSockJsIntegrationTests extends AbstractSockJsIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class UndertowTestConfig {
|
||||
@Bean
|
||||
RequestUpgradeStrategy upgradeStrategy() {
|
||||
return new UndertowRequestUpgradeStrategy();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue