Refactor and polish SockJS package structure
After this change the top-level sockjs package contains the main types for use in applications.
This commit is contained in:
parent
dad7115c23
commit
ad40ecff4b
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
|
||||||
|
|
||||||
import org.springframework.scheduling.TaskScheduler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SockJS configuration options that need to be made available to {@link TransportHandler}
|
|
||||||
* s and SockJS sessions.
|
|
||||||
*
|
|
||||||
* @author Rossen Stoyanchev
|
|
||||||
* @since 4.0
|
|
||||||
*/
|
|
||||||
public interface SockJsConfiguration {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Streaming transports save responses on the client side and don't free
|
|
||||||
* memory used by delivered messages. Such transports need to recycle the
|
|
||||||
* connection once in a while. This property sets a minimum number of bytes
|
|
||||||
* that can be send over a single HTTP streaming request before it will be
|
|
||||||
* closed. After that client will open a new request. Setting this value to
|
|
||||||
* one effectively disables streaming and will make streaming transports to
|
|
||||||
* behave like polling transports.
|
|
||||||
*
|
|
||||||
* <p>The default value is 128K (i.e. 128 * 1024).
|
|
||||||
*/
|
|
||||||
int getStreamBytesLimit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The amount of time in milliseconds when the server has not sent any
|
|
||||||
* messages and after which the server should send a heartbeat frame to the
|
|
||||||
* client in order to keep the connection from breaking.
|
|
||||||
*
|
|
||||||
* <p>The default value is 25,000 (25 seconds).
|
|
||||||
*/
|
|
||||||
long getHeartbeatTime();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A scheduler instance to use for scheduling heart-beat messages.
|
|
||||||
*/
|
|
||||||
TaskScheduler getTaskScheduler();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The codec to use for encoding and decoding SockJS messages.
|
|
||||||
* @exception IllegalStateException if no {@link SockJsMessageCodec} is available
|
|
||||||
*/
|
|
||||||
SockJsMessageCodec getMessageCodecRequired();
|
|
||||||
|
|
||||||
}
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.support;
|
package org.springframework.web.socket.sockjs;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -29,20 +29,12 @@ import org.springframework.http.server.ServletServerHttpResponse;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.HttpRequestHandler;
|
import org.springframework.web.HttpRequestHandler;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsService;
|
|
||||||
import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator;
|
import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator;
|
||||||
import org.springframework.web.socket.support.LoggingWebSocketHandlerDecorator;
|
import org.springframework.web.socket.support.LoggingWebSocketHandlerDecorator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link HttpRequestHandler} for processing SockJS requests. This is the main class
|
* An {@link HttpRequestHandler} that allows mapping a {@link SockJsService} to requests
|
||||||
* to use when configuring a SockJS service at a specific URL. It is a very thin wrapper
|
* in a Servlet container.
|
||||||
* around a {@link SockJsService} and a {@link WebSocketHandler} instance also adapting
|
|
||||||
* the {@link HttpServletRequest} and {@link HttpServletResponse} to
|
|
||||||
* {@link ServerHttpRequest} and {@link ServerHttpResponse} respectively.
|
|
||||||
*
|
|
||||||
* <p>The {@link #decorateWebSocketHandler(WebSocketHandler)} method decorates the given
|
|
||||||
* WebSocketHandler with a logging and exception handling decorators. This method can be
|
|
||||||
* overridden to change that.
|
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
|
@ -17,37 +17,31 @@
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs;
|
||||||
|
|
||||||
import org.springframework.core.NestedRuntimeException;
|
import org.springframework.core.NestedRuntimeException;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raised when a TransportHandler fails during request processing. If the underlying
|
* Raised when SockJS request handling fails.
|
||||||
* exception occurs while sending messages to the client, the session is closed and the
|
|
||||||
* {@link WebSocketHandler} notified.
|
|
||||||
*
|
|
||||||
* <p>If the underlying exception occurs while processing an incoming HTTP request,
|
|
||||||
* including over HTTP POST, the session will remain open. Only the incoming request is
|
|
||||||
* rejected.
|
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class TransportErrorException extends NestedRuntimeException {
|
public class SockJsProcessingException extends NestedRuntimeException {
|
||||||
|
|
||||||
private final String sockJsSessionId;
|
private final String sessionId;
|
||||||
|
|
||||||
public TransportErrorException(String msg, Throwable cause, String sockJsSessionId) {
|
|
||||||
|
public SockJsProcessingException(String msg, Throwable cause, String sessionId) {
|
||||||
super(msg, cause);
|
super(msg, cause);
|
||||||
this.sockJsSessionId = sockJsSessionId;
|
this.sessionId = sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSockJsSessionId() {
|
public String getSockJsSessionId() {
|
||||||
return this.sockJsSessionId;
|
return this.sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return "Transport error for SockJS session id=" + this.sockJsSessionId + ", " + super.getMessage();
|
return "Transport error for SockJS session id=" + this.sessionId + ", " + super.getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -23,16 +23,17 @@ import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service for processing SockJS requests.
|
* A service for processing SockJS HTTP requests.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*
|
*
|
||||||
* @see org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler
|
* @see SockJsHttpRequestHandler
|
||||||
*/
|
*/
|
||||||
public interface SockJsService {
|
public interface SockJsService {
|
||||||
|
|
||||||
|
|
||||||
void handleRequest(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler)
|
void handleRequest(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler)
|
||||||
throws IOException, TransportErrorException;
|
throws IOException, SockJsProcessingException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common abstractions for the SockJS protocol.
|
* Top-level SockJS types.
|
||||||
*/
|
*/
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.support;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
@ -44,6 +44,8 @@ import org.springframework.util.DigestUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
|
import org.springframework.web.socket.sockjs.SockJsService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract base class for {@link SockJsService} implementations that provides SockJS
|
* An abstract base class for {@link SockJsService} implementations that provides SockJS
|
||||||
|
@ -63,7 +65,7 @@ import org.springframework.web.socket.WebSocketHandler;
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractSockJsService implements SockJsService, SockJsConfiguration {
|
public abstract class AbstractSockJsService implements SockJsService {
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
@ -153,9 +155,8 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
* <p>By default this is set to point to
|
* <p>By default this is set to point to
|
||||||
* "https://d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.4.min.js".
|
* "https://d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.4.min.js".
|
||||||
*/
|
*/
|
||||||
public AbstractSockJsService setSockJsClientLibraryUrl(String clientLibraryUrl) {
|
public void setSockJsClientLibraryUrl(String clientLibraryUrl) {
|
||||||
this.clientLibraryUrl = clientLibraryUrl;
|
this.clientLibraryUrl = clientLibraryUrl;
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,12 +167,21 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
return this.clientLibraryUrl;
|
return this.clientLibraryUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractSockJsService setStreamBytesLimit(int streamBytesLimit) {
|
/**
|
||||||
|
* Streaming transports save responses on the client side and don't free
|
||||||
|
* memory used by delivered messages. Such transports need to recycle the
|
||||||
|
* connection once in a while. This property sets a minimum number of bytes
|
||||||
|
* that can be send over a single HTTP streaming request before it will be
|
||||||
|
* closed. After that client will open a new request. Setting this value to
|
||||||
|
* one effectively disables streaming and will make streaming transports to
|
||||||
|
* behave like polling transports.
|
||||||
|
*
|
||||||
|
* <p>The default value is 128K (i.e. 128 * 1024).
|
||||||
|
*/
|
||||||
|
public void setStreamBytesLimit(int streamBytesLimit) {
|
||||||
this.streamBytesLimit = streamBytesLimit;
|
this.streamBytesLimit = streamBytesLimit;
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getStreamBytesLimit() {
|
public int getStreamBytesLimit() {
|
||||||
return this.streamBytesLimit;
|
return this.streamBytesLimit;
|
||||||
}
|
}
|
||||||
|
@ -184,9 +194,8 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
* <p>Set this option to indicate if a JSESSIONID cookie should be created. The
|
* <p>Set this option to indicate if a JSESSIONID cookie should be created. The
|
||||||
* default value is "true".
|
* default value is "true".
|
||||||
*/
|
*/
|
||||||
public AbstractSockJsService setJsessionIdCookieRequired(boolean jsessionIdCookieRequired) {
|
public void setJsessionIdCookieRequired(boolean jsessionIdCookieRequired) {
|
||||||
this.jsessionIdCookieRequired = jsessionIdCookieRequired;
|
this.jsessionIdCookieRequired = jsessionIdCookieRequired;
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,17 +206,24 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
return this.jsessionIdCookieRequired;
|
return this.jsessionIdCookieRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractSockJsService setHeartbeatTime(long heartbeatTime) {
|
/**
|
||||||
|
* The amount of time in milliseconds when the server has not sent any
|
||||||
|
* messages and after which the server should send a heartbeat frame to the
|
||||||
|
* client in order to keep the connection from breaking.
|
||||||
|
*
|
||||||
|
* <p>The default value is 25,000 (25 seconds).
|
||||||
|
*/
|
||||||
|
public void setHeartbeatTime(long heartbeatTime) {
|
||||||
this.heartbeatTime = heartbeatTime;
|
this.heartbeatTime = heartbeatTime;
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getHeartbeatTime() {
|
public long getHeartbeatTime() {
|
||||||
return this.heartbeatTime;
|
return this.heartbeatTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* A scheduler instance to use for scheduling heart-beat messages.
|
||||||
|
*/
|
||||||
public TaskScheduler getTaskScheduler() {
|
public TaskScheduler getTaskScheduler() {
|
||||||
return this.taskScheduler;
|
return this.taskScheduler;
|
||||||
}
|
}
|
||||||
|
@ -253,7 +269,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler)
|
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler)
|
||||||
throws IOException, TransportErrorException {
|
throws IOException, SockJsProcessingException {
|
||||||
|
|
||||||
String sockJsPath = getSockJsPath(request);
|
String sockJsPath = getSockJsPath(request);
|
||||||
if (sockJsPath == null) {
|
if (sockJsPath == null) {
|
||||||
|
@ -307,7 +323,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTransportRequest(request, response, sessionId, TransportType.fromValue(transport), handler);
|
handleTransportRequest(request, response, handler, sessionId, transport);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
response.flush();
|
response.flush();
|
||||||
|
@ -321,7 +337,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
|
|
||||||
String path = request.getURI().getPath();
|
String path = request.getURI().getPath();
|
||||||
|
|
||||||
// SockJS prefix hints?
|
// Try SockJS prefix hints
|
||||||
if (!this.validSockJsPrefixes.isEmpty()) {
|
if (!this.validSockJsPrefixes.isEmpty()) {
|
||||||
for (String prefix : this.validSockJsPrefixes) {
|
for (String prefix : this.validSockJsPrefixes) {
|
||||||
int index = path.indexOf(prefix);
|
int index = path.indexOf(prefix);
|
||||||
|
@ -333,7 +349,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SockJS info request?
|
// Try SockJS info request
|
||||||
if (path.endsWith("/info")) {
|
if (path.endsWith("/info")) {
|
||||||
this.knownSockJsPrefixes.add(path.substring(0, path.length() - "/info".length()));
|
this.knownSockJsPrefixes.add(path.substring(0, path.length() - "/info".length()));
|
||||||
return "/info";
|
return "/info";
|
||||||
|
@ -357,11 +373,11 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SockJS greeting?
|
// Try SockJS greeting
|
||||||
String pathNoSlash = path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
|
String pathNoSlash = path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
|
||||||
String lastSegment = pathNoSlash.substring(pathNoSlash.lastIndexOf('/') + 1);
|
String lastSegment = pathNoSlash.substring(pathNoSlash.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
if ((TransportType.fromValue(lastSegment) == null) && !lastSegment.startsWith("iframe")) {
|
if (!isValidTransportType(lastSegment) && !lastSegment.startsWith("iframe")) {
|
||||||
this.knownSockJsPrefixes.add(path);
|
this.knownSockJsPrefixes.add(path);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -369,12 +385,14 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract boolean isValidTransportType(String transportType);
|
||||||
|
|
||||||
protected abstract void handleRawWebSocketRequest(ServerHttpRequest request,
|
protected abstract void handleRawWebSocketRequest(ServerHttpRequest request,
|
||||||
ServerHttpResponse response, WebSocketHandler webSocketHandler) throws IOException;
|
ServerHttpResponse response, WebSocketHandler webSocketHandler) throws IOException;
|
||||||
|
|
||||||
protected abstract void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
|
protected abstract void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
String sessionId, TransportType transportType, WebSocketHandler webSocketHandler)
|
WebSocketHandler webSocketHandler, String sessionId, String transport)
|
||||||
throws IOException, TransportErrorException;
|
throws IOException, SockJsProcessingException;
|
||||||
|
|
||||||
|
|
||||||
protected boolean validateRequest(String serverId, String sessionId, String transport) {
|
protected boolean validateRequest(String serverId, String sessionId, String transport) {
|
||||||
|
@ -390,7 +408,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isWebSocketEnabled() && transport.equals(TransportType.WEBSOCKET.value())) {
|
if (!isWebSocketEnabled() && transport.equals("websocket")) {
|
||||||
logger.warn("Websocket transport is disabled");
|
logger.warn("Websocket transport is disabled");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
|
@ -14,10 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.support;
|
package org.springframework.web.socket.sockjs.support.frame;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.socket.sockjs.SockJsMessageCodec;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.support;
|
package org.springframework.web.socket.sockjs.support.frame;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.support;
|
package org.springframework.web.socket.sockjs.support.frame;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.support.frame;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.support.frame;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support classes for creating SockJS frames including the encoding and decoding
|
||||||
|
* of SockJS message frames.
|
||||||
|
*/
|
||||||
|
package org.springframework.web.socket.sockjs.support.frame;
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support classes for the SockJS implementation.
|
* Support classes for SockJS including an
|
||||||
|
* {@link org.springframework.web.socket.sockjs.support.AbstractSockJsService}
|
||||||
|
* implementation.
|
||||||
*/
|
*/
|
||||||
package org.springframework.web.socket.sockjs.support;
|
package org.springframework.web.socket.sockjs.support;
|
||||||
|
|
||||||
|
|
|
@ -14,31 +14,25 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.transport;
|
||||||
|
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A contract for SockJS transport implementations. A {@link TransportHandler} is closely
|
* Handles SockJS session URLs.
|
||||||
* related to and often delegates to an {@link AbstractSockJsSession}. In fact most
|
|
||||||
* transports are also implementations of {@link SockJsSessionFactory} with the only exception
|
|
||||||
* to that being HTTP transports that receive messages as they depend on finding an existing
|
|
||||||
* session. See {@link TransportType} for a list of all available transport types.
|
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*
|
|
||||||
* @see SockJsService
|
|
||||||
*/
|
*/
|
||||||
public interface TransportHandler {
|
public interface TransportHandler {
|
||||||
|
|
||||||
TransportType getTransportType();
|
TransportType getTransportType();
|
||||||
|
|
||||||
void setSockJsConfiguration(SockJsConfiguration sockJsConfig);
|
|
||||||
|
|
||||||
void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
WebSocketHandler handler, AbstractSockJsSession session) throws TransportErrorException;
|
WebSocketHandler handler, WebSocketSession session) throws SockJsProcessingException;
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.transport;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -25,7 +25,7 @@ import java.util.Map;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SockJS server transport types.
|
* Defines SockJS transport types.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
@ -24,10 +24,11 @@ import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
|
import org.springframework.web.socket.TextMessage;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator;
|
import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
|
@ -44,22 +45,16 @@ public abstract class AbstractHttpReceivingTransportHandler
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws TransportErrorException {
|
WebSocketHandler webSocketHandler, WebSocketSession webSocketSession) throws SockJsProcessingException {
|
||||||
|
|
||||||
if (session == null) {
|
|
||||||
response.setStatusCode(HttpStatus.NOT_FOUND);
|
|
||||||
logger.warn("Session not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check "Sec-WebSocket-Protocol" header
|
// TODO: check "Sec-WebSocket-Protocol" header
|
||||||
// https://github.com/sockjs/sockjs-client/issues/130
|
// https://github.com/sockjs/sockjs-client/issues/130
|
||||||
|
|
||||||
handleRequestInternal(request, response, session);
|
handleRequestInternal(request, response, webSocketHandler, webSocketSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
protected void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
AbstractSockJsSession session) throws TransportErrorException {
|
WebSocketHandler wsHandler, WebSocketSession wsSession) throws SockJsProcessingException {
|
||||||
|
|
||||||
String[] messages = null;
|
String[] messages = null;
|
||||||
try {
|
try {
|
||||||
|
@ -67,22 +62,22 @@ public abstract class AbstractHttpReceivingTransportHandler
|
||||||
}
|
}
|
||||||
catch (JsonMappingException ex) {
|
catch (JsonMappingException ex) {
|
||||||
logger.error("Failed to read message: " + ex.getMessage());
|
logger.error("Failed to read message: " + ex.getMessage());
|
||||||
sendInternalServerError(response, "Payload expected.", session.getId());
|
sendInternalServerError(response, "Payload expected.", wsSession.getId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
logger.error("Failed to read message: " + ex.getMessage());
|
logger.error("Failed to read message: " + ex.getMessage());
|
||||||
sendInternalServerError(response, "Broken JSON encoding.", session.getId());
|
sendInternalServerError(response, "Broken JSON encoding.", wsSession.getId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
logger.error("Failed to read message: " + t.getMessage());
|
logger.error("Failed to read message: " + t.getMessage());
|
||||||
sendInternalServerError(response, "Failed to process messages", session.getId());
|
sendInternalServerError(response, "Failed to process messages", wsSession.getId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messages == null) {
|
if (messages == null) {
|
||||||
sendInternalServerError(response, "Payload expected.", session.getId());
|
sendInternalServerError(response, "Payload expected.", wsSession.getId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,23 +89,25 @@ public abstract class AbstractHttpReceivingTransportHandler
|
||||||
response.getHeaders().setContentType(new MediaType("text", "plain", Charset.forName("UTF-8")));
|
response.getHeaders().setContentType(new MediaType("text", "plain", Charset.forName("UTF-8")));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
session.delegateMessages(messages);
|
for (String message : messages) {
|
||||||
|
wsHandler.handleMessage(wsSession, new TextMessage(message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
ExceptionWebSocketHandlerDecorator.tryCloseWithError(session, t, logger);
|
ExceptionWebSocketHandlerDecorator.tryCloseWithError(wsSession, t, logger);
|
||||||
throw new TransportErrorException("Unhandled WebSocketHandler error in " + this, t, session.getId());
|
throw new SockJsProcessingException("Unhandled WebSocketHandler error in " + this, t, wsSession.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sendInternalServerError(ServerHttpResponse response, String error,
|
protected void sendInternalServerError(ServerHttpResponse response, String error,
|
||||||
String sessionId) throws TransportErrorException {
|
String sessionId) throws SockJsProcessingException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
|
response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
response.getBody().write(error.getBytes("UTF-8"));
|
response.getBody().write(error.getBytes("UTF-8"));
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
throw new TransportErrorException("Failed to send error message to client", t, sessionId);
|
throw new SockJsProcessingException("Failed to send error message to client", t, sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -22,12 +22,12 @@ import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
import org.springframework.web.socket.sockjs.SockJsSessionFactory;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for HTTP-based transports that send messages over HTTP.
|
* Base class for HTTP-based transports that send messages over HTTP.
|
||||||
|
@ -41,34 +41,34 @@ public abstract class AbstractHttpSendingTransportHandler extends TransportHandl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws TransportErrorException {
|
WebSocketHandler webSocketHandler, WebSocketSession session) throws SockJsProcessingException {
|
||||||
|
|
||||||
// Set content type before writing
|
// Set content type before writing
|
||||||
response.getHeaders().setContentType(getContentType());
|
response.getHeaders().setContentType(getContentType());
|
||||||
|
|
||||||
AbstractHttpSockJsSession httpServerSession = (AbstractHttpSockJsSession) session;
|
AbstractHttpSockJsSession sockJsSession = (AbstractHttpSockJsSession) session;
|
||||||
handleRequestInternal(request, response, httpServerSession);
|
handleRequestInternal(request, response, sockJsSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
protected void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
AbstractHttpSockJsSession httpServerSession) throws TransportErrorException {
|
AbstractHttpSockJsSession sockJsSession) throws SockJsProcessingException {
|
||||||
|
|
||||||
if (httpServerSession.isNew()) {
|
if (sockJsSession.isNew()) {
|
||||||
logger.debug("Opening " + getTransportType() + " connection");
|
logger.debug("Opening " + getTransportType() + " connection");
|
||||||
httpServerSession.setInitialRequest(request, response, getFrameFormat(request));
|
sockJsSession.setInitialRequest(request, response, getFrameFormat(request));
|
||||||
}
|
}
|
||||||
else if (!httpServerSession.isActive()) {
|
else if (!sockJsSession.isActive()) {
|
||||||
logger.debug("starting " + getTransportType() + " async request");
|
logger.debug("starting " + getTransportType() + " async request");
|
||||||
httpServerSession.setLongPollingRequest(request, response, getFrameFormat(request));
|
sockJsSession.setLongPollingRequest(request, response, getFrameFormat(request));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
logger.debug("another " + getTransportType() + " connection still open: " + httpServerSession);
|
logger.debug("another " + getTransportType() + " connection still open: " + sockJsSession);
|
||||||
SockJsFrame closeFrame = SockJsFrame.closeFrameAnotherConnectionOpen();
|
SockJsFrame closeFrame = SockJsFrame.closeFrameAnotherConnectionOpen();
|
||||||
response.getBody().write(getFrameFormat(request).format(closeFrame).getContentBytes());
|
response.getBody().write(getFrameFormat(request).format(closeFrame).getContentBytes());
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new TransportErrorException("Failed to send SockJS close frame", e, httpServerSession.getId());
|
throw new SockJsProcessingException("Failed to send SockJS close frame", e, sockJsSession.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -39,18 +39,19 @@ import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.server.DefaultHandshakeHandler;
|
import org.springframework.web.socket.server.DefaultHandshakeHandler;
|
||||||
import org.springframework.web.socket.server.HandshakeHandler;
|
import org.springframework.web.socket.server.HandshakeHandler;
|
||||||
import org.springframework.web.socket.server.support.ServerWebSocketSessionInitializer;
|
import org.springframework.web.socket.server.support.ServerWebSocketSessionInitializer;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsService;
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
|
||||||
import org.springframework.web.socket.sockjs.SockJsMessageCodec;
|
|
||||||
import org.springframework.web.socket.sockjs.SockJsService;
|
import org.springframework.web.socket.sockjs.SockJsService;
|
||||||
import org.springframework.web.socket.sockjs.SockJsSessionFactory;
|
import org.springframework.web.socket.sockjs.support.AbstractSockJsService;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
import org.springframework.web.socket.sockjs.support.frame.Jackson2SockJsMessageCodec;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsMessageCodec;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.support.Jackson2SockJsMessageCodec;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.SockJsServiceConfig;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -159,12 +160,18 @@ public class DefaultSockJsService extends AbstractSockJsService {
|
||||||
|
|
||||||
protected void addTransportHandlers(Collection<TransportHandler> handlers) {
|
protected void addTransportHandlers(Collection<TransportHandler> handlers) {
|
||||||
for (TransportHandler handler : handlers) {
|
for (TransportHandler handler : handlers) {
|
||||||
handler.setSockJsConfiguration(this);
|
if (handler instanceof TransportHandlerSupport) {
|
||||||
|
((TransportHandlerSupport) handler).setSockJsServiceConfiguration(this.sockJsServiceConfig);
|
||||||
|
}
|
||||||
this.transportHandlers.put(handler.getTransportType(), handler);
|
this.transportHandlers.put(handler.getTransportType(), handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The codec to use for encoding and decoding SockJS messages.
|
||||||
|
* @exception IllegalStateException if no {@link SockJsMessageCodec} is available
|
||||||
|
*/
|
||||||
public void setMessageCodec(SockJsMessageCodec messageCodec) {
|
public void setMessageCodec(SockJsMessageCodec messageCodec) {
|
||||||
this.messageCodec = messageCodec;
|
this.messageCodec = messageCodec;
|
||||||
}
|
}
|
||||||
|
@ -173,13 +180,6 @@ public class DefaultSockJsService extends AbstractSockJsService {
|
||||||
return this.messageCodec;
|
return this.messageCodec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SockJsMessageCodec getMessageCodecRequired() {
|
|
||||||
Assert.state(this.messageCodec != null, "A SockJsMessageCodec is required but not available."
|
|
||||||
+ " Either add Jackson 2 or Jackson 1.x to the classpath, or configure a SockJsMessageCode");
|
|
||||||
return this.messageCodec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<TransportType, TransportHandler> getTransportHandlers() {
|
public Map<TransportType, TransportHandler> getTransportHandlers() {
|
||||||
return Collections.unmodifiableMap(this.transportHandlers);
|
return Collections.unmodifiableMap(this.transportHandlers);
|
||||||
}
|
}
|
||||||
|
@ -203,11 +203,17 @@ public class DefaultSockJsService extends AbstractSockJsService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
|
protected void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
String sessionId, TransportType transportType, WebSocketHandler webSocketHandler)
|
WebSocketHandler wsHandler, String sessionId, String transport)
|
||||||
throws IOException, TransportErrorException {
|
throws IOException, SockJsProcessingException {
|
||||||
|
|
||||||
|
TransportType transportType = TransportType.fromValue(transport);
|
||||||
|
if (transportType == null) {
|
||||||
|
logger.debug("Unknown transport type: " + transportType);
|
||||||
|
response.setStatusCode(HttpStatus.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TransportHandler transportHandler = this.transportHandlers.get(transportType);
|
TransportHandler transportHandler = this.transportHandlers.get(transportType);
|
||||||
|
|
||||||
if (transportHandler == null) {
|
if (transportHandler == null) {
|
||||||
logger.debug("Transport handler not found");
|
logger.debug("Transport handler not found");
|
||||||
response.setStatusCode(HttpStatus.NOT_FOUND);
|
response.setStatusCode(HttpStatus.NOT_FOUND);
|
||||||
|
@ -231,58 +237,60 @@ public class DefaultSockJsService extends AbstractSockJsService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractSockJsSession session = getSockJsSession(sessionId, webSocketHandler,
|
WebSocketSession session = this.sessions.get(sessionId);
|
||||||
transportHandler, request, response);
|
if (session == null) {
|
||||||
|
if (transportHandler instanceof SockJsSessionFactory) {
|
||||||
if (session != null) {
|
SockJsSessionFactory sessionFactory = (SockJsSessionFactory) transportHandler;
|
||||||
if (transportType.sendsNoCacheInstruction()) {
|
session = createSockJsSession(sessionId, sessionFactory, wsHandler, request, response);
|
||||||
addNoCacheHeaders(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transportType.setsJsessionId() && isJsessionIdCookieRequired()) {
|
|
||||||
Cookie cookie = request.getCookies().getCookie("JSESSIONID");
|
|
||||||
String jsid = (cookie != null) ? cookie.getValue() : "dummy";
|
|
||||||
// TODO: bypass use of Cookie object (causes Jetty to set Expires header)
|
|
||||||
response.getHeaders().set("Set-Cookie", "JSESSIONID=" + jsid + ";path=/");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transportType.supportsCors()) {
|
|
||||||
addCorsHeaders(request, response);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (session == null) {
|
||||||
|
response.setStatusCode(HttpStatus.NOT_FOUND);
|
||||||
|
logger.warn("Session not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
transportHandler.handleRequest(request, response, webSocketHandler, session);
|
if (transportType.sendsNoCacheInstruction()) {
|
||||||
|
addNoCacheHeaders(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transportType.setsJsessionId() && isJsessionIdCookieRequired()) {
|
||||||
|
Cookie cookie = request.getCookies().getCookie("JSESSIONID");
|
||||||
|
String jsid = (cookie != null) ? cookie.getValue() : "dummy";
|
||||||
|
// TODO: bypass use of Cookie object (causes Jetty to set Expires header)
|
||||||
|
response.getHeaders().set("Set-Cookie", "JSESSIONID=" + jsid + ";path=/");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transportType.supportsCors()) {
|
||||||
|
addCorsHeaders(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
transportHandler.handleRequest(request, response, wsHandler, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractSockJsSession getSockJsSession(String sessionId, WebSocketHandler handler,
|
private WebSocketSession createSockJsSession(String sessionId, SockJsSessionFactory sessionFactory,
|
||||||
TransportHandler transportHandler, ServerHttpRequest request, ServerHttpResponse response) {
|
WebSocketHandler handler, ServerHttpRequest request, ServerHttpResponse response) {
|
||||||
|
|
||||||
AbstractSockJsSession session = this.sessions.get(sessionId);
|
synchronized (this.sessions) {
|
||||||
if (session != null) {
|
AbstractSockJsSession session = this.sessions.get(sessionId);
|
||||||
return session;
|
if (session != null) {
|
||||||
}
|
|
||||||
|
|
||||||
if (transportHandler instanceof SockJsSessionFactory) {
|
|
||||||
SockJsSessionFactory sessionFactory = (SockJsSessionFactory) transportHandler;
|
|
||||||
|
|
||||||
synchronized (this.sessions) {
|
|
||||||
session = this.sessions.get(sessionId);
|
|
||||||
if (session != null) {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
if (this.sessionCleanupTask == null) {
|
|
||||||
scheduleSessionTask();
|
|
||||||
}
|
|
||||||
logger.debug("Creating new session with session id \"" + sessionId + "\"");
|
|
||||||
session = sessionFactory.createSession(sessionId, handler);
|
|
||||||
String protocol = null; // TODO: https://github.com/sockjs/sockjs-client/issues/130
|
|
||||||
this.sessionInitializer.initialize(request, response, protocol, session);
|
|
||||||
this.sessions.put(sessionId, session);
|
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
if (this.sessionCleanupTask == null) {
|
||||||
|
scheduleSessionTask();
|
||||||
|
}
|
||||||
|
logger.debug("Creating new session with session id \"" + sessionId + "\"");
|
||||||
|
session = sessionFactory.createSession(sessionId, handler);
|
||||||
|
String protocol = null; // TODO: https://github.com/sockjs/sockjs-client/issues/130
|
||||||
|
this.sessionInitializer.initialize(request, response, protocol, session);
|
||||||
|
this.sessions.put(sessionId, session);
|
||||||
|
return session;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
@Override
|
||||||
|
protected boolean isValidTransportType(String lastSegment) {
|
||||||
|
return TransportType.fromValue(lastSegment) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleSessionTask() {
|
private void scheduleSessionTask() {
|
||||||
|
@ -314,4 +322,31 @@ public class DefaultSockJsService extends AbstractSockJsService {
|
||||||
}, getDisconnectDelay());
|
}, getDisconnectDelay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final SockJsServiceConfig sockJsServiceConfig = new SockJsServiceConfig() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStreamBytesLimit() {
|
||||||
|
return DefaultSockJsService.this.getStreamBytesLimit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getHeartbeatTime() {
|
||||||
|
return DefaultSockJsService.this.getHeartbeatTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TaskScheduler getTaskScheduler() {
|
||||||
|
return DefaultSockJsService.this.getTaskScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SockJsMessageCodec getMessageCodec() {
|
||||||
|
Assert.state(DefaultSockJsService.this.getMessageCodec() != null,
|
||||||
|
"A SockJsMessageCodec is required but not available."
|
||||||
|
+ " Either add Jackson 2 or Jackson 1.x to the classpath, or configure a SockJsMessageCode");
|
||||||
|
return DefaultSockJsService.this.getMessageCodec();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
@ -22,10 +22,11 @@ import java.nio.charset.Charset;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.DefaultFrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.DefaultFrameFormat;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.session.SockJsServiceConfig;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.StreamingSockJsSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A TransportHandler for sending messages via Server-Sent events:
|
* A TransportHandler for sending messages via Server-Sent events:
|
||||||
|
@ -49,7 +50,7 @@ public class EventSourceTransportHandler extends AbstractHttpSendingTransportHan
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
public StreamingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
||||||
return new EventSourceStreamingSockJsSession(sessionId, getSockJsConfig(), handler);
|
return new EventSourceStreamingSockJsSession(sessionId, getSockJsServiceConfig(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,7 +61,7 @@ public class EventSourceTransportHandler extends AbstractHttpSendingTransportHan
|
||||||
|
|
||||||
private final class EventSourceStreamingSockJsSession extends StreamingSockJsSession {
|
private final class EventSourceStreamingSockJsSession extends StreamingSockJsSession {
|
||||||
|
|
||||||
private EventSourceStreamingSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler handler) {
|
private EventSourceStreamingSockJsSession(String sessionId, SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super(sessionId, config, handler);
|
super(sessionId, config, handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
@ -25,12 +25,14 @@ import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.DefaultFrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.DefaultFrameFormat;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.session.SockJsServiceConfig;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.StreamingSockJsSession;
|
||||||
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.util.JavaScriptUtils;
|
import org.springframework.web.util.JavaScriptUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,12 +87,12 @@ public class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandle
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
public StreamingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
||||||
return new HtmlFileStreamingSockJsSession(sessionId, getSockJsConfig(), handler);
|
return new HtmlFileStreamingSockJsSession(sessionId, getSockJsServiceConfig(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
AbstractHttpSockJsSession session) throws TransportErrorException {
|
AbstractHttpSockJsSession session) throws SockJsProcessingException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String callback = request.getQueryParams().getFirst("c");
|
String callback = request.getQueryParams().getFirst("c");
|
||||||
|
@ -101,7 +103,7 @@ public class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
throw new TransportErrorException("Failed to send error to client", t, session.getId());
|
throw new SockJsProcessingException("Failed to send error to client", t, session.getId());
|
||||||
}
|
}
|
||||||
super.handleRequestInternal(request, response, session);
|
super.handleRequestInternal(request, response, session);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +121,7 @@ public class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandle
|
||||||
|
|
||||||
private final class HtmlFileStreamingSockJsSession extends StreamingSockJsSession {
|
private final class HtmlFileStreamingSockJsSession extends StreamingSockJsSession {
|
||||||
|
|
||||||
private HtmlFileStreamingSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler handler) {
|
private HtmlFileStreamingSockJsSession(String sessionId, SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super(sessionId, config, handler);
|
super(sessionId, config, handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
@ -24,10 +24,12 @@ import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.PollingSockJsSession;
|
||||||
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.util.JavaScriptUtils;
|
import org.springframework.web.util.JavaScriptUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,12 +52,12 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PollingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
public PollingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
||||||
return new PollingSockJsSession(sessionId, getSockJsConfig(), handler);
|
return new PollingSockJsSession(sessionId, getSockJsServiceConfig(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
AbstractHttpSockJsSession session) throws TransportErrorException {
|
AbstractHttpSockJsSession session) throws SockJsProcessingException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String callback = request.getQueryParams().getFirst("c");
|
String callback = request.getQueryParams().getFirst("c");
|
||||||
|
@ -66,7 +68,7 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
throw new TransportErrorException("Failed to send error to client", t, session.getId());
|
throw new SockJsProcessingException("Failed to send error to client", t, session.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
super.handleRequestInternal(request, response, session);
|
super.handleRequestInternal(request, response, session);
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -25,11 +25,12 @@ import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsMessageCodec;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsMessageCodec;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link TransportHandler} that receives messages over HTTP.
|
* A {@link TransportHandler} that receives messages over HTTP.
|
||||||
|
@ -48,22 +49,22 @@ public class JsonpTransportHandler extends AbstractHttpReceivingTransportHandler
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
AbstractSockJsSession sockJsSession) throws TransportErrorException {
|
WebSocketHandler webSocketHandler, WebSocketSession webSocketSession) throws SockJsProcessingException {
|
||||||
|
|
||||||
super.handleRequestInternal(request, response, sockJsSession);
|
super.handleRequestInternal(request, response, webSocketHandler, webSocketSession);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response.getBody().write("ok".getBytes("UTF-8"));
|
response.getBody().write("ok".getBytes("UTF-8"));
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
throw new TransportErrorException("Failed to write response body", t, sockJsSession.getId());
|
throw new SockJsProcessingException("Failed to write response body", t, webSocketSession.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String[] readMessages(ServerHttpRequest request) throws IOException {
|
protected String[] readMessages(ServerHttpRequest request) throws IOException {
|
||||||
|
|
||||||
SockJsMessageCodec messageCodec = getSockJsConfig().getMessageCodecRequired();
|
SockJsMessageCodec messageCodec = getSockJsServiceConfig().getMessageCodec();
|
||||||
|
|
||||||
MediaType contentType = request.getHeaders().getContentType();
|
MediaType contentType = request.getHeaders().getContentType();
|
||||||
if ((contentType != null) && MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) {
|
if ((contentType != null) && MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) {
|
|
@ -14,9 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory for creating a SockJS session. {@link TransportHandler}s typically also serve
|
* A factory for creating a SockJS session. {@link TransportHandler}s typically also serve
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ import org.springframework.web.socket.TextMessage;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.WebSocketSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.adapter.TextWebSocketHandlerAdapter;
|
import org.springframework.web.socket.adapter.TextWebSocketHandlerAdapter;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.transport.session.SockJsServiceConfig;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of {@link WebSocketHandler} that adds SockJS messages frames, sends
|
* An implementation of {@link WebSocketHandler} that adds SockJS messages frames, sends
|
||||||
|
@ -43,26 +44,26 @@ import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
||||||
*/
|
*/
|
||||||
public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
|
public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
|
||||||
|
|
||||||
private final SockJsConfiguration sockJsConfig;
|
private final SockJsServiceConfig sockJsServiceConfig;
|
||||||
|
|
||||||
private final WebSocketServerSockJsSession session;
|
private final WebSocketServerSockJsSession session;
|
||||||
|
|
||||||
private final AtomicInteger sessionCount = new AtomicInteger(0);
|
private final AtomicInteger sessionCount = new AtomicInteger(0);
|
||||||
|
|
||||||
|
|
||||||
public SockJsWebSocketHandler(SockJsConfiguration config,
|
public SockJsWebSocketHandler(SockJsServiceConfig sockJsServiceConfig,
|
||||||
WebSocketHandler webSocketHandler, WebSocketServerSockJsSession session) {
|
WebSocketHandler webSocketHandler, WebSocketServerSockJsSession session) {
|
||||||
|
|
||||||
Assert.notNull(config, "config must not be null");
|
Assert.notNull(sockJsServiceConfig, "sockJsServiceConfig must not be null");
|
||||||
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
|
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
|
||||||
Assert.notNull(session, "session must not be null");
|
Assert.notNull(session, "session must not be null");
|
||||||
|
|
||||||
this.sockJsConfig = config;
|
this.sockJsServiceConfig = sockJsServiceConfig;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SockJsConfiguration getSockJsConfig() {
|
protected SockJsServiceConfig getSockJsConfig() {
|
||||||
return this.sockJsConfig;
|
return this.sockJsServiceConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -14,11 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.transport.session.SockJsServiceConfig;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,16 +29,15 @@ public abstract class TransportHandlerSupport {
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||||
|
|
||||||
private SockJsConfiguration sockJsConfig;
|
private SockJsServiceConfig sockJsServiceConfig;
|
||||||
|
|
||||||
|
|
||||||
public void setSockJsConfiguration(SockJsConfiguration sockJsConfig) {
|
public void setSockJsServiceConfiguration(SockJsServiceConfig sockJsConfig) {
|
||||||
this.sockJsConfig = sockJsConfig;
|
this.sockJsServiceConfig = sockJsConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SockJsConfiguration getSockJsConfig() {
|
public SockJsServiceConfig getSockJsServiceConfig() {
|
||||||
return this.sockJsConfig;
|
return this.sockJsServiceConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -22,12 +22,13 @@ import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.server.HandshakeHandler;
|
import org.springframework.web.socket.server.HandshakeHandler;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.socket.sockjs.SockJsSessionFactory;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A WebSocket {@link TransportHandler}. Uses {@link SockJsWebSocketHandler} and
|
* A WebSocket {@link TransportHandler}. Uses {@link SockJsWebSocketHandler} and
|
||||||
|
@ -58,20 +59,20 @@ public class WebSocketTransportHandler extends TransportHandlerSupport
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
|
public AbstractSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
|
||||||
return new WebSocketServerSockJsSession(sessionId, getSockJsConfig(), webSocketHandler);
|
return new WebSocketServerSockJsSession(sessionId, getSockJsServiceConfig(), webSocketHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws TransportErrorException {
|
WebSocketHandler wsHandler, WebSocketSession wsSession) throws SockJsProcessingException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
WebSocketServerSockJsSession wsSession = (WebSocketServerSockJsSession) session;
|
WebSocketServerSockJsSession sockJsSession = (WebSocketServerSockJsSession) wsSession;
|
||||||
WebSocketHandler sockJsWrapper = new SockJsWebSocketHandler(getSockJsConfig(), webSocketHandler, wsSession);
|
WebSocketHandler sockJsHandler = new SockJsWebSocketHandler(getSockJsServiceConfig(), wsHandler, sockJsSession);
|
||||||
this.handshakeHandler.doHandshake(request, response, sockJsWrapper);
|
this.handshakeHandler.doHandshake(request, response, sockJsHandler);
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
throw new TransportErrorException("Failed to start handshake request", t, session.getId());
|
throw new SockJsProcessingException("Failed to start handshake request", t, wsSession.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,18 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.DefaultFrameFormat;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.DefaultFrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.PollingSockJsSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link TransportHandler} based on XHR (long) polling.
|
* A {@link TransportHandler} based on XHR (long) polling.
|
||||||
|
@ -51,7 +52,7 @@ public class XhrPollingTransportHandler extends AbstractHttpSendingTransportHand
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PollingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
public PollingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
||||||
return new PollingSockJsSession(sessionId, getSockJsConfig(), handler);
|
return new PollingSockJsSession(sessionId, getSockJsServiceConfig(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
@ -22,11 +22,12 @@ import java.nio.charset.Charset;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.DefaultFrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.DefaultFrameFormat;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.session.SockJsServiceConfig;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.StreamingSockJsSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link TransportHandler} that sends messages over an HTTP streaming request.
|
* A {@link TransportHandler} that sends messages over an HTTP streaming request.
|
||||||
|
@ -49,7 +50,7 @@ public class XhrStreamingTransportHandler extends AbstractHttpSendingTransportHa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
public StreamingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
|
||||||
return new XhrStreamingSockJsSession(sessionId, getSockJsConfig(), handler);
|
return new XhrStreamingSockJsSession(sessionId, getSockJsServiceConfig(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,7 +61,7 @@ public class XhrStreamingTransportHandler extends AbstractHttpSendingTransportHa
|
||||||
|
|
||||||
private final class XhrStreamingSockJsSession extends StreamingSockJsSession {
|
private final class XhrStreamingSockJsSession extends StreamingSockJsSession {
|
||||||
|
|
||||||
private XhrStreamingSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler handler) {
|
private XhrStreamingSockJsSession(String sessionId, SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super(sessionId, config, handler);
|
super(sessionId, config, handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link TransportHandler} that receives messages over HTTP.
|
* A {@link TransportHandler} that receives messages over HTTP.
|
||||||
|
@ -38,7 +38,7 @@ public class XhrTransportHandler extends AbstractHttpReceivingTransportHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String[] readMessages(ServerHttpRequest request) throws IOException {
|
protected String[] readMessages(ServerHttpRequest request) throws IOException {
|
||||||
return getSockJsConfig().getMessageCodecRequired().decodeInputStream(request.getBody());
|
return getSockJsServiceConfig().getMessageCodec().decodeInputStream(request.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link org.springframework.web.socket.sockjs.transport.TransportHandler}
|
||||||
|
* implementation classes as well as a concrete
|
||||||
|
* {@link org.springframework.web.socket.sockjs.SockJsService}.
|
||||||
|
*/
|
||||||
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server-side support for SockJS transports including
|
* Server-side support for SockJS transports including
|
||||||
* {@link org.springframework.web.socket.sockjs.TransportHandler} implementations
|
* {@link org.springframework.web.socket.sockjs.transport.TransportHandler} implementations
|
||||||
* for processing incoming requests, their
|
* for processing incoming requests, their
|
||||||
* {@link org.springframework.web.socket.sockjs.AbstractSockJsSession session} counterparts for
|
* {@link org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession session} counterparts for
|
||||||
* sending messages over the various transports, and
|
* sending messages over the various transports, and
|
||||||
* {@link org.springframework.web.socket.sockjs.transport.DefaultSockJsService}.
|
* {@link org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService}.
|
||||||
*/
|
*/
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
@ -26,11 +26,9 @@ import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame;
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
|
||||||
import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator;
|
import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,7 +50,7 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||||
private String protocol;
|
private String protocol;
|
||||||
|
|
||||||
|
|
||||||
public AbstractHttpSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler handler) {
|
public AbstractHttpSockJsSession(String sessionId, SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super(sessionId, config, handler);
|
super(sessionId, config, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +74,7 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setInitialRequest(ServerHttpRequest request, ServerHttpResponse response,
|
public synchronized void setInitialRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
FrameFormat frameFormat) throws TransportErrorException {
|
FrameFormat frameFormat) throws SockJsProcessingException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
udpateRequest(request, response, frameFormat);
|
udpateRequest(request, response, frameFormat);
|
||||||
|
@ -85,7 +83,7 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
tryCloseWithSockJsTransportError(t, null);
|
tryCloseWithSockJsTransportError(t, null);
|
||||||
throw new TransportErrorException("Failed open SockJS session", t, getId());
|
throw new SockJsProcessingException("Failed open SockJS session", t, getId());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
delegateConnectionEstablished();
|
delegateConnectionEstablished();
|
||||||
|
@ -99,7 +97,7 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setLongPollingRequest(ServerHttpRequest request, ServerHttpResponse response,
|
public synchronized void setLongPollingRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
FrameFormat frameFormat) throws TransportErrorException {
|
FrameFormat frameFormat) throws SockJsProcessingException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
udpateRequest(request, response, frameFormat);
|
udpateRequest(request, response, frameFormat);
|
||||||
|
@ -110,7 +108,7 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||||
writeFrame(SockJsFrame.closeFrameGoAway());
|
writeFrame(SockJsFrame.closeFrameGoAway());
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
throw new TransportErrorException("Failed to send SockJS close frame", ex, getId());
|
throw new SockJsProcessingException("Failed to send SockJS close frame", ex, getId());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +121,7 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
tryCloseWithSockJsTransportError(t, null);
|
tryCloseWithSockJsTransportError(t, null);
|
||||||
throw new TransportErrorException("Failed to start long running request and flush messages", t, getId());
|
throw new SockJsProcessingException("Failed to start long running request and flush messages", t, getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -33,6 +33,8 @@ import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.WebSocketMessage;
|
import org.springframework.web.socket.WebSocketMessage;
|
||||||
import org.springframework.web.socket.WebSocketSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.adapter.ConfigurableWebSocketSession;
|
import org.springframework.web.socket.adapter.ConfigurableWebSocketSession;
|
||||||
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract base class SockJS sessions implementing {@link WebSocketSession}.
|
* An abstract base class SockJS sessions implementing {@link WebSocketSession}.
|
||||||
|
@ -55,7 +57,7 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
|
||||||
|
|
||||||
private Principal principal;
|
private Principal principal;
|
||||||
|
|
||||||
private final SockJsConfiguration sockJsConfig;
|
private final SockJsServiceConfig sockJsServiceConfig;
|
||||||
|
|
||||||
private final WebSocketHandler handler;
|
private final WebSocketHandler handler;
|
||||||
|
|
||||||
|
@ -70,16 +72,16 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param sessionId the session ID
|
* @param sessionId the session ID
|
||||||
* @param config the sockJS configuration
|
* @param config SockJS service configuration options
|
||||||
* @param webSocketHandler the recipient of SockJS messages
|
* @param wsHandler the recipient of SockJS messages
|
||||||
*/
|
*/
|
||||||
public AbstractSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler webSocketHandler) {
|
public AbstractSockJsSession(String sessionId, SockJsServiceConfig config, WebSocketHandler wsHandler) {
|
||||||
Assert.notNull(sessionId, "sessionId is required");
|
Assert.notNull(sessionId, "sessionId is required");
|
||||||
Assert.notNull(config, "sockJsConfig is required");
|
Assert.notNull(config, "sockJsConfig is required");
|
||||||
Assert.notNull(webSocketHandler, "webSocketHandler is required");
|
Assert.notNull(wsHandler, "webSocketHandler is required");
|
||||||
this.id = sessionId;
|
this.id = sessionId;
|
||||||
this.sockJsConfig = config;
|
this.sockJsServiceConfig = config;
|
||||||
this.handler = webSocketHandler;
|
this.handler = wsHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -132,8 +134,8 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SockJsConfiguration getSockJsConfig() {
|
public SockJsServiceConfig getSockJsServiceConfig() {
|
||||||
return this.sockJsConfig;
|
return this.sockJsServiceConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNew() {
|
public boolean isNew() {
|
||||||
|
@ -318,7 +320,7 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
|
||||||
logger.warn("Terminating connection due to failure to send message: " + ex.getMessage());
|
logger.warn("Terminating connection due to failure to send message: " + ex.getMessage());
|
||||||
disconnect(CloseStatus.SERVER_ERROR);
|
disconnect(CloseStatus.SERVER_ERROR);
|
||||||
close(CloseStatus.SERVER_ERROR);
|
close(CloseStatus.SERVER_ERROR);
|
||||||
throw new TransportErrorException("Failed to write " + frame, ex, this.getId());
|
throw new SockJsProcessingException("Failed to write " + frame, ex, this.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,13 +334,13 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void scheduleHeartbeat() {
|
protected void scheduleHeartbeat() {
|
||||||
Assert.state(this.sockJsConfig.getTaskScheduler() != null, "heartbeatScheduler not configured");
|
Assert.state(this.sockJsServiceConfig.getTaskScheduler() != null, "heartbeatScheduler not configured");
|
||||||
cancelHeartbeat();
|
cancelHeartbeat();
|
||||||
if (!isActive()) {
|
if (!isActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Date time = new Date(System.currentTimeMillis() + this.sockJsConfig.getHeartbeatTime());
|
Date time = new Date(System.currentTimeMillis() + this.sockJsServiceConfig.getHeartbeatTime());
|
||||||
this.heartbeatTask = this.sockJsConfig.getTaskScheduler().schedule(new Runnable() {
|
this.heartbeatTask = this.sockJsServiceConfig.getTaskScheduler().schedule(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
sendHeartbeat();
|
sendHeartbeat();
|
||||||
|
@ -349,7 +351,7 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
|
||||||
}
|
}
|
||||||
}, time);
|
}, time);
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Scheduled heartbeat after " + this.sockJsConfig.getHeartbeatTime()/1000 + " seconds");
|
logger.trace("Scheduled heartbeat after " + this.sockJsServiceConfig.getHeartbeatTime()/1000 + " seconds");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,13 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsMessageCodec;
|
||||||
import org.springframework.web.socket.sockjs.SockJsMessageCodec;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SockJS session for use with polling HTTP transports.
|
* A SockJS session for use with polling HTTP transports.
|
||||||
|
@ -30,7 +29,7 @@ import org.springframework.web.socket.sockjs.SockJsMessageCodec;
|
||||||
*/
|
*/
|
||||||
public class PollingSockJsSession extends AbstractHttpSockJsSession {
|
public class PollingSockJsSession extends AbstractHttpSockJsSession {
|
||||||
|
|
||||||
public PollingSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler handler) {
|
public PollingSockJsSession(String sessionId, SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super(sessionId, config, handler);
|
super(sessionId, config, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ public class PollingSockJsSession extends AbstractHttpSockJsSession {
|
||||||
String[] messages = getMessageCache().toArray(new String[getMessageCache().size()]);
|
String[] messages = getMessageCache().toArray(new String[getMessageCache().size()]);
|
||||||
getMessageCache().clear();
|
getMessageCache().clear();
|
||||||
|
|
||||||
SockJsMessageCodec messageCodec = getSockJsConfig().getMessageCodecRequired();
|
SockJsMessageCodec messageCodec = getSockJsServiceConfig().getMessageCodec();
|
||||||
SockJsFrame frame = SockJsFrame.messageFrame(messageCodec, messages);
|
SockJsFrame frame = SockJsFrame.messageFrame(messageCodec, messages);
|
||||||
writeFrame(frame);
|
writeFrame(frame);
|
||||||
}
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
|
import org.springframework.web.socket.sockjs.SockJsService;
|
||||||
|
import org.springframework.web.socket.sockjs.support.frame.SockJsMessageCodec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides transport handling code with access to the {@link SockJsService} configuration
|
||||||
|
* options they need to have access to. Mainly for internal use.
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public interface SockJsServiceConfig {
|
||||||
|
|
||||||
|
int getStreamBytesLimit();
|
||||||
|
|
||||||
|
long getHeartbeatTime();
|
||||||
|
|
||||||
|
TaskScheduler getTaskScheduler();
|
||||||
|
|
||||||
|
SockJsMessageCodec getMessageCodec();
|
||||||
|
|
||||||
|
}
|
|
@ -14,18 +14,17 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsMessageCodec;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsMessageCodec;
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SockJS session for use with streaming HTTP transports.
|
* A SockJS session for use with streaming HTTP transports.
|
||||||
|
@ -37,14 +36,14 @@ public class StreamingSockJsSession extends AbstractHttpSockJsSession {
|
||||||
private int byteCount;
|
private int byteCount;
|
||||||
|
|
||||||
|
|
||||||
public StreamingSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler handler) {
|
public StreamingSockJsSession(String sessionId, SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super(sessionId, config, handler);
|
super(sessionId, config, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setInitialRequest(ServerHttpRequest request, ServerHttpResponse response,
|
public synchronized void setInitialRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
FrameFormat frameFormat) throws TransportErrorException {
|
FrameFormat frameFormat) throws SockJsProcessingException {
|
||||||
|
|
||||||
super.setInitialRequest(request, response, frameFormat);
|
super.setInitialRequest(request, response, frameFormat);
|
||||||
|
|
||||||
|
@ -61,7 +60,7 @@ public class StreamingSockJsSession extends AbstractHttpSockJsSession {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
String message = getMessageCache().poll();
|
String message = getMessageCache().poll();
|
||||||
SockJsMessageCodec messageCodec = getSockJsConfig().getMessageCodecRequired();
|
SockJsMessageCodec messageCodec = getSockJsServiceConfig().getMessageCodec();
|
||||||
SockJsFrame frame = SockJsFrame.messageFrame(messageCodec, message);
|
SockJsFrame frame = SockJsFrame.messageFrame(messageCodec, message);
|
||||||
writeFrame(frame);
|
writeFrame(frame);
|
||||||
|
|
||||||
|
@ -70,7 +69,7 @@ public class StreamingSockJsSession extends AbstractHttpSockJsSession {
|
||||||
logger.trace(this.byteCount + " bytes written so far, "
|
logger.trace(this.byteCount + " bytes written so far, "
|
||||||
+ getMessageCache().size() + " more messages not flushed");
|
+ getMessageCache().size() + " more messages not flushed");
|
||||||
}
|
}
|
||||||
if (this.byteCount >= getSockJsConfig().getStreamBytesLimit()) {
|
if (this.byteCount >= getSockJsServiceConfig().getStreamBytesLimit()) {
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Streamed bytes limit reached. Recycling current request");
|
logger.trace("Streamed bytes limit reached. Recycling current request");
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -23,10 +23,8 @@ import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.TextMessage;
|
import org.springframework.web.socket.TextMessage;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.WebSocketSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsMessageCodec;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame;
|
|
||||||
import org.springframework.web.socket.sockjs.SockJsMessageCodec;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SockJS session for use with the WebSocket transport.
|
* A SockJS session for use with the WebSocket transport.
|
||||||
|
@ -39,7 +37,7 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession {
|
||||||
private WebSocketSession webSocketSession;
|
private WebSocketSession webSocketSession;
|
||||||
|
|
||||||
|
|
||||||
public WebSocketServerSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler handler) {
|
public WebSocketServerSockJsSession(String sessionId, SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super(sessionId, config, handler);
|
super(sessionId, config, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +83,7 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession {
|
||||||
}
|
}
|
||||||
String[] messages;
|
String[] messages;
|
||||||
try {
|
try {
|
||||||
messages = getSockJsConfig().getMessageCodecRequired().decode(payload);
|
messages = getSockJsServiceConfig().getMessageCodec().decode(payload);
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
logger.error("Broken data received. Terminating WebSocket connection abruptly", ex);
|
logger.error("Broken data received. Terminating WebSocket connection abruptly", ex);
|
||||||
|
@ -98,7 +96,7 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession {
|
||||||
@Override
|
@Override
|
||||||
public void sendMessageInternal(String message) throws IOException {
|
public void sendMessageInternal(String message) throws IOException {
|
||||||
cancelHeartbeat();
|
cancelHeartbeat();
|
||||||
SockJsMessageCodec messageCodec = getSockJsConfig().getMessageCodecRequired();
|
SockJsMessageCodec messageCodec = getSockJsServiceConfig().getMessageCodec();
|
||||||
SockJsFrame frame = SockJsFrame.messageFrame(messageCodec, message);
|
SockJsFrame frame = SockJsFrame.messageFrame(messageCodec, message);
|
||||||
writeFrame(frame);
|
writeFrame(frame);
|
||||||
scheduleHeartbeat();
|
scheduleHeartbeat();
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SockJS specific implementations of
|
||||||
|
* {@link org.springframework.web.socket.WebSocketSession}.
|
||||||
|
*/
|
||||||
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.support;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ import org.springframework.scheduling.TaskScheduler;
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||||
import org.springframework.web.socket.AbstractHttpRequestTests;
|
import org.springframework.web.socket.AbstractHttpRequestTests;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -77,7 +79,7 @@ public class AbstractSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
handleRequest("GET", "/a/server/session/xhr", HttpStatus.OK);
|
handleRequest("GET", "/a/server/session/xhr", HttpStatus.OK);
|
||||||
|
|
||||||
assertEquals("session", this.service.sessionId);
|
assertEquals("session", this.service.sessionId);
|
||||||
assertEquals(TransportType.XHR, this.service.transportType);
|
assertEquals(TransportType.XHR.value(), this.service.transport);
|
||||||
assertSame(this.handler, this.service.handler);
|
assertSame(this.handler, this.service.handler);
|
||||||
|
|
||||||
this.service.setValidSockJsPrefixes("/b");
|
this.service.setValidSockJsPrefixes("/b");
|
||||||
|
@ -96,7 +98,7 @@ public class AbstractSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
handleRequest("GET", "/a/server/session/xhr", HttpStatus.OK);
|
handleRequest("GET", "/a/server/session/xhr", HttpStatus.OK);
|
||||||
|
|
||||||
assertEquals("session", this.service.sessionId);
|
assertEquals("session", this.service.sessionId);
|
||||||
assertEquals(TransportType.XHR, this.service.transportType);
|
assertEquals(TransportType.XHR.value(), this.service.transport);
|
||||||
assertSame(this.handler, this.service.handler);
|
assertSame(this.handler, this.service.handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +109,7 @@ public class AbstractSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
handleRequest("GET", "/a/server/session/xhr", HttpStatus.OK);
|
handleRequest("GET", "/a/server/session/xhr", HttpStatus.OK);
|
||||||
|
|
||||||
assertEquals("session", this.service.sessionId);
|
assertEquals("session", this.service.sessionId);
|
||||||
assertEquals(TransportType.XHR, this.service.transportType);
|
assertEquals(TransportType.XHR.value(), this.service.transport);
|
||||||
assertSame(this.handler, this.service.handler);
|
assertSame(this.handler, this.service.handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +218,7 @@ public class AbstractSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
|
|
||||||
private String sessionId;
|
private String sessionId;
|
||||||
|
|
||||||
private TransportType transportType;
|
private String transport;
|
||||||
|
|
||||||
private WebSocketHandler handler;
|
private WebSocketHandler handler;
|
||||||
|
|
||||||
|
@ -224,11 +226,6 @@ public class AbstractSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
super(scheduler);
|
super(scheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SockJsMessageCodec getMessageCodecRequired() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleRawWebSocketRequest(ServerHttpRequest request,
|
protected void handleRawWebSocketRequest(ServerHttpRequest request,
|
||||||
ServerHttpResponse response, WebSocketHandler handler) throws IOException {
|
ServerHttpResponse response, WebSocketHandler handler) throws IOException {
|
||||||
|
@ -237,15 +234,19 @@ public class AbstractSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleTransportRequest(ServerHttpRequest request,
|
protected void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
ServerHttpResponse response, String sessionId,
|
WebSocketHandler handler, String sessionId, String transport)
|
||||||
TransportType transportType, WebSocketHandler handler)
|
throws IOException, SockJsProcessingException {
|
||||||
throws IOException, TransportErrorException {
|
|
||||||
|
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.transportType = transportType;
|
this.transport = transport;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isValidTransportType(String transportType) {
|
||||||
|
return TransportType.fromValue(transportType) != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,9 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.transport;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -29,14 +29,15 @@ import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.scheduling.TaskScheduler;
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
import org.springframework.web.socket.AbstractHttpRequestTests;
|
import org.springframework.web.socket.AbstractHttpRequestTests;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.socket.sockjs.SockJsSessionFactory;
|
import org.springframework.web.socket.sockjs.transport.TransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.StubSockJsConfig;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
import org.springframework.web.socket.sockjs.TestSockJsSession;
|
import org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
import org.springframework.web.socket.sockjs.transport.handler.SockJsSessionFactory;
|
||||||
import org.springframework.web.socket.sockjs.TransportHandler;
|
import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession;
|
||||||
import org.springframework.web.socket.sockjs.TransportType;
|
import org.springframework.web.socket.sockjs.transport.session.StubSockJsServiceConfig;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.TestSockJsSession;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Matchers.*;
|
import static org.mockito.Matchers.*;
|
||||||
|
@ -83,7 +84,7 @@ public class DefaultSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
WebSocketHandler webSocketHandler = mock(WebSocketHandler.class);
|
WebSocketHandler webSocketHandler = mock(WebSocketHandler.class);
|
||||||
|
|
||||||
DefaultSockJsService service = new DefaultSockJsService(taskScheduler, transportHandlers);
|
DefaultSockJsService service = new DefaultSockJsService(taskScheduler, transportHandlers);
|
||||||
service.handleTransportRequest(this.request, this.response, "123", TransportType.XHR, webSocketHandler);
|
service.handleTransportRequest(this.request, this.response, webSocketHandler, "123", TransportType.XHR.value());
|
||||||
|
|
||||||
assertEquals(200, this.servletResponse.getStatus());
|
assertEquals(200, this.servletResponse.getStatus());
|
||||||
assertNotNull(xhrHandler.session);
|
assertNotNull(xhrHandler.session);
|
||||||
|
@ -107,7 +108,7 @@ public class DefaultSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
Set<TransportHandler> transportHandlers = Collections.<TransportHandler>singleton(xhrHandler);
|
Set<TransportHandler> transportHandlers = Collections.<TransportHandler>singleton(xhrHandler);
|
||||||
|
|
||||||
DefaultSockJsService service = new DefaultSockJsService(taskScheduler, transportHandlers);
|
DefaultSockJsService service = new DefaultSockJsService(taskScheduler, transportHandlers);
|
||||||
service.handleTransportRequest(this.request, this.response, "123", TransportType.XHR, null);
|
service.handleTransportRequest(this.request, this.response, null, "123", TransportType.XHR.value());
|
||||||
|
|
||||||
assertEquals(204, this.servletResponse.getStatus());
|
assertEquals(204, this.servletResponse.getStatus());
|
||||||
assertEquals("*", this.response.getHeaders().getFirst("Access-Control-Allow-Origin"));
|
assertEquals("*", this.response.getHeaders().getFirst("Access-Control-Allow-Origin"));
|
||||||
|
@ -122,7 +123,7 @@ public class DefaultSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
|
|
||||||
Set<TransportHandler> transportHandlers = new HashSet<>();
|
Set<TransportHandler> transportHandlers = new HashSet<>();
|
||||||
DefaultSockJsService service = new DefaultSockJsService(mock(TaskScheduler.class), transportHandlers);
|
DefaultSockJsService service = new DefaultSockJsService(mock(TaskScheduler.class), transportHandlers);
|
||||||
service.handleTransportRequest(this.request, this.response, "123", TransportType.XHR, null);
|
service.handleTransportRequest(this.request, this.response, null, "123", TransportType.XHR.value());
|
||||||
|
|
||||||
assertEquals(404, this.servletResponse.getStatus());
|
assertEquals(404, this.servletResponse.getStatus());
|
||||||
}
|
}
|
||||||
|
@ -135,20 +136,20 @@ public class DefaultSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
Set<TransportHandler> transportHandlers = new HashSet<>();
|
Set<TransportHandler> transportHandlers = new HashSet<>();
|
||||||
transportHandlers.add(new StubXhrTransportHandler());
|
transportHandlers.add(new StubXhrTransportHandler());
|
||||||
transportHandlers.add(new StubXhrSendTransportHandler());
|
transportHandlers.add(new StubXhrSendTransportHandler());
|
||||||
WebSocketHandler webSocketHandler = mock(WebSocketHandler.class);
|
WebSocketHandler wsHandler = mock(WebSocketHandler.class);
|
||||||
DefaultSockJsService service = new DefaultSockJsService(mock(TaskScheduler.class), transportHandlers);
|
DefaultSockJsService service = new DefaultSockJsService(mock(TaskScheduler.class), transportHandlers);
|
||||||
|
|
||||||
service.handleTransportRequest(this.request, this.response, "123", TransportType.XHR_SEND, webSocketHandler);
|
service.handleTransportRequest(this.request, this.response, wsHandler, "123", TransportType.XHR_SEND.value());
|
||||||
|
|
||||||
assertEquals(404, this.servletResponse.getStatus()); // dropped (no session)
|
assertEquals(404, this.servletResponse.getStatus()); // dropped (no session)
|
||||||
|
|
||||||
resetResponse();
|
resetResponse();
|
||||||
service.handleTransportRequest(this.request, this.response, "123", TransportType.XHR, webSocketHandler);
|
service.handleTransportRequest(this.request, this.response, wsHandler, "123", TransportType.XHR.value());
|
||||||
|
|
||||||
assertEquals(200, this.servletResponse.getStatus());
|
assertEquals(200, this.servletResponse.getStatus());
|
||||||
|
|
||||||
resetResponse();
|
resetResponse();
|
||||||
service.handleTransportRequest(this.request, this.response, "123", TransportType.XHR_SEND, webSocketHandler);
|
service.handleTransportRequest(this.request, this.response, wsHandler, "123", TransportType.XHR_SEND.value());
|
||||||
|
|
||||||
assertEquals(200, this.servletResponse.getStatus());
|
assertEquals(200, this.servletResponse.getStatus());
|
||||||
}
|
}
|
||||||
|
@ -158,20 +159,16 @@ public class DefaultSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
|
|
||||||
WebSocketHandler webSocketHandler;
|
WebSocketHandler webSocketHandler;
|
||||||
|
|
||||||
AbstractSockJsSession session;
|
WebSocketSession session;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TransportType getTransportType() {
|
public TransportType getTransportType() {
|
||||||
return TransportType.XHR;
|
return TransportType.XHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSockJsConfiguration(SockJsConfiguration sockJsConfig) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
WebSocketHandler handler, AbstractSockJsSession session) throws TransportErrorException {
|
WebSocketHandler handler, WebSocketSession session) throws SockJsProcessingException {
|
||||||
|
|
||||||
this.webSocketHandler = handler;
|
this.webSocketHandler = handler;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
@ -179,7 +176,7 @@ public class DefaultSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
|
public AbstractSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
|
||||||
return new TestSockJsSession(sessionId, new StubSockJsConfig(), webSocketHandler);
|
return new TestSockJsSession(sessionId, new StubSockJsServiceConfig(), webSocketHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -191,13 +188,9 @@ public class DefaultSockJsServiceTests extends AbstractHttpRequestTests {
|
||||||
return TransportType.XHR_SEND;
|
return TransportType.XHR_SEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSockJsConfiguration(SockJsConfiguration sockJsConfig) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
WebSocketHandler handler, AbstractSockJsSession session) throws TransportErrorException {
|
WebSocketHandler handler, WebSocketSession session) throws SockJsProcessingException {
|
||||||
|
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
response.setStatusCode(HttpStatus.NOT_FOUND);
|
response.setStatusCode(HttpStatus.NOT_FOUND);
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -23,10 +23,13 @@ import org.springframework.web.socket.AbstractHttpRequestTests;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.TextMessage;
|
import org.springframework.web.socket.TextMessage;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
import org.springframework.web.socket.sockjs.StubSockJsConfig;
|
import org.springframework.web.socket.sockjs.transport.handler.AbstractHttpReceivingTransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.TestSockJsSession;
|
import org.springframework.web.socket.sockjs.transport.handler.JsonpTransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.TransportErrorException;
|
import org.springframework.web.socket.sockjs.transport.handler.XhrTransportHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.StubSockJsServiceConfig;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.TestSockJsSession;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
@ -105,7 +108,7 @@ public class HttpReceivingTransportHandlerTests extends AbstractHttpRequestTest
|
||||||
@Test
|
@Test
|
||||||
public void delegateMessageException() throws Exception {
|
public void delegateMessageException() throws Exception {
|
||||||
|
|
||||||
StubSockJsConfig sockJsConfig = new StubSockJsConfig();
|
StubSockJsServiceConfig sockJsConfig = new StubSockJsServiceConfig();
|
||||||
|
|
||||||
this.servletRequest.setContent("[\"x\"]".getBytes("UTF-8"));
|
this.servletRequest.setContent("[\"x\"]".getBytes("UTF-8"));
|
||||||
|
|
||||||
|
@ -117,11 +120,11 @@ public class HttpReceivingTransportHandlerTests extends AbstractHttpRequestTest
|
||||||
|
|
||||||
try {
|
try {
|
||||||
XhrTransportHandler transportHandler = new XhrTransportHandler();
|
XhrTransportHandler transportHandler = new XhrTransportHandler();
|
||||||
transportHandler.setSockJsConfiguration(sockJsConfig);
|
transportHandler.setSockJsServiceConfiguration(sockJsConfig);
|
||||||
transportHandler.handleRequest(this.request, this.response, webSocketHandler, session);
|
transportHandler.handleRequest(this.request, this.response, webSocketHandler, session);
|
||||||
fail("Expected exception");
|
fail("Expected exception");
|
||||||
}
|
}
|
||||||
catch (TransportErrorException ex) {
|
catch (SockJsProcessingException ex) {
|
||||||
assertEquals(CloseStatus.SERVER_ERROR, session.getStatus());
|
assertEquals(CloseStatus.SERVER_ERROR, session.getStatus());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,9 +134,9 @@ public class HttpReceivingTransportHandlerTests extends AbstractHttpRequestTest
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
WebSocketHandler webSocketHandler = mock(WebSocketHandler.class);
|
WebSocketHandler webSocketHandler = mock(WebSocketHandler.class);
|
||||||
AbstractSockJsSession session = new TestSockJsSession("1", new StubSockJsConfig(), webSocketHandler);
|
AbstractSockJsSession session = new TestSockJsSession("1", new StubSockJsServiceConfig(), webSocketHandler);
|
||||||
|
|
||||||
transportHandler.setSockJsConfiguration(new StubSockJsConfig());
|
transportHandler.setSockJsServiceConfiguration(new StubSockJsServiceConfig());
|
||||||
transportHandler.handleRequest(this.request, this.response, webSocketHandler, session);
|
transportHandler.handleRequest(this.request, this.response, webSocketHandler, session);
|
||||||
|
|
||||||
assertEquals("text/plain;charset=UTF-8", this.response.getHeaders().getContentType().toString());
|
assertEquals("text/plain;charset=UTF-8", this.response.getHeaders().getContentType().toString());
|
||||||
|
@ -145,7 +148,7 @@ public class HttpReceivingTransportHandlerTests extends AbstractHttpRequestTest
|
||||||
resetResponse();
|
resetResponse();
|
||||||
|
|
||||||
WebSocketHandler webSocketHandler = mock(WebSocketHandler.class);
|
WebSocketHandler webSocketHandler = mock(WebSocketHandler.class);
|
||||||
AbstractSockJsSession session = new TestSockJsSession("1", new StubSockJsConfig(), webSocketHandler);
|
AbstractSockJsSession session = new TestSockJsSession("1", new StubSockJsServiceConfig(), webSocketHandler);
|
||||||
|
|
||||||
new XhrTransportHandler().handleRequest(this.request, this.response, webSocketHandler, session);
|
new XhrTransportHandler().handleRequest(this.request, this.response, webSocketHandler, session);
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.handler;
|
||||||
|
|
||||||
import java.sql.Date;
|
import java.sql.Date;
|
||||||
|
|
||||||
|
@ -23,10 +23,18 @@ import org.junit.Test;
|
||||||
import org.springframework.scheduling.TaskScheduler;
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
import org.springframework.web.socket.AbstractHttpRequestTests;
|
import org.springframework.web.socket.AbstractHttpRequestTests;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.AbstractSockJsSession;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
import org.springframework.web.socket.sockjs.transport.handler.AbstractHttpSendingTransportHandler;
|
||||||
import org.springframework.web.socket.sockjs.StubSockJsConfig;
|
import org.springframework.web.socket.sockjs.transport.handler.EventSourceTransportHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.handler.HtmlFileTransportHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.handler.JsonpPollingTransportHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.handler.XhrPollingTransportHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.handler.XhrStreamingTransportHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.PollingSockJsSession;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.StreamingSockJsSession;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.StubSockJsServiceConfig;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Matchers.*;
|
import static org.mockito.Matchers.*;
|
||||||
|
@ -41,7 +49,7 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
|
||||||
|
|
||||||
private WebSocketHandler webSocketHandler;
|
private WebSocketHandler webSocketHandler;
|
||||||
|
|
||||||
private StubSockJsConfig sockJsConfig;
|
private StubSockJsServiceConfig sockJsConfig;
|
||||||
|
|
||||||
private TaskScheduler taskScheduler;
|
private TaskScheduler taskScheduler;
|
||||||
|
|
||||||
|
@ -54,7 +62,7 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
|
||||||
this.webSocketHandler = mock(WebSocketHandler.class);
|
this.webSocketHandler = mock(WebSocketHandler.class);
|
||||||
this.taskScheduler = mock(TaskScheduler.class);
|
this.taskScheduler = mock(TaskScheduler.class);
|
||||||
|
|
||||||
this.sockJsConfig = new StubSockJsConfig();
|
this.sockJsConfig = new StubSockJsServiceConfig();
|
||||||
this.sockJsConfig.setTaskScheduler(this.taskScheduler);
|
this.sockJsConfig.setTaskScheduler(this.taskScheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +70,7 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
|
||||||
public void handleRequestXhr() throws Exception {
|
public void handleRequestXhr() throws Exception {
|
||||||
|
|
||||||
XhrPollingTransportHandler transportHandler = new XhrPollingTransportHandler();
|
XhrPollingTransportHandler transportHandler = new XhrPollingTransportHandler();
|
||||||
transportHandler.setSockJsConfiguration(this.sockJsConfig);
|
transportHandler.setSockJsServiceConfiguration(this.sockJsConfig);
|
||||||
|
|
||||||
AbstractSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
AbstractSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
||||||
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
||||||
|
@ -89,7 +97,7 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
|
||||||
public void jsonpTransport() throws Exception {
|
public void jsonpTransport() throws Exception {
|
||||||
|
|
||||||
JsonpPollingTransportHandler transportHandler = new JsonpPollingTransportHandler();
|
JsonpPollingTransportHandler transportHandler = new JsonpPollingTransportHandler();
|
||||||
transportHandler.setSockJsConfiguration(this.sockJsConfig);
|
transportHandler.setSockJsServiceConfiguration(this.sockJsConfig);
|
||||||
PollingSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
PollingSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
||||||
|
|
||||||
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
||||||
|
@ -110,7 +118,7 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
|
||||||
public void handleRequestXhrStreaming() throws Exception {
|
public void handleRequestXhrStreaming() throws Exception {
|
||||||
|
|
||||||
XhrStreamingTransportHandler transportHandler = new XhrStreamingTransportHandler();
|
XhrStreamingTransportHandler transportHandler = new XhrStreamingTransportHandler();
|
||||||
transportHandler.setSockJsConfiguration(this.sockJsConfig);
|
transportHandler.setSockJsServiceConfiguration(this.sockJsConfig);
|
||||||
AbstractSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
AbstractSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
||||||
|
|
||||||
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
||||||
|
@ -124,7 +132,7 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
|
||||||
public void htmlFileTransport() throws Exception {
|
public void htmlFileTransport() throws Exception {
|
||||||
|
|
||||||
HtmlFileTransportHandler transportHandler = new HtmlFileTransportHandler();
|
HtmlFileTransportHandler transportHandler = new HtmlFileTransportHandler();
|
||||||
transportHandler.setSockJsConfiguration(this.sockJsConfig);
|
transportHandler.setSockJsServiceConfiguration(this.sockJsConfig);
|
||||||
StreamingSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
StreamingSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
||||||
|
|
||||||
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
||||||
|
@ -145,7 +153,7 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
|
||||||
public void eventSourceTransport() throws Exception {
|
public void eventSourceTransport() throws Exception {
|
||||||
|
|
||||||
EventSourceTransportHandler transportHandler = new EventSourceTransportHandler();
|
EventSourceTransportHandler transportHandler = new EventSourceTransportHandler();
|
||||||
transportHandler.setSockJsConfiguration(this.sockJsConfig);
|
transportHandler.setSockJsServiceConfiguration(this.sockJsConfig);
|
||||||
StreamingSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
StreamingSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
|
||||||
|
|
||||||
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -28,12 +28,11 @@ import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.BaseAbstractSockJsSessionTests;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.DefaultFrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame;
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame.FrameFormat;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.DefaultFrameFormat;
|
import org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession;
|
||||||
import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
|
import org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSessionTests.TestAbstractHttpSockJsSession;
|
||||||
import org.springframework.web.socket.sockjs.transport.AbstractHttpSockJsSessionTests.TestAbstractHttpSockJsSession;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
@ -128,7 +127,7 @@ public class AbstractHttpSockJsSessionTests extends BaseAbstractSockJsSessionTes
|
||||||
private boolean heartbeatScheduled;
|
private boolean heartbeatScheduled;
|
||||||
|
|
||||||
|
|
||||||
public TestAbstractHttpSockJsSession(SockJsConfiguration config, WebSocketHandler handler) {
|
public TestAbstractHttpSockJsSession(SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super("1", config, handler);
|
super("1", config, handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.Date;
|
import java.sql.Date;
|
||||||
|
@ -24,6 +24,9 @@ import java.util.concurrent.ScheduledFuture;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.TextMessage;
|
import org.springframework.web.socket.TextMessage;
|
||||||
|
import org.springframework.web.socket.sockjs.SockJsProcessingException;
|
||||||
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Matchers.*;
|
import static org.mockito.Matchers.*;
|
||||||
|
@ -210,7 +213,7 @@ public class AbstractSockJsSessionTests extends BaseAbstractSockJsSessionTests<T
|
||||||
this.session.writeFrame(SockJsFrame.openFrame());
|
this.session.writeFrame(SockJsFrame.openFrame());
|
||||||
fail("expected exception");
|
fail("expected exception");
|
||||||
}
|
}
|
||||||
catch (TransportErrorException ex) {
|
catch (SockJsProcessingException ex) {
|
||||||
assertEquals(CloseStatus.SERVER_ERROR, this.session.getStatus());
|
assertEquals(CloseStatus.SERVER_ERROR, this.session.getStatus());
|
||||||
verify(this.webSocketHandler).afterConnectionClosed(this.session, CloseStatus.SERVER_ERROR);
|
verify(this.webSocketHandler).afterConnectionClosed(this.session, CloseStatus.SERVER_ERROR);
|
||||||
}
|
}
|
|
@ -14,11 +14,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.springframework.scheduling.TaskScheduler;
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
@ -32,7 +33,7 @@ public abstract class BaseAbstractSockJsSessionTests<S extends AbstractSockJsSes
|
||||||
|
|
||||||
protected WebSocketHandler webSocketHandler;
|
protected WebSocketHandler webSocketHandler;
|
||||||
|
|
||||||
protected StubSockJsConfig sockJsConfig;
|
protected StubSockJsServiceConfig sockJsConfig;
|
||||||
|
|
||||||
protected TaskScheduler taskScheduler;
|
protected TaskScheduler taskScheduler;
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ public abstract class BaseAbstractSockJsSessionTests<S extends AbstractSockJsSes
|
||||||
this.webSocketHandler = mock(WebSocketHandler.class);
|
this.webSocketHandler = mock(WebSocketHandler.class);
|
||||||
this.taskScheduler = mock(TaskScheduler.class);
|
this.taskScheduler = mock(TaskScheduler.class);
|
||||||
|
|
||||||
this.sockJsConfig = new StubSockJsConfig();
|
this.sockJsConfig = new StubSockJsServiceConfig();
|
||||||
this.sockJsConfig.setTaskScheduler(this.taskScheduler);
|
this.sockJsConfig.setTaskScheduler(this.taskScheduler);
|
||||||
|
|
||||||
this.session = initSockJsSession();
|
this.session = initSockJsSession();
|
|
@ -14,16 +14,17 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import org.springframework.scheduling.TaskScheduler;
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||||
import org.springframework.web.socket.sockjs.support.Jackson2SockJsMessageCodec;
|
import org.springframework.web.socket.sockjs.support.frame.Jackson2SockJsMessageCodec;
|
||||||
|
import org.springframework.web.socket.sockjs.support.frame.SockJsMessageCodec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class StubSockJsConfig implements SockJsConfiguration {
|
public class StubSockJsServiceConfig implements SockJsServiceConfig {
|
||||||
|
|
||||||
private int streamBytesLimit = 128 * 1024;
|
private int streamBytesLimit = 128 * 1024;
|
||||||
|
|
||||||
|
@ -62,12 +63,8 @@ public class StubSockJsConfig implements SockJsConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SockJsMessageCodec getMessageCodecRequired() {
|
|
||||||
return this.messageCodec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SockJsMessageCodec getMessageCodec() {
|
public SockJsMessageCodec getMessageCodec() {
|
||||||
return messageCodec;
|
return this.messageCodec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMessageCodec(SockJsMessageCodec messageCodec) {
|
public void setMessageCodec(SockJsMessageCodec messageCodec) {
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -22,6 +22,8 @@ import java.util.List;
|
||||||
|
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.sockjs.support.frame.SockJsFrame;
|
||||||
|
import org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
@ -43,7 +45,7 @@ public class TestSockJsSession extends AbstractSockJsSession {
|
||||||
private String subProtocol;
|
private String subProtocol;
|
||||||
|
|
||||||
|
|
||||||
public TestSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler handler) {
|
public TestSockJsSession(String sessionId, SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super(sessionId, config, handler);
|
super(sessionId, config, handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.web.socket.sockjs.transport;
|
package org.springframework.web.socket.sockjs.transport.session;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -27,9 +27,8 @@ import org.junit.Test;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.TextMessage;
|
import org.springframework.web.socket.TextMessage;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.sockjs.BaseAbstractSockJsSessionTests;
|
import org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession;
|
||||||
import org.springframework.web.socket.sockjs.SockJsConfiguration;
|
import org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSessionTests.TestWebSocketServerSockJsSession;
|
||||||
import org.springframework.web.socket.sockjs.transport.WebSocketServerSockJsSessionTests.TestWebSocketServerSockJsSession;
|
|
||||||
import org.springframework.web.socket.support.TestWebSocketSession;
|
import org.springframework.web.socket.support.TestWebSocketSession;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
@ -134,7 +133,7 @@ public class WebSocketServerSockJsSessionTests extends BaseAbstractSockJsSession
|
||||||
|
|
||||||
private final List<String> heartbeatSchedulingEvents = new ArrayList<>();
|
private final List<String> heartbeatSchedulingEvents = new ArrayList<>();
|
||||||
|
|
||||||
public TestWebSocketServerSockJsSession(SockJsConfiguration config, WebSocketHandler handler) {
|
public TestWebSocketServerSockJsSession(SockJsServiceConfig config, WebSocketHandler handler) {
|
||||||
super("1", config, handler);
|
super("1", config, handler);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue