Skip to content

Commit

Permalink
HttpSessionHandshakeInterceptor and related web.socket.server polishing
Browse files Browse the repository at this point in the history
Issue: SPR-12352
  • Loading branch information
jhoeller committed Oct 20, 2014
1 parent 716916b commit b6fdcff
Show file tree
Hide file tree
Showing 21 changed files with 158 additions and 235 deletions.
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://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,
Expand Down Expand Up @@ -34,18 +34,12 @@
@SuppressWarnings("serial")
public class HandshakeFailureException extends NestedRuntimeException {

/**
* Constructor with message and root cause.
*/
public HandshakeFailureException(String message, Throwable cause) {
super(message, cause);
}

/**
* Constructor without a message.
*/
public HandshakeFailureException(String message) {
super(message);
}

public HandshakeFailureException(String message, Throwable cause) {
super(message, cause);
}

}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://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,
Expand All @@ -28,7 +28,6 @@
*
* @author Rossen Stoyanchev
* @since 4.0
*
* @see HandshakeInterceptor
* @see org.springframework.web.socket.server.support.WebSocketHttpRequestHandler
* @see org.springframework.web.socket.sockjs.SockJsService
Expand All @@ -37,19 +36,16 @@ public interface HandshakeHandler {

/**
* Initiate the handshake.
*
* @param request the current request
* @param response the current response
* @param wsHandler the handler to process WebSocket messages; see
* {@link PerConnectionWebSocketHandler} for providing a handler with
* per-connection lifecycle.
* @param attributes attributes from the HTTP handshake to associate with the WebSocket
* session; the provided attributes are copied, the original map is not used.
*
* @return whether the handshake negotiation was successful or not. In either case the
* response status, headers, and body will have been updated to reflect the
* result of the negotiation
*
* @throws HandshakeFailureException thrown when handshake processing failed to
* complete due to an internal, unrecoverable error, i.e. a server error as
* opposed to a failure to successfully negotiate the handshake.
Expand Down
Expand Up @@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://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,
Expand Down Expand Up @@ -41,18 +41,18 @@ public interface HandshakeInterceptor {
* @param wsHandler the target WebSocket handler
* @param attributes attributes from the HTTP handshake to associate with the WebSocket
* session; the provided attributes are copied, the original map is not used.
* @return whether to proceed with the handshake {@code true} or abort {@code false}
* @return whether to proceed with the handshake ({@code true}) or abort ({@code false})
*/
boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception;

/**
* Invoked after the handshake is done. The response status and headers indicate the
* results of the handshake, i.e. whether it was successful or not.
* Invoked after the handshake is done. The response status and headers indicate
* the results of the handshake, i.e. whether it was successful or not.
* @param request the current request
* @param response the current response
* @param wsHandler the target WebSocket handler
* @param exception an exception raised during the handshake, or {@code null}
* @param exception an exception raised during the handshake, or {@code null} if none
*/
void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Exception exception);
Expand Down
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://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,
Expand Down Expand Up @@ -39,7 +39,7 @@ public interface RequestUpgradeStrategy {
String[] getSupportedVersions();

/**
* @return the WebSocket protocol extensions supported by the underlying WebSocket server.
* Return the WebSocket protocol extensions supported by the underlying WebSocket server.
*/
List<WebSocketExtension> getSupportedExtensions(ServerHttpRequest request);

Expand All @@ -53,9 +53,8 @@ public interface RequestUpgradeStrategy {
* @param user the user to associate with the WebSocket session
* @param wsHandler the handler for WebSocket messages
* @param attributes handshake request specific attributes to be set on the WebSocket
* session via {@link org.springframework.web.socket.server.HandshakeInterceptor}
* and thus made available to the
* {@link org.springframework.web.socket.WebSocketHandler};
* session via {@link org.springframework.web.socket.server.HandshakeInterceptor} and
* thus made available to the {@link org.springframework.web.socket.WebSocketHandler}
* @throws HandshakeFailureException thrown when handshake processing failed to
* complete due to an internal, unrecoverable error, i.e. a server error as
* opposed to a failure to successfully negotiate the requirements of the
Expand Down
Expand Up @@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://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,
Expand Down Expand Up @@ -63,7 +63,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
new NamedThreadLocal<WebSocketHandlerContainer>("WebSocket Handler Container");


private WebSocketServerFactory factory;
private final WebSocketServerFactory factory;

private volatile List<WebSocketExtension> supportedExtensions;

Expand Down
@@ -1,21 +1,4 @@
/*
* Copyright 2002-2013 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
*
* http://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.
*/

/**
* Server-side support for the Jetty WebSocket API.
* Server-side support for the Jetty 9+ WebSocket API.
*/
package org.springframework.web.socket.server.jetty;

@@ -1,21 +1,4 @@
/*
* Copyright 2002-2013 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
*
* http://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.
*/

/**
* Server-side abstractions for WebSocket interactions.
*/
package org.springframework.web.socket.server;

Expand Up @@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://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,
Expand Down Expand Up @@ -112,15 +112,15 @@ public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
StandardWebSocketHandlerAdapter endpoint = new StandardWebSocketHandlerAdapter(wsHandler, session);

List<Extension> extensions = new ArrayList<Extension>();
for (WebSocketExtension e : selectedExtensions) {
extensions.add(new WebSocketToStandardExtensionAdapter(e));
for (WebSocketExtension extension : selectedExtensions) {
extensions.add(new WebSocketToStandardExtensionAdapter(extension));
}

upgradeInternal(request, response, selectedProtocol, extensions, endpoint);
}

protected abstract void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,
String selectedProtocol, List<Extension> selectedExtensions,
Endpoint endpoint) throws HandshakeFailureException;
String selectedProtocol, List<Extension> selectedExtensions, Endpoint endpoint)
throws HandshakeFailureException;

}
Expand Up @@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://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,
Expand All @@ -16,6 +16,23 @@

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.Arrays;
import java.util.List;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.DeploymentException;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.Extension;
import javax.websocket.WebSocketContainer;

import org.glassfish.tyrus.core.ComponentProviderService;
import org.glassfish.tyrus.core.RequestContext;
import org.glassfish.tyrus.core.TyrusEndpoint;
Expand All @@ -26,6 +43,7 @@
import org.glassfish.tyrus.core.WebSocketApplication;
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;
Expand All @@ -35,23 +53,6 @@
import org.springframework.web.socket.WebSocketExtension;
import org.springframework.web.socket.server.HandshakeFailureException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.DeploymentException;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.Extension;
import javax.websocket.WebSocketContainer;
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.Arrays;
import java.util.List;
import java.util.Random;

/**
* An base class for WebSocket servers using Tyrus.
*
Expand All @@ -65,7 +66,6 @@ public abstract class AbstractTyrusRequestUpgradeStrategy extends AbstractStanda

private static final Random random = new Random();


private final ComponentProviderService componentProvider = ComponentProviderService.create();


Expand All @@ -78,17 +78,15 @@ protected List<WebSocketExtension> getInstalledExtensions(WebSocketContainer con
try {
return super.getInstalledExtensions(container);
}
catch (UnsupportedOperationException e) {
return new ArrayList<WebSocketExtension>();
catch (UnsupportedOperationException ex) {
return new ArrayList<WebSocketExtension>(0);
}
}

protected abstract TyrusEndpointHelper getEndpointHelper();


@Override
public void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,
String subProtocol, List<Extension> extensions, Endpoint endpoint) throws HandshakeFailureException {
String selectedProtocol, List<Extension> extensions, Endpoint endpoint)
throws HandshakeFailureException {

HttpServletRequest servletRequest = getHttpServletRequest(request);
HttpServletResponse servletResponse = getHttpServletResponse(response);
Expand All @@ -100,7 +98,7 @@ public void upgradeInternal(ServerHttpRequest request, ServerHttpResponse respon
try {
// Shouldn't matter for processing but must be unique
String path = "/" + random.nextLong();
tyrusEndpoint = createTyrusEndpoint(endpoint, path, subProtocol, extensions, serverContainer, engine);
tyrusEndpoint = createTyrusEndpoint(endpoint, path, selectedProtocol, extensions, serverContainer, engine);
getEndpointHelper().register(engine, tyrusEndpoint);

HttpHeaders headers = request.getHeaders();
Expand Down Expand Up @@ -133,9 +131,6 @@ public void upgradeInternal(ServerHttpRequest request, ServerHttpResponse respon
}
}

protected abstract void handleSuccess(HttpServletRequest request, HttpServletResponse response,
UpgradeInfo upgradeInfo, TyrusUpgradeResponse upgradeResponse) throws IOException, ServletException;

private Object createTyrusEndpoint(Endpoint endpoint, String endpointPath, String protocol,
List<Extension> extensions, WebSocketContainer container, TyrusWebSocketEngine engine)
throws DeploymentException {
Expand All @@ -161,6 +156,12 @@ private RequestContext createRequestContext(HttpServletRequest request, String e
}


protected abstract TyrusEndpointHelper getEndpointHelper();

protected abstract void handleSuccess(HttpServletRequest request, HttpServletResponse response,
UpgradeInfo upgradeInfo, TyrusUpgradeResponse upgradeResponse) throws IOException, ServletException;


/**
* Helps with the creation, registration, and un-registration of endpoints.
*/
Expand All @@ -172,9 +173,9 @@ Object createdEndpoint(ServerEndpointRegistration registration, ComponentProvide
void register(TyrusWebSocketEngine engine, Object endpoint);

void unregister(TyrusWebSocketEngine engine, Object endpoint);

}


protected static class Tyrus17EndpointHelper implements TyrusEndpointHelper {

private static final Constructor<?> constructor;
Expand Down Expand Up @@ -243,6 +244,7 @@ public void unregister(TyrusWebSocketEngine engine, Object endpoint) {
}
}


protected static class Tyrus135EndpointHelper implements TyrusEndpointHelper {

private static final Method registerMethod;
Expand Down

0 comments on commit b6fdcff

Please sign in to comment.