public abstract class AbstractSockJsService extends java.lang.Object implements SockJsService, CorsConfigurationSource
SockJsService
implementations that provides SockJS
path resolution and handling of static SockJS requests (e.g. "/info", "/iframe.html",
etc). Sub-classes must handle session URLs (i.e. transport-specific requests).
By default, only same origin requests are allowed. Use setAllowedOrigins(List)
to specify a list of allowed origins (a list containing "*" will allow all origins).Modifier and Type | Class and Description |
---|---|
private static interface |
AbstractSockJsService.SockJsRequestHandler |
Modifier and Type | Field and Description |
---|---|
private java.util.List<java.lang.String> |
allowedOrigins |
private java.lang.String |
clientLibraryUrl |
private long |
disconnectDelay |
private long |
heartbeatTime |
private int |
httpMessageCacheSize |
private AbstractSockJsService.SockJsRequestHandler |
iframeHandler |
private AbstractSockJsService.SockJsRequestHandler |
infoHandler |
protected Log |
logger |
private java.lang.String |
name |
private static long |
ONE_YEAR |
private static java.util.Random |
random |
private boolean |
sessionCookieNeeded |
private int |
streamBytesLimit |
private boolean |
suppressCors |
private TaskScheduler |
taskScheduler |
private static java.nio.charset.Charset |
UTF8_CHARSET |
private boolean |
webSocketEnabled |
private static java.lang.String |
XFRAME_OPTIONS_HEADER |
Constructor and Description |
---|
AbstractSockJsService(TaskScheduler scheduler) |
Modifier and Type | Method and Description |
---|---|
protected void |
addCacheHeaders(ServerHttpResponse response) |
protected void |
addNoCacheHeaders(ServerHttpResponse response) |
protected boolean |
checkOrigin(ServerHttpRequest request,
ServerHttpResponse response,
HttpMethod... httpMethods) |
java.util.List<java.lang.String> |
getAllowedOrigins() |
CorsConfiguration |
getCorsConfiguration(HttpServletRequest request)
Return a
CorsConfiguration based on the incoming request. |
long |
getDisconnectDelay()
Return the amount of time in milliseconds before a client is considered disconnected.
|
long |
getHeartbeatTime()
Return the amount of time in milliseconds when the server has not sent
any messages.
|
int |
getHttpMessageCacheSize()
Return the size of the HTTP message cache.
|
java.lang.String |
getName()
Return the unique name associated with this service.
|
java.lang.String |
getSockJsClientLibraryUrl()
Return he URL to the SockJS JavaScript client library.
|
int |
getStreamBytesLimit()
Return the minimum number of bytes that can be sent over a single HTTP
streaming request before it will be closed.
|
TaskScheduler |
getTaskScheduler()
A scheduler instance to use for scheduling heart-beat messages.
|
protected abstract void |
handleRawWebSocketRequest(ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler webSocketHandler)
Handle request for raw WebSocket communication, i.e.
|
void |
handleRequest(ServerHttpRequest request,
ServerHttpResponse response,
java.lang.String sockJsPath,
WebSocketHandler wsHandler)
This method determines the SockJS path and handles SockJS static URLs.
|
protected abstract void |
handleTransportRequest(ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler webSocketHandler,
java.lang.String sessionId,
java.lang.String transport)
Handle a SockJS session URL (i.e.
|
boolean |
isSessionCookieNeeded()
Return whether the JSESSIONID cookie is required for the application to function.
|
boolean |
isWebSocketEnabled()
Return whether WebSocket transport is enabled.
|
protected void |
sendMethodNotAllowed(ServerHttpResponse response,
HttpMethod... httpMethods) |
void |
setAllowedOrigins(java.util.List<java.lang.String> allowedOrigins)
Configure allowed
Origin header values. |
void |
setDisconnectDelay(long disconnectDelay)
The amount of time in milliseconds before a client is considered
disconnected after not having a receiving connection, i.e.
|
void |
setHeartbeatTime(long heartbeatTime)
Specify 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.
|
void |
setHttpMessageCacheSize(int httpMessageCacheSize)
The number of server-to-client messages that a session can cache while waiting
for the next HTTP polling request from the client.
|
void |
setName(java.lang.String name)
Set a unique name for this service (mainly for logging purposes).
|
void |
setSessionCookieNeeded(boolean sessionCookieNeeded)
The SockJS protocol requires a server to respond to an initial "/info" request from
clients with a "cookie_needed" boolean property that indicates whether the use of a
JSESSIONID cookie is required for the application to function correctly, e.g.
|
void |
setSockJsClientLibraryUrl(java.lang.String clientLibraryUrl)
Transports with no native cross-domain communication (e.g.
|
void |
setStreamBytesLimit(int streamBytesLimit)
Streaming transports save responses on the client side and don't free
memory used by delivered messages.
|
void |
setSuppressCors(boolean suppressCors)
This option can be used to disable automatic addition of CORS headers for
SockJS requests.
|
void |
setWebSocketEnabled(boolean webSocketEnabled)
Some load balancers do not support WebSocket.
|
boolean |
shouldSuppressCors() |
private boolean |
validatePath(ServerHttpRequest request)
Ensure the path does not contain a file extension, either in the filename
(e.g.
|
protected boolean |
validateRequest(java.lang.String serverId,
java.lang.String sessionId,
java.lang.String transport) |
private static final java.nio.charset.Charset UTF8_CHARSET
private static final long ONE_YEAR
private static final java.util.Random random
private static final java.lang.String XFRAME_OPTIONS_HEADER
protected final Log logger
private final TaskScheduler taskScheduler
private java.lang.String name
private java.lang.String clientLibraryUrl
private int streamBytesLimit
private boolean sessionCookieNeeded
private long heartbeatTime
private long disconnectDelay
private int httpMessageCacheSize
private boolean webSocketEnabled
private final java.util.List<java.lang.String> allowedOrigins
private boolean suppressCors
private final AbstractSockJsService.SockJsRequestHandler infoHandler
private final AbstractSockJsService.SockJsRequestHandler iframeHandler
public AbstractSockJsService(TaskScheduler scheduler)
public TaskScheduler getTaskScheduler()
public void setName(java.lang.String name)
public java.lang.String getName()
public void setSockJsClientLibraryUrl(java.lang.String clientLibraryUrl)
By default this is set to point to "https://cdn.jsdelivr.net/sockjs/1.0.0/sockjs.min.js". However, it can also be set to point to a URL served by the application.
Note that it's possible to specify a relative URL in which case the URL must be relative to the iframe URL. For example assuming a SockJS endpoint mapped to "/sockjs", and resulting iframe URL "/sockjs/iframe.html", then the the relative URL must start with "../../" to traverse up to the location above the SockJS mapping. In case of a prefix-based Servlet mapping one more traversal may be needed.
public java.lang.String getSockJsClientLibraryUrl()
public void setStreamBytesLimit(int streamBytesLimit)
The default value is 128K (i.e. 128 * 1024).
public int getStreamBytesLimit()
public void setSessionCookieNeeded(boolean sessionCookieNeeded)
This is especially important for IE 8,9 that support XDomainRequest -- a modified AJAX/XHR -- that can do requests across domains but does not send any cookies. In those cases, the SockJS client prefers the "iframe-htmlfile" transport over "xdr-streaming" in order to be able to send cookies.
The SockJS protocol also expects a SockJS service to echo back the JSESSIONID cookie when this property is set to true. However, when running in a Servlet container this is not necessary since the container takes care of it.
The default value is "true" to maximize the chance for applications to work correctly in IE 8,9 with support for cookies (and the JSESSIONID cookie in particular). However, an application can choose to set this to "false" if the use of cookies (and HTTP session) is not required.
public boolean isSessionCookieNeeded()
public void setHeartbeatTime(long heartbeatTime)
The default value is 25,000 (25 seconds).
public long getHeartbeatTime()
public void setDisconnectDelay(long disconnectDelay)
The default value is 5000.
public long getDisconnectDelay()
public void setHttpMessageCacheSize(int httpMessageCacheSize)
The amount of time between HTTP requests should be relatively brief and will
not exceed the allows disconnect delay (see setDisconnectDelay(long)
);
5 seconds by default.
The default size is 100.
public int getHttpMessageCacheSize()
public void setWebSocketEnabled(boolean webSocketEnabled)
The default value is "true".
public boolean isWebSocketEnabled()
public void setAllowedOrigins(java.util.List<java.lang.String> allowedOrigins)
Origin
header values. This check is mostly
designed for browsers. There is nothing preventing other types of client
to modify the Origin
header value.
When SockJS is enabled and origins are restricted, transport types that do not allow to check request origin (JSONP and Iframe based transports) are disabled. As a consequence, IE 6 to 9 are not supported when origins are restricted.
Each provided allowed origin must have a scheme, and optionally a port (e.g. "http://example.org", "http://example.org:9090"). An allowed origin string may also be "*" in which case all origins are allowed.
public java.util.List<java.lang.String> getAllowedOrigins()
setAllowedOrigins(List)
public void setSuppressCors(boolean suppressCors)
The default value is "false".
public boolean shouldSuppressCors()
setSuppressCors(boolean)
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response, java.lang.String sockJsPath, WebSocketHandler wsHandler) throws SockJsException
handleRequest
in interface SockJsService
request
- the current requestresponse
- the current responsesockJsPath
- the remainder of the path within the SockJS service prefixwsHandler
- the handler that will exchange messages with the SockJS clientSockJsException
- raised when request processing fails; generally, failed
attempts to send messages to clients automatically close the SockJS session
and raise SockJsTransportFailureException
; failed attempts to read
messages from clients do not automatically close the session and may result
in SockJsMessageDeliveryException
or SockJsException
;
exceptions from the WebSocketHandler can be handled internally or through
ExceptionWebSocketHandlerDecorator
or some alternative decorator.
The former is automatically added when using
SockJsHttpRequestHandler
.protected boolean validateRequest(java.lang.String serverId, java.lang.String sessionId, java.lang.String transport)
private boolean validatePath(ServerHttpRequest request)
Since the last part of the path is expected to be a transport type, the presence of an extension would not work. All we need to do is check if there are any path parameters, which would have been removed from the SockJS path during request mapping, and if found reject the request.
protected abstract void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler webSocketHandler) throws java.io.IOException
java.io.IOException
protected abstract void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler webSocketHandler, java.lang.String sessionId, java.lang.String transport) throws SockJsException
SockJsException
protected boolean checkOrigin(ServerHttpRequest request, ServerHttpResponse response, HttpMethod... httpMethods) throws java.io.IOException
java.io.IOException
public CorsConfiguration getCorsConfiguration(HttpServletRequest request)
CorsConfigurationSource
CorsConfiguration
based on the incoming request.getCorsConfiguration
in interface CorsConfigurationSource
protected void addCacheHeaders(ServerHttpResponse response)
protected void addNoCacheHeaders(ServerHttpResponse response)
protected void sendMethodNotAllowed(ServerHttpResponse response, HttpMethod... httpMethods)