Add EndpointRequestUpgradeStrategy
Now there is just one EndpointHandshakeRequestHandler that works on different runtimes.
This commit is contained in:
parent
741927664c
commit
30ab5953f9
|
@ -33,12 +33,14 @@ import org.springframework.util.Assert;
|
||||||
* Java WebSocket runtime and also configures the underlying
|
* Java WebSocket runtime and also configures the underlying
|
||||||
* {@link javax.websocket.server.ServerContainer}.
|
* {@link javax.websocket.server.ServerContainer}.
|
||||||
*
|
*
|
||||||
|
* <p>If the runtime is a Servlet container, use {@link ServletEndpointExporter}.
|
||||||
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class ServerEndpointExporter implements BeanPostProcessor, InitializingBean {
|
public class EndpointExporter implements BeanPostProcessor, InitializingBean {
|
||||||
|
|
||||||
private static Log logger = LogFactory.getLog(ServerEndpointExporter.class);
|
private static Log logger = LogFactory.getLog(EndpointExporter.class);
|
||||||
|
|
||||||
private Long maxSessionIdleTimeout;
|
private Long maxSessionIdleTimeout;
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.websocket.server.endpoint;
|
||||||
|
|
||||||
|
import javax.websocket.Endpoint;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.websocket.WebSocketHandler;
|
||||||
|
import org.springframework.websocket.endpoint.StandardWebSocketHandlerAdapter;
|
||||||
|
import org.springframework.websocket.server.AbstractHandshakeRequestHandler;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class EndpointHandshakeRequestHandler extends AbstractHandshakeRequestHandler {
|
||||||
|
|
||||||
|
private static final boolean tomcatWebSocketPresent = ClassUtils.isPresent(
|
||||||
|
"org.apache.tomcat.websocket.server.WsHandshakeRequest", EndpointHandshakeRequestHandler.class.getClassLoader());
|
||||||
|
|
||||||
|
private final EndpointRegistration endpointRegistration;
|
||||||
|
|
||||||
|
private final EndpointRequestUpgradeStrategy upgradeStrategy;
|
||||||
|
|
||||||
|
|
||||||
|
public EndpointHandshakeRequestHandler(WebSocketHandler webSocketHandler) {
|
||||||
|
this(new StandardWebSocketHandlerAdapter(webSocketHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
public EndpointHandshakeRequestHandler(Endpoint endpoint) {
|
||||||
|
this.endpointRegistration = new EndpointRegistration("/dummy", endpoint);
|
||||||
|
this.upgradeStrategy = createRequestUpgradeStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EndpointRequestUpgradeStrategy createRequestUpgradeStrategy() {
|
||||||
|
String className;
|
||||||
|
if (tomcatWebSocketPresent) {
|
||||||
|
className = "org.springframework.websocket.server.endpoint.TomcatRequestUpgradeStrategy";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalStateException("No suitable EndpointRequestUpgradeStrategy");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Class<?> clazz = ClassUtils.forName(className, EndpointHandshakeRequestHandler.class.getClassLoader());
|
||||||
|
return (EndpointRequestUpgradeStrategy) BeanUtils.instantiateClass(clazz.getConstructor());
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
throw new IllegalStateException("Failed to instantiate " + className, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EndpointRegistration getEndpointRegistration() {
|
||||||
|
return this.endpointRegistration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doHandshakeInternal(ServerHttpRequest request, ServerHttpResponse response, String protocol)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
logger.debug("Upgrading HTTP request");
|
||||||
|
this.upgradeStrategy.upgrade(request, response, protocol, this.endpointRegistration);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -46,13 +46,13 @@ import org.springframework.websocket.endpoint.StandardWebSocketHandlerAdapter;
|
||||||
* which case it will be adapted via {@link StandardWebSocketHandlerAdapter}.
|
* which case it will be adapted via {@link StandardWebSocketHandlerAdapter}.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Beans of this type are detected by {@link ServerEndpointExporter} and
|
* Beans of this type are detected by {@link EndpointExporter} and
|
||||||
* registered with a Java WebSocket runtime at startup.
|
* registered with a Java WebSocket runtime at startup.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class ServerEndpointRegistration implements ServerEndpointConfig, BeanFactoryAware {
|
public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAware {
|
||||||
|
|
||||||
private final String path;
|
private final String path;
|
||||||
|
|
||||||
|
@ -69,14 +69,14 @@ public class ServerEndpointRegistration implements ServerEndpointConfig, BeanFac
|
||||||
private final Configurator configurator = new Configurator() {};
|
private final Configurator configurator = new Configurator() {};
|
||||||
|
|
||||||
|
|
||||||
public ServerEndpointRegistration(String path, String beanName) {
|
public EndpointRegistration(String path, String beanName) {
|
||||||
Assert.hasText(path, "path must not be empty");
|
Assert.hasText(path, "path must not be empty");
|
||||||
Assert.notNull(beanName, "beanName is required");
|
Assert.notNull(beanName, "beanName is required");
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.bean = beanName;
|
this.bean = beanName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerEndpointRegistration(String path, Object bean) {
|
public EndpointRegistration(String path, Object bean) {
|
||||||
Assert.hasText(path, "path must not be empty");
|
Assert.hasText(path, "path must not be empty");
|
||||||
Assert.notNull(bean, "bean is required");
|
Assert.notNull(bean, "bean is required");
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
@ -104,7 +104,7 @@ public class ServerEndpointRegistration implements ServerEndpointConfig, BeanFac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Endpoint getEndpoint() {
|
public Endpoint getEndpoint() {
|
||||||
Object bean = this.bean;
|
Object bean = this.bean;
|
||||||
if (this.bean instanceof String) {
|
if (this.bean instanceof String) {
|
||||||
bean = this.beanFactory.getBean((String) this.bean);
|
bean = this.beanFactory.getBean((String) this.bean);
|
||||||
|
@ -166,23 +166,23 @@ public class ServerEndpointRegistration implements ServerEndpointConfig, BeanFac
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
|
public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
|
||||||
return (T) ServerEndpointRegistration.this.getEndpoint();
|
return (T) EndpointRegistration.this.getEndpoint();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
|
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
|
||||||
ServerEndpointRegistration.this.modifyHandshake(request, response);
|
EndpointRegistration.this.modifyHandshake(request, response);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean checkOrigin(String originHeaderValue) {
|
public boolean checkOrigin(String originHeaderValue) {
|
||||||
return ServerEndpointRegistration.this.checkOrigin(originHeaderValue);
|
return EndpointRegistration.this.checkOrigin(originHeaderValue);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String getNegotiatedSubprotocol(List<String> supported, List<String> requested) {
|
public String getNegotiatedSubprotocol(List<String> supported, List<String> requested) {
|
||||||
return ServerEndpointRegistration.this.selectSubProtocol(requested);
|
return EndpointRegistration.this.selectSubProtocol(requested);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested) {
|
public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested) {
|
||||||
return ServerEndpointRegistration.this.selectExtensions(requested);
|
return EndpointRegistration.this.selectExtensions(requested);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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.websocket.server.endpoint;
|
||||||
|
|
||||||
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A strategy for performing the actual request upgrade after the handshake checks have
|
||||||
|
* passed, encapsulating runtime-specific steps of the handshake.
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public interface EndpointRequestUpgradeStrategy {
|
||||||
|
|
||||||
|
void upgrade(ServerHttpRequest request, ServerHttpResponse response, String protocol,
|
||||||
|
EndpointRegistration registration) throws Exception;
|
||||||
|
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ import org.springframework.web.context.ServletContextAware;
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class ServletServerEndpointExporter extends ServerEndpointExporter implements ServletContextAware {
|
public class ServletEndpointExporter extends EndpointExporter implements ServletContextAware {
|
||||||
|
|
||||||
private ServletContext servletContext;
|
private ServletContext servletContext;
|
||||||
|
|
||||||
|
@ -43,7 +43,8 @@ public class ServletServerEndpointExporter extends ServerEndpointExporter implem
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
// TODO: remove hard dependency on Tomcat (see Tomcat's WsListener)
|
|
||||||
|
// TODO: this is needed (see WsListener) but remove hard dependency
|
||||||
WsServerContainer sc = WsServerContainer.getServerContainer();
|
WsServerContainer sc = WsServerContainer.getServerContainer();
|
||||||
sc.setServletContext(this.servletContext);
|
sc.setServletContext(this.servletContext);
|
||||||
|
|
|
@ -1,79 +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.websocket.server.endpoint;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.websocket.Endpoint;
|
|
||||||
import javax.websocket.server.ServerEndpointConfig;
|
|
||||||
|
|
||||||
import org.apache.tomcat.websocket.server.WsHandshakeRequest;
|
|
||||||
import org.apache.tomcat.websocket.server.WsHttpUpgradeHandler;
|
|
||||||
import org.apache.tomcat.websocket.server.WsServerContainer;
|
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
|
||||||
import org.springframework.http.server.ServletServerHttpRequest;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
import org.springframework.websocket.WebSocketHandler;
|
|
||||||
import org.springframework.websocket.endpoint.StandardWebSocketHandlerAdapter;
|
|
||||||
import org.springframework.websocket.server.AbstractHandshakeRequestHandler;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Rossen Stoyanchev
|
|
||||||
* @since 4.0
|
|
||||||
*/
|
|
||||||
public class TomcatHandshakeRequestHandler extends AbstractHandshakeRequestHandler {
|
|
||||||
|
|
||||||
private final Endpoint endpoint;
|
|
||||||
|
|
||||||
private final ServerEndpointConfig endpointConfig;
|
|
||||||
|
|
||||||
|
|
||||||
public TomcatHandshakeRequestHandler(WebSocketHandler webSocketHandler) {
|
|
||||||
this(new StandardWebSocketHandlerAdapter(webSocketHandler));
|
|
||||||
}
|
|
||||||
|
|
||||||
public TomcatHandshakeRequestHandler(Endpoint endpoint) {
|
|
||||||
this.endpoint = endpoint;
|
|
||||||
this.endpointConfig = new ServerEndpointRegistration("/dummy", this.endpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doHandshakeInternal(ServerHttpRequest request, ServerHttpResponse response, String protocol) throws Exception {
|
|
||||||
|
|
||||||
logger.debug("Upgrading HTTP request");
|
|
||||||
|
|
||||||
Assert.isTrue(request instanceof ServletServerHttpRequest);
|
|
||||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
|
||||||
|
|
||||||
WsHandshakeRequest wsRequest = new WsHandshakeRequest(servletRequest);
|
|
||||||
Method method = ReflectionUtils.findMethod(WsHandshakeRequest.class, "finished");
|
|
||||||
ReflectionUtils.makeAccessible(method);
|
|
||||||
method.invoke(wsRequest);
|
|
||||||
|
|
||||||
WsHttpUpgradeHandler wsHandler = servletRequest.upgrade(WsHttpUpgradeHandler.class);
|
|
||||||
|
|
||||||
wsHandler.preInit(this.endpoint, this.endpointConfig, WsServerContainer.getServerContainer(),
|
|
||||||
wsRequest, protocol, Collections.<String, String> emptyMap(), servletRequest.isSecure());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* 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.websocket.server.endpoint;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.tomcat.websocket.server.WsHandshakeRequest;
|
||||||
|
import org.apache.tomcat.websocket.server.WsHttpUpgradeHandler;
|
||||||
|
import org.apache.tomcat.websocket.server.WsServerContainer;
|
||||||
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
|
import org.springframework.http.server.ServletServerHttpRequest;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class TomcatRequestUpgradeStrategy implements EndpointRequestUpgradeStrategy {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void upgrade(ServerHttpRequest request, ServerHttpResponse response, String protocol,
|
||||||
|
EndpointRegistration registration) throws Exception {
|
||||||
|
|
||||||
|
Assert.isTrue(request instanceof ServletServerHttpRequest);
|
||||||
|
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||||
|
|
||||||
|
WsHttpUpgradeHandler wsHandler = servletRequest.upgrade(WsHttpUpgradeHandler.class);
|
||||||
|
|
||||||
|
WsHandshakeRequest wsRequest = new WsHandshakeRequest(servletRequest);
|
||||||
|
Method method = ReflectionUtils.findMethod(WsHandshakeRequest.class, "finished");
|
||||||
|
ReflectionUtils.makeAccessible(method);
|
||||||
|
method.invoke(wsRequest);
|
||||||
|
|
||||||
|
wsHandler.preInit(registration.getEndpoint(), registration,
|
||||||
|
WsServerContainer.getServerContainer(), wsRequest, protocol,
|
||||||
|
Collections.<String, String> emptyMap(), servletRequest.isSecure());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Server-specific support for working with standard Java WebSocket Endpoint's.
|
* Server-specific support for configuring and adapting standard Java WebSocket endpoint's.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package org.springframework.websocket.server.endpoint;
|
package org.springframework.websocket.server.endpoint;
|
||||||
|
|
Loading…
Reference in New Issue