INT-4039: Add Allowed Origins to WebSockets
JIRA: https://jira.spring.io/browse/INT-4039 Also add `suppressCors` for the `SockJsServiceOptions` Polishing according PR comments
This commit is contained in:
committed by
Gary Russell
parent
d414383eac
commit
f5488efcaa
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -58,6 +58,8 @@ public class ServerWebSocketContainer extends IntegrationWebSocketContainer impl
|
||||
|
||||
private SockJsServiceOptions sockJsServiceOptions;
|
||||
|
||||
private String[] origins;
|
||||
|
||||
public ServerWebSocketContainer(String... paths) {
|
||||
this.paths = paths;
|
||||
}
|
||||
@@ -91,6 +93,18 @@ public class ServerWebSocketContainer extends IntegrationWebSocketContainer impl
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure allowed {@code Origin} header values.
|
||||
* @param origins the origins to allow.
|
||||
* @return the current ServerWebSocketContainer
|
||||
* @since 4.3
|
||||
* @see WebSocketHandlerRegistration#setAllowedOrigins(String...)
|
||||
*/
|
||||
public ServerWebSocketContainer setAllowedOrigins(String... origins) {
|
||||
this.origins = origins; //NOSONAR - fully delegated
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerWebSocketContainer withSockJs(SockJsServiceOptions... sockJsServiceOptions) {
|
||||
if (ObjectUtils.isEmpty(sockJsServiceOptions)) {
|
||||
this.sockJsServiceOptions = new SockJsServiceOptions();
|
||||
@@ -118,7 +132,8 @@ public class ServerWebSocketContainer extends IntegrationWebSocketContainer impl
|
||||
|
||||
WebSocketHandlerRegistration registration = registry.addHandler(webSocketHandler, this.paths)
|
||||
.setHandshakeHandler(this.handshakeHandler)
|
||||
.addInterceptors(this.interceptors);
|
||||
.addInterceptors(this.interceptors)
|
||||
.setAllowedOrigins(this.origins);
|
||||
|
||||
if (this.sockJsServiceOptions != null) {
|
||||
SockJsServiceRegistration sockJsServiceRegistration = registration.withSockJS();
|
||||
@@ -155,6 +170,10 @@ public class ServerWebSocketContainer extends IntegrationWebSocketContainer impl
|
||||
if (this.sockJsServiceOptions.messageCodec != null) {
|
||||
sockJsServiceRegistration.setMessageCodec(this.sockJsServiceOptions.messageCodec);
|
||||
}
|
||||
if (this.sockJsServiceOptions.suppressCors != null) {
|
||||
sockJsServiceRegistration.setSupressCors(this.sockJsServiceOptions.suppressCors);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -184,6 +203,8 @@ public class ServerWebSocketContainer extends IntegrationWebSocketContainer impl
|
||||
|
||||
private SockJsMessageCodec messageCodec;
|
||||
|
||||
private Boolean suppressCors;
|
||||
|
||||
public SockJsServiceOptions setTaskScheduler(TaskScheduler taskScheduler) {
|
||||
this.taskScheduler = taskScheduler;
|
||||
return this;
|
||||
@@ -234,6 +255,11 @@ public class ServerWebSocketContainer extends IntegrationWebSocketContainer impl
|
||||
return this;
|
||||
}
|
||||
|
||||
public SockJsServiceOptions setSuppressCors(boolean suppressCors) {
|
||||
this.suppressCors = suppressCors;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -87,6 +87,7 @@ public class ServerWebSocketContainerParser extends AbstractSingleBeanDefinition
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(sockjsBuilder, sockjs, "scheduler",
|
||||
"taskScheduler");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(sockjsBuilder, sockjs, "message-codec");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(sockjsBuilder, sockjs, "suppress-cors");
|
||||
|
||||
String transportHandlers = sockjs.getAttribute("transport-handlers");
|
||||
if (StringUtils.hasText(transportHandlers)) {
|
||||
@@ -103,6 +104,7 @@ public class ServerWebSocketContainerParser extends AbstractSingleBeanDefinition
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "handshake-handler");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-buffer-size-limit");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-time-limit");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "allowed-origins");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -248,6 +248,15 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="suppress-cors" type="xsd:string" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
This option can be used to disable automatic addition
|
||||
of CORS headers for SockJS requests.
|
||||
The default value is 'false'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
@@ -311,6 +320,24 @@
|
||||
<xsd:union memberTypes="xsd:int xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="allowed-origins" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Configure allowed Origin header values. Multiple origins may be specified
|
||||
as a comma-separated list.
|
||||
|
||||
This check is mostly designed for browser clients. There is noting preventing other
|
||||
types of client to modify the Origin header value.
|
||||
|
||||
When SockJS is enabled and allowed origins are restricted, transport types that do not
|
||||
use Origin headers for cross origin requests (jsonp-polling, iframe-xhr-polling,
|
||||
iframe-eventsource and iframe-htmlfile) are disabled. As a consequence, IE6/IE7 are not
|
||||
supported and IE8/IE9 will only be supported without cookies.
|
||||
|
||||
By default, all origins are allowed.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
send-time-limit="100"
|
||||
handshake-handler="handshakeHandler"
|
||||
handshake-interceptors="handshakeInterceptor"
|
||||
decorator-factories="decoratorFactory">
|
||||
decorator-factories="decoratorFactory"
|
||||
allowed-origins="http://foo.com">
|
||||
<int-websocket:sockjs client-library-url="https://foo.sock.js"
|
||||
disconnect-delay="4000"
|
||||
heartbeat-time="30000"
|
||||
@@ -28,34 +29,35 @@
|
||||
stream-bytes-limit="2000"
|
||||
websocket-enabled="false"
|
||||
scheduler="taskScheduler"
|
||||
message-codec="sockJsMessageCodec"/>
|
||||
message-codec="sockJsMessageCodec"
|
||||
suppress-cors="true" />
|
||||
</int-websocket:server-container>
|
||||
|
||||
<bean id="handshakeHandler" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.web.socket.server.HandshakeHandler"/>
|
||||
<constructor-arg value="org.springframework.web.socket.server.HandshakeHandler" />
|
||||
</bean>
|
||||
|
||||
<bean id="handshakeInterceptor" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.web.socket.server.HandshakeInterceptor"/>
|
||||
<constructor-arg value="org.springframework.web.socket.server.HandshakeInterceptor" />
|
||||
</bean>
|
||||
|
||||
<bean id="sockJsMessageCodec" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.web.socket.sockjs.frame.SockJsMessageCodec"/>
|
||||
<constructor-arg value="org.springframework.web.socket.sockjs.frame.SockJsMessageCodec" />
|
||||
</bean>
|
||||
|
||||
<bean id="decoratorFactory"
|
||||
class="org.springframework.integration.websocket.config.WebSocketParserTests.TestWebSocketHandlerDecoratorFactory" />
|
||||
|
||||
<websocket:message-broker application-destination-prefix="/app">
|
||||
<websocket:stomp-endpoint path="/foo"/>
|
||||
<websocket:simple-broker prefix="/topic"/>
|
||||
<websocket:stomp-endpoint path="/foo" />
|
||||
<websocket:simple-broker prefix="/topic" />
|
||||
</websocket:message-broker>
|
||||
|
||||
<int-websocket:inbound-channel-adapter id="defaultInboundAdapter" container="serverWebSocketContainer"
|
||||
use-broker="true"/>
|
||||
use-broker="true" />
|
||||
|
||||
<bean id="webSocketClient" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.web.socket.client.WebSocketClient"/>
|
||||
<constructor-arg value="org.springframework.web.socket.client.WebSocketClient" />
|
||||
</bean>
|
||||
|
||||
<int-websocket:client-container id="clientWebSocketContainer"
|
||||
@@ -67,18 +69,19 @@
|
||||
origin="FOO"
|
||||
phase="100">
|
||||
<int-websocket:http-headers>
|
||||
<entry key="FOO" value="BAR,baz"/>
|
||||
<entry key="FOO" value="BAR,baz" />
|
||||
</int-websocket:http-headers>
|
||||
</int-websocket:client-container>
|
||||
|
||||
<bean id="stompSubProtocolHandler" class="org.springframework.web.socket.messaging.StompSubProtocolHandler"/>
|
||||
<bean id="stompSubProtocolHandler" class="org.springframework.web.socket.messaging.StompSubProtocolHandler" />
|
||||
|
||||
<bean id="passThruSubProtocolHandler"
|
||||
class="org.springframework.integration.websocket.support.PassThruSubProtocolHandler"/>
|
||||
class="org.springframework.integration.websocket.support.PassThruSubProtocolHandler" />
|
||||
|
||||
<bean id="simpleMessageConverter" class="org.springframework.integration.support.converter.SimpleMessageConverter"/>
|
||||
<bean id="simpleMessageConverter"
|
||||
class="org.springframework.integration.support.converter.SimpleMessageConverter" />
|
||||
|
||||
<bean id="mapMessageConverter" class="org.springframework.integration.support.converter.MapMessageConverter"/>
|
||||
<bean id="mapMessageConverter" class="org.springframework.integration.support.converter.MapMessageConverter" />
|
||||
|
||||
<int-websocket:inbound-channel-adapter id="customInboundAdapter" container="clientWebSocketContainer"
|
||||
auto-startup="false"
|
||||
@@ -90,23 +93,23 @@
|
||||
channel="clientInboundChannel"
|
||||
error-channel="errorChannel"
|
||||
send-timeout="2000"
|
||||
phase="200"/>
|
||||
phase="200" />
|
||||
|
||||
<int:channel id="clientInboundChannel"/>
|
||||
<int:channel id="clientInboundChannel" />
|
||||
|
||||
<int-websocket:outbound-channel-adapter id="defaultOutboundAdapter" container="serverWebSocketContainer"/>
|
||||
<int-websocket:outbound-channel-adapter id="defaultOutboundAdapter" container="serverWebSocketContainer" />
|
||||
|
||||
<int-websocket:outbound-channel-adapter id="customOutboundAdapter" container="clientWebSocketContainer"
|
||||
default-protocol-handler="stompSubProtocolHandler"
|
||||
protocol-handlers="passThruSubProtocolHandler"
|
||||
message-converters="simpleMessageConverter,mapMessageConverter"
|
||||
merge-with-default-converters="true"
|
||||
channel="clientOutboundChannel"/>
|
||||
channel="clientOutboundChannel" />
|
||||
|
||||
<int:channel id="clientOutboundChannel"/>
|
||||
<int:channel id="clientOutboundChannel" />
|
||||
|
||||
<int-websocket:client-container id="simpleClientWebSocketContainer"
|
||||
client="webSocketClient"
|
||||
uri="ws://foo.bar"/>
|
||||
uri="ws://foo.bar" />
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.integration.websocket.config;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -164,6 +165,8 @@ public class WebSocketParserTests {
|
||||
assertSame(this.handshakeInterceptor, interceptors[0]);
|
||||
assertEquals(100, TestUtils.getPropertyValue(this.serverWebSocketContainer, "sendTimeLimit"));
|
||||
assertEquals(100000, TestUtils.getPropertyValue(this.serverWebSocketContainer, "sendBufferSizeLimit"));
|
||||
assertArrayEquals(new String[] {"http://foo.com"},
|
||||
TestUtils.getPropertyValue(this.serverWebSocketContainer, "origins", String[].class));
|
||||
|
||||
WebSocketHandlerDecoratorFactory[] decoratorFactories =
|
||||
TestUtils.getPropertyValue(this.serverWebSocketContainer, "decoratorFactories",
|
||||
@@ -189,6 +192,7 @@ public class WebSocketParserTests {
|
||||
assertEquals("https://foo.sock.js", sockJsService.getSockJsClientLibraryUrl());
|
||||
assertFalse(sockJsService.isSessionCookieNeeded());
|
||||
assertFalse(sockJsService.isWebSocketEnabled());
|
||||
assertTrue(sockJsService.shouldSuppressCors());
|
||||
|
||||
assertSame(this.serverWebSocketContainer,
|
||||
TestUtils.getPropertyValue(this.defaultInboundAdapter, "webSocketContainer"));
|
||||
|
||||
@@ -188,7 +188,10 @@ public class WebSocketServerTests {
|
||||
|
||||
@Bean
|
||||
public IntegrationWebSocketContainer clientWebSocketContainer() {
|
||||
return new ClientWebSocketContainer(webSocketClient(), server().getWsBaseUrl() + "/ws");
|
||||
ClientWebSocketContainer clientWebSocketContainer =
|
||||
new ClientWebSocketContainer(webSocketClient(), server().getWsBaseUrl() + "/ws");
|
||||
clientWebSocketContainer.setOrigin("http://foo.com");
|
||||
return clientWebSocketContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -251,6 +254,7 @@ public class WebSocketServerTests {
|
||||
public ServerWebSocketContainer serverWebSocketContainer() {
|
||||
return new ServerWebSocketContainer("/ws")
|
||||
.setDecoratorFactories(testWebSocketHandlerDecoratorFactory())
|
||||
.setAllowedOrigins("http://foo.com")
|
||||
.withSockJs();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,18 +41,18 @@ That allows us to reuse many configuration items and infrastructure hooks to bui
|
||||
//Client side
|
||||
@Bean
|
||||
public WebSocketClient webSocketClient() {
|
||||
return new SockJsClient(Collections.<Transport>singletonList(new WebSocketTransport(new JettyWebSocketClient())));
|
||||
return new SockJsClient(Collections.singletonList(new WebSocketTransport(new JettyWebSocketClient())));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationWebSocketContainer clientWebSocketContainer() {
|
||||
return new ClientWebSocketContainer(webSocketClient(), "ws://my.server.com/endpoint");
|
||||
return new ClientWebSocketContainer(webSocketClient(), "ws://my.server.com/endpoint");
|
||||
}
|
||||
|
||||
//Server side
|
||||
@Bean
|
||||
public IntegrationWebSocketContainer serverWebSocketContainer() {
|
||||
return new ServerWebSocketContainer("/endpoint").withSockJs();
|
||||
return new ServerWebSocketContainer("/endpoint").withSockJs();
|
||||
}
|
||||
----
|
||||
|
||||
@@ -131,18 +131,18 @@ To include it in your configuration, simply provide the following namespace decl
|
||||
[source,xml]
|
||||
----
|
||||
<int-websocket:client-container
|
||||
id="" <1>
|
||||
client="" <2>
|
||||
uri="" <3>
|
||||
uri-variables="" <4>
|
||||
origin="" <5>
|
||||
send-time-limit="" <6>
|
||||
send-buffer-size-limit="" <7>
|
||||
auto-startup="" <8>
|
||||
phase=""> <9>
|
||||
<int-websocket:http-headers>
|
||||
<entry key="" value=""/>
|
||||
</int-websocket:http-headers> <10>
|
||||
id="" <1>
|
||||
client="" <2>
|
||||
uri="" <3>
|
||||
uri-variables="" <4>
|
||||
origin="" <5>
|
||||
send-time-limit="" <6>
|
||||
send-buffer-size-limit="" <7>
|
||||
auto-startup="" <8>
|
||||
phase=""> <9>
|
||||
<int-websocket:http-headers>
|
||||
<entry key="" value=""/>
|
||||
</int-websocket:http-headers> <10>
|
||||
</int-websocket:client-container>
|
||||
----
|
||||
|
||||
@@ -197,18 +197,20 @@ See `SmartLifeCycle`.
|
||||
handshake-interceptors="" <4>
|
||||
decorator-factories="" <5>
|
||||
send-time-limit="" <6>
|
||||
send-buffer-size-limit=""> <7>
|
||||
send-buffer-size-limit="" <7>
|
||||
allowed-origins=""> <8>
|
||||
<int-websocket:sockjs
|
||||
client-library-url="" <8>
|
||||
stream-bytes-limit="" <9>
|
||||
session-cookie-needed="" <10>
|
||||
heartbeat-time="" <11>
|
||||
disconnect-delay="" <12>
|
||||
message-cache-size="" <13>
|
||||
websocket-enabled="" <14>
|
||||
scheduler="" <15>
|
||||
message-codec="" <16>
|
||||
transport-handlers="" /> <17>
|
||||
client-library-url="" <9>
|
||||
stream-bytes-limit="" <10>
|
||||
session-cookie-needed="" <11>
|
||||
heartbeat-time="" <12>
|
||||
disconnect-delay="" <13>
|
||||
message-cache-size="" <14>
|
||||
websocket-enabled="" <15>
|
||||
scheduler="" <16>
|
||||
message-codec="" <17>
|
||||
transport-handlers="" <18>
|
||||
suppress-cors="true"="" /> <19>
|
||||
</int-websocket:server-container>
|
||||
----
|
||||
|
||||
@@ -239,7 +241,15 @@ for more information.
|
||||
<7> See the same option on the `<int-websocket:client-container>`.
|
||||
|
||||
|
||||
<8> Transports with no native cross-domain communication (e.g.
|
||||
<8> Configure allowed Origin header values. Multiple origins may be specified as a comma-separated list.
|
||||
This check is mostly designed for browser clients.
|
||||
There is noting preventing other types of client to modify the Origin header value.
|
||||
When SockJS is enabled and allowed origins are restricted, transport types that do not use Origin headers for cross origin requests (jsonp-polling, iframe-xhr-polling, iframe-eventsource and iframe-htmlfile) are disabled.
|
||||
As a consequence, IE6/IE7 are not supported and IE8/IE9 will only be supported without cookies.
|
||||
By default, all origins are allowed.
|
||||
|
||||
|
||||
<9> Transports with no native cross-domain communication (e.g.
|
||||
"eventsource", "htmlfile") must get a simple page from the "foreign" domain in an invisible iframe so that code in the iframe can run from a domain local to the SockJS server.
|
||||
Since the iframe needs to load the SockJS javascript client library, this property allows specifying where to load it from.
|
||||
By default this is set to point to `https://d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.4.min.js`.
|
||||
@@ -249,62 +259,66 @@ For example assuming a SockJS endpoint mapped to "/sockjs", and resulting iframe
|
||||
In case of a prefix-based Servlet mapping one more traversal may be needed.
|
||||
|
||||
|
||||
<9> Minimum number of bytes that can be send over a single HTTP streaming request before it will be closed.
|
||||
<10> Minimum number of bytes that can be send over a single HTTP streaming request before it will be closed.
|
||||
Defaults to `128K` (i.e.
|
||||
128*1024 bytes).
|
||||
|
||||
|
||||
<10> The "cookie_needed" value in the response from the SockJs `"/info"` endpoint.
|
||||
<11> The "cookie_needed" value in the response from the SockJs `"/info"` endpoint.
|
||||
This property indicates whether the use of a JSESSIONID cookie is required for the application to function correctly, e.g.
|
||||
for load balancing or in Java Servlet containers for the use of an HTTP session.
|
||||
|
||||
|
||||
<11> The amount of time in milliseconds when the server has not sent any messages and after which the server should
|
||||
<12> 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.
|
||||
The default value is `25,000` (25 seconds).
|
||||
|
||||
|
||||
<12> The amount of time in milliseconds before a client is considered disconnected after not having a receiving
|
||||
<13> The amount of time in milliseconds before a client is considered disconnected after not having a receiving
|
||||
connection, i.e.
|
||||
an active connection over which the server can send data to the client.
|
||||
The default value is `5000`.
|
||||
|
||||
|
||||
<13> The number of server-to-client messages that a session can cache while waiting for the next HTTP polling request
|
||||
<14> The number of server-to-client messages that a session can cache while waiting for the next HTTP polling request
|
||||
from the client.
|
||||
The default size is `100`.
|
||||
|
||||
|
||||
<14> Some load balancers don't support websockets.
|
||||
<15> Some load balancers don't support websockets.
|
||||
Set this option to `false` to disable the WebSocket transport on the server side.
|
||||
The default value is `true`.
|
||||
|
||||
|
||||
<15> The `TaskScheduler` bean reference; a new `ThreadPoolTaskScheduler` instance will be created if no value is
|
||||
<16> The `TaskScheduler` bean reference; a new `ThreadPoolTaskScheduler` instance will be created if no value is
|
||||
provided.
|
||||
This scheduler instance will be used for scheduling heart-beat messages.
|
||||
|
||||
|
||||
<16> The `SockJsMessageCodec` bean reference to use for encoding and decoding SockJS messages.
|
||||
<17> The `SockJsMessageCodec` bean reference to use for encoding and decoding SockJS messages.
|
||||
By default `Jackson2SockJsMessageCodec` is used requiring the Jackson library to be present on the classpath.
|
||||
|
||||
|
||||
<17> List of `TransportHandler` bean references.
|
||||
<18> List of `TransportHandler` bean references.
|
||||
|
||||
|
||||
<19> The option to disable automatic addition of CORS headers for SockJS requests.
|
||||
The default value is `false`.
|
||||
|
||||
*<int-websocket:outbound-channel-adapter>*
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<int-websocket:outbound-channel-adapter
|
||||
id="" <1>
|
||||
channel="" <2>
|
||||
container="" <3>
|
||||
default-protocol-handler="" <4>
|
||||
protocol-handlers="" <5>
|
||||
message-converters="" <6>
|
||||
merge-with-default-converters="" <7>
|
||||
auto-startup="" <8>
|
||||
phase=""/> <9>
|
||||
id="" <1>
|
||||
channel="" <2>
|
||||
container="" <3>
|
||||
default-protocol-handler="" <4>
|
||||
protocol-handlers="" <5>
|
||||
message-converters="" <6>
|
||||
merge-with-default-converters="" <7>
|
||||
auto-startup="" <8>
|
||||
phase=""/> <9>
|
||||
----
|
||||
|
||||
|
||||
@@ -357,19 +371,19 @@ See `SmartLifeCycle`.
|
||||
[source,xml]
|
||||
----
|
||||
<int-websocket:inbound-channel-adapter
|
||||
id="" <1>
|
||||
channel="" <2>
|
||||
error-channel="" <3>
|
||||
container="" <4>
|
||||
default-protocol-handler="" <5>
|
||||
protocol-handlers="" <6>
|
||||
message-converters="" <7>
|
||||
merge-with-default-converters="" <8>
|
||||
send-timeout="" <9>
|
||||
payload-type="" <10>
|
||||
use-broker="" <11>
|
||||
auto-startup="" <12>
|
||||
phase=""/> <13>
|
||||
id="" <1>
|
||||
channel="" <2>
|
||||
error-channel="" <3>
|
||||
container="" <4>
|
||||
default-protocol-handler="" <5>
|
||||
protocol-handlers="" <6>
|
||||
message-converters="" <7>
|
||||
merge-with-default-converters="" <8>
|
||||
send-timeout="" <9>
|
||||
payload-type="" <10>
|
||||
use-broker="" <11>
|
||||
auto-startup="" <12>
|
||||
phase=""/> <13>
|
||||
----
|
||||
|
||||
|
||||
|
||||
@@ -270,3 +270,8 @@ See <<channel-wiretap>> for more information.
|
||||
|
||||
The `ChannelMessageStoreQueryProvider` now supports H2 database.
|
||||
See <<jdbc-message-store-channels>> for more information.
|
||||
|
||||
==== WebSocket Changes
|
||||
|
||||
The `ServerWebSocketContainer` now exposes `allowedOrigins` option and `SockJsServiceOptions` a `suppressCors` option.
|
||||
See <<web-sockets>> for more information.
|
||||
|
||||
Reference in New Issue
Block a user