Remove IOException from HandshakeHandler
This commit is contained in:
parent
2397b21096
commit
13ce20b1ca
|
|
@ -132,50 +132,55 @@ public class DefaultHandshakeHandler implements HandshakeHandler {
|
|||
|
||||
@Override
|
||||
public final boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler webSocketHandler, Map<String, Object> attributes) throws IOException, HandshakeFailureException {
|
||||
WebSocketHandler wsHandler, Map<String, Object> attributes) throws HandshakeFailureException {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Initiating handshake for " + request.getURI() + ", headers=" + request.getHeaders());
|
||||
}
|
||||
|
||||
if (!HttpMethod.GET.equals(request.getMethod())) {
|
||||
response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);
|
||||
response.getHeaders().setAllow(Collections.singleton(HttpMethod.GET));
|
||||
logger.debug("Only HTTP GET is allowed, current method is " + request.getMethod());
|
||||
return false;
|
||||
try {
|
||||
if (!HttpMethod.GET.equals(request.getMethod())) {
|
||||
response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);
|
||||
response.getHeaders().setAllow(Collections.singleton(HttpMethod.GET));
|
||||
logger.debug("Only HTTP GET is allowed, current method is " + request.getMethod());
|
||||
return false;
|
||||
}
|
||||
if (!"WebSocket".equalsIgnoreCase(request.getHeaders().getUpgrade())) {
|
||||
handleInvalidUpgradeHeader(request, response);
|
||||
return false;
|
||||
}
|
||||
if (!request.getHeaders().getConnection().contains("Upgrade") &&
|
||||
!request.getHeaders().getConnection().contains("upgrade")) {
|
||||
handleInvalidConnectHeader(request, response);
|
||||
return false;
|
||||
}
|
||||
if (!isWebSocketVersionSupported(request)) {
|
||||
handleWebSocketVersionNotSupported(request, response);
|
||||
return false;
|
||||
}
|
||||
if (!isValidOrigin(request)) {
|
||||
response.setStatusCode(HttpStatus.FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
String wsKey = request.getHeaders().getSecWebSocketKey();
|
||||
if (wsKey == null) {
|
||||
logger.debug("Missing \"Sec-WebSocket-Key\" header");
|
||||
response.setStatusCode(HttpStatus.BAD_REQUEST);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!"WebSocket".equalsIgnoreCase(request.getHeaders().getUpgrade())) {
|
||||
handleInvalidUpgradeHeader(request, response);
|
||||
return false;
|
||||
}
|
||||
if (!request.getHeaders().getConnection().contains("Upgrade") &&
|
||||
!request.getHeaders().getConnection().contains("upgrade")) {
|
||||
handleInvalidConnectHeader(request, response);
|
||||
return false;
|
||||
}
|
||||
if (!isWebSocketVersionSupported(request)) {
|
||||
handleWebSocketVersionNotSupported(request, response);
|
||||
return false;
|
||||
}
|
||||
if (!isValidOrigin(request)) {
|
||||
response.setStatusCode(HttpStatus.FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
String wsKey = request.getHeaders().getSecWebSocketKey();
|
||||
if (wsKey == null) {
|
||||
logger.debug("Missing \"Sec-WebSocket-Key\" header");
|
||||
response.setStatusCode(HttpStatus.BAD_REQUEST);
|
||||
return false;
|
||||
catch (IOException ex) {
|
||||
throw new HandshakeFailureException(
|
||||
"Response update failed during upgrade to WebSocket, uri=" + request.getURI(), ex);
|
||||
}
|
||||
|
||||
String selectedProtocol = selectProtocol(request.getHeaders().getSecWebSocketProtocol());
|
||||
// TODO: select extensions
|
||||
String subProtocol = selectProtocol(request.getHeaders().getSecWebSocketProtocol());
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Upgrading request");
|
||||
logger.debug("Upgrading request, sub-protocol=" + subProtocol);
|
||||
}
|
||||
|
||||
this.requestUpgradeStrategy.upgrade(request, response, selectedProtocol, webSocketHandler, attributes);
|
||||
this.requestUpgradeStrategy.upgrade(request, response, subProtocol, wsHandler, attributes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,12 +34,19 @@ import org.springframework.core.NestedRuntimeException;
|
|||
@SuppressWarnings("serial")
|
||||
public class HandshakeFailureException extends NestedRuntimeException {
|
||||
|
||||
public HandshakeFailureException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
|
||||
/**
|
||||
* Constructor with message and root cause.
|
||||
*/
|
||||
public HandshakeFailureException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public HandshakeFailureException(String msg) {
|
||||
super(msg);
|
||||
/**
|
||||
* Constructor without a message.
|
||||
*/
|
||||
public HandshakeFailureException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.web.socket.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
|
|
@ -36,6 +35,7 @@ import org.springframework.web.socket.support.PerConnectionWebSocketHandler;
|
|||
*/
|
||||
public interface HandshakeHandler {
|
||||
|
||||
|
||||
/**
|
||||
* Initiate the handshake.
|
||||
*
|
||||
|
|
@ -51,14 +51,11 @@ public interface HandshakeHandler {
|
|||
* response status, headers, and body will have been updated to reflect the
|
||||
* result of the negotiation
|
||||
*
|
||||
* @throws IOException thrown when accessing or setting the response
|
||||
*
|
||||
* @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
|
||||
* handshake request.
|
||||
* opposed to a failure to successfully negotiate the handshake.
|
||||
*/
|
||||
boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
|
||||
Map<String, Object> attributes) throws IOException, HandshakeFailureException;
|
||||
Map<String, Object> attributes) throws HandshakeFailureException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.web.socket.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
|
|
@ -53,6 +52,6 @@ public interface RequestUpgradeStrategy {
|
|||
* handshake request.
|
||||
*/
|
||||
void upgrade(ServerHttpRequest request, ServerHttpResponse response, String acceptedProtocol,
|
||||
WebSocketHandler wsHandler, Map<String, Object> attributes) throws IOException, HandshakeFailureException;
|
||||
WebSocketHandler wsHandler, Map<String, Object> attributes) throws HandshakeFailureException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.web.socket.server.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -34,7 +33,8 @@ import org.springframework.web.socket.server.HandshakeFailureException;
|
|||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
|
||||
/**
|
||||
* A {@link RequestUpgradeStrategy} for containers that support standard Java WebSocket.
|
||||
* A base class for {@link RequestUpgradeStrategy} implementations that build on the
|
||||
* standard WebSocket API for Java.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
|
|
@ -46,20 +46,20 @@ public abstract class AbstractStandardUpgradeStrategy implements RequestUpgradeS
|
|||
|
||||
@Override
|
||||
public void upgrade(ServerHttpRequest request, ServerHttpResponse response, String acceptedProtocol,
|
||||
WebSocketHandler wsHandler, Map<String, Object> attributes)
|
||||
throws IOException, HandshakeFailureException {
|
||||
WebSocketHandler wsHandler, Map<String, Object> attributes) throws HandshakeFailureException {
|
||||
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
|
||||
InetSocketAddress localAddr = request.getLocalAddress();
|
||||
InetSocketAddress remoteAddr = request.getRemoteAddress();
|
||||
|
||||
StandardWebSocketSession wsSession = new StandardWebSocketSession(headers, attributes, localAddr, remoteAddr);
|
||||
StandardWebSocketHandlerAdapter endpoint = new StandardWebSocketHandlerAdapter(wsHandler, wsSession);
|
||||
StandardWebSocketSession session = new StandardWebSocketSession(headers, attributes, localAddr, remoteAddr);
|
||||
StandardWebSocketHandlerAdapter endpoint = new StandardWebSocketHandlerAdapter(wsHandler, session);
|
||||
|
||||
upgradeInternal(request, response, acceptedProtocol, endpoint);
|
||||
}
|
||||
|
||||
protected abstract void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String selectedProtocol, Endpoint endpoint) throws IOException, HandshakeFailureException;
|
||||
String selectedProtocol, Endpoint endpoint) throws HandshakeFailureException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class GlassFishRequestUpgradeStrategy extends AbstractStandardUpgradeStra
|
|||
|
||||
@Override
|
||||
public void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String selectedProtocol, Endpoint endpoint) throws IOException, HandshakeFailureException {
|
||||
String selectedProtocol, Endpoint endpoint) throws HandshakeFailureException {
|
||||
|
||||
Assert.isTrue(request instanceof ServletServerHttpRequest);
|
||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||
|
|
@ -85,12 +85,16 @@ public class GlassFishRequestUpgradeStrategy extends AbstractStandardUpgradeStra
|
|||
webSocketEngine.register(webSocketApplication);
|
||||
}
|
||||
catch (DeploymentException ex) {
|
||||
throw new HandshakeFailureException("Failed to deploy endpoint in GlassFish", ex);
|
||||
throw new HandshakeFailureException("Failed to configure endpoint in GlassFish", ex);
|
||||
}
|
||||
|
||||
try {
|
||||
performUpgrade(servletRequest, servletResponse, request.getHeaders(), webSocketApplication);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new HandshakeFailureException(
|
||||
"Response update failed during upgrade to WebSocket, uri=" + request.getURI(), ex);
|
||||
}
|
||||
finally {
|
||||
webSocketEngine.unregister(webSocketApplication);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,30 +44,26 @@ import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
|||
* {@code org.eclipse.jetty.websocket.server.WebSocketHandler} class.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
|
||||
|
||||
// FIXME jetty has options, timeouts etc. Do we need a common abstraction
|
||||
|
||||
// FIXME need a way for someone to plug their own RequestUpgradeStrategy or override
|
||||
// Jetty settings
|
||||
|
||||
// FIXME when to call factory.cleanup();
|
||||
|
||||
private static final String WEBSOCKET_LISTENER_ATTR_NAME = JettyRequestUpgradeStrategy.class.getName()
|
||||
+ ".HANDLER_PROVIDER";
|
||||
private static final String WS_HANDLER_ATTR_NAME = JettyRequestUpgradeStrategy.class.getName() + ".WS_LISTENER";
|
||||
|
||||
private WebSocketServerFactory factory;
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public JettyRequestUpgradeStrategy() {
|
||||
this.factory = new WebSocketServerFactory();
|
||||
this.factory.setCreator(new WebSocketCreator() {
|
||||
@Override
|
||||
public Object createWebSocket(UpgradeRequest request, UpgradeResponse response) {
|
||||
Assert.isInstanceOf(ServletUpgradeRequest.class, request);
|
||||
return ((ServletUpgradeRequest) request).getServletAttributes().get(WEBSOCKET_LISTENER_ATTR_NAME);
|
||||
return ((ServletUpgradeRequest) request).getServletAttributes().get(WS_HANDLER_ATTR_NAME);
|
||||
}
|
||||
});
|
||||
try {
|
||||
|
|
@ -86,7 +82,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
|
|||
|
||||
@Override
|
||||
public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String protocol, WebSocketHandler wsHandler, Map<String, Object> attrs) throws IOException {
|
||||
String protocol, WebSocketHandler wsHandler, Map<String, Object> attrs) throws HandshakeFailureException {
|
||||
|
||||
Assert.isInstanceOf(ServletServerHttpRequest.class, request);
|
||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||
|
|
@ -94,19 +90,21 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
|
|||
Assert.isInstanceOf(ServletServerHttpResponse.class, response);
|
||||
HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse();
|
||||
|
||||
if (!this.factory.isUpgradeRequest(servletRequest, servletResponse)) {
|
||||
// should never happen
|
||||
throw new HandshakeFailureException("Not a WebSocket request");
|
||||
Assert.isTrue(this.factory.isUpgradeRequest(servletRequest, servletResponse), "Not a WebSocket handshake");
|
||||
|
||||
JettyWebSocketSession session = new JettyWebSocketSession(request.getPrincipal(), attrs);
|
||||
JettyWebSocketHandlerAdapter handlerAdapter = new JettyWebSocketHandlerAdapter(wsHandler, session);
|
||||
|
||||
try {
|
||||
servletRequest.setAttribute(WS_HANDLER_ATTR_NAME, handlerAdapter);
|
||||
this.factory.acceptWebSocket(servletRequest, servletResponse);
|
||||
}
|
||||
|
||||
JettyWebSocketSession wsSession = new JettyWebSocketSession(request.getPrincipal(), attrs);
|
||||
JettyWebSocketHandlerAdapter wsListener = new JettyWebSocketHandlerAdapter(wsHandler, wsSession);
|
||||
|
||||
servletRequest.setAttribute(WEBSOCKET_LISTENER_ATTR_NAME, wsListener);
|
||||
|
||||
if (!this.factory.acceptWebSocket(servletRequest, servletResponse)) {
|
||||
// should not happen
|
||||
throw new HandshakeFailureException("WebSocket request not accepted by Jetty");
|
||||
catch (IOException ex) {
|
||||
throw new HandshakeFailureException(
|
||||
"Response update failed during upgrade to WebSocket, uri=" + request.getURI(), ex);
|
||||
}
|
||||
finally {
|
||||
servletRequest.removeAttribute(WS_HANDLER_ATTR_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@
|
|||
|
||||
package org.springframework.web.socket.server.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.websocket.Endpoint;
|
||||
|
|
@ -67,8 +69,13 @@ public class TomcatRequestUpgradeStrategy extends AbstractStandardUpgradeStrateg
|
|||
try {
|
||||
getContainer(servletRequest).doUpgrade(servletRequest, servletResponse, endpointConfig, pathParams);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new HandshakeFailureException("Failed to upgrade HttpServletRequest", ex);
|
||||
catch (ServletException ex) {
|
||||
throw new HandshakeFailureException(
|
||||
"Servlet request failed to upgrade to WebSocket, uri=" + request.getURI(), ex);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new HandshakeFailureException(
|
||||
"Response update failed during upgrade to WebSocket, uri=" + request.getURI(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ public class SockJsException extends NestedRuntimeException {
|
|||
private final String sessionId;
|
||||
|
||||
|
||||
public SockJsException(String message, Throwable cause) {
|
||||
this(message, null, cause);
|
||||
}
|
||||
|
||||
public SockJsException(String message, String sessionId, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.sessionId = sessionId;
|
||||
|
|
|
|||
|
|
@ -74,10 +74,15 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler {
|
|||
public void handleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
|
||||
throws ServletException, IOException {
|
||||
|
||||
ServerHttpRequest serverRequest = new ServletServerHttpRequest(servletRequest);
|
||||
ServerHttpResponse serverResponse = new ServletServerHttpResponse(servletResponse);
|
||||
ServerHttpRequest request = new ServletServerHttpRequest(servletRequest);
|
||||
ServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
|
||||
this.sockJsService.handleRequest(serverRequest, serverResponse, this.webSocketHandler);
|
||||
try {
|
||||
this.sockJsService.handleRequest(request, response, this.webSocketHandler);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw new SockJsException("Uncaught failure in SockJS request, uri=" + request.getURI(), t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.web.socket.sockjs.transport.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -26,6 +25,7 @@ import org.springframework.util.Assert;
|
|||
import org.springframework.web.socket.CloseStatus;
|
||||
import org.springframework.web.socket.WebSocketHandler;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
import org.springframework.web.socket.server.HandshakeFailureException;
|
||||
import org.springframework.web.socket.server.HandshakeHandler;
|
||||
import org.springframework.web.socket.sockjs.SockJsException;
|
||||
import org.springframework.web.socket.sockjs.SockJsTransportFailureException;
|
||||
|
|
@ -35,7 +35,7 @@ import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSes
|
|||
import org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession;
|
||||
|
||||
/**
|
||||
* A WebSocket {@link TransportHandler}. Uses {@link SockJsWebSocketHandler} and
|
||||
* WebSocket-based {@link TransportHandler}. Uses {@link SockJsWebSocketHandler} and
|
||||
* {@link WebSocketServerSockJsSession} to add SockJS processing.
|
||||
*
|
||||
* <p>Also implements {@link HandshakeHandler} to support raw WebSocket communication at
|
||||
|
|
@ -87,7 +87,7 @@ public class WebSocketTransportHandler extends TransportHandlerSupport
|
|||
|
||||
@Override
|
||||
public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler handler, Map<String, Object> attributes) throws IOException {
|
||||
WebSocketHandler handler, Map<String, Object> attributes) throws HandshakeFailureException {
|
||||
|
||||
return this.handshakeHandler.doHandshake(request, response, handler, attributes);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue