001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.socket.server.standard; 018 019import java.io.IOException; 020import java.util.Collections; 021import java.util.List; 022import java.util.Map; 023import javax.servlet.ServletException; 024import javax.servlet.http.HttpServletRequest; 025import javax.servlet.http.HttpServletResponse; 026import javax.websocket.Endpoint; 027import javax.websocket.Extension; 028 029import org.apache.tomcat.websocket.server.WsServerContainer; 030 031import org.springframework.http.server.ServerHttpRequest; 032import org.springframework.http.server.ServerHttpResponse; 033import org.springframework.web.socket.server.HandshakeFailureException; 034 035/** 036 * A WebSocket {@code RequestUpgradeStrategy} for Apache Tomcat. Compatible with 037 * all versions of Tomcat that support JSR-356, i.e. Tomcat 7.0.47+ and higher. 038 * 039 * <p>To modify properties of the underlying {@link javax.websocket.server.ServerContainer} 040 * you can use {@link ServletServerContainerFactoryBean} in XML configuration or, 041 * when using Java configuration, access the container instance through the 042 * "javax.websocket.server.ServerContainer" ServletContext attribute. 043 * 044 * @author Rossen Stoyanchev 045 * @since 4.0 046 */ 047public class TomcatRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy { 048 049 @Override 050 public String[] getSupportedVersions() { 051 return new String[] {"13"}; 052 } 053 054 @Override 055 public void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response, 056 String selectedProtocol, List<Extension> selectedExtensions, Endpoint endpoint) 057 throws HandshakeFailureException { 058 059 HttpServletRequest servletRequest = getHttpServletRequest(request); 060 HttpServletResponse servletResponse = getHttpServletResponse(response); 061 062 StringBuffer requestUrl = servletRequest.getRequestURL(); 063 String path = servletRequest.getRequestURI(); // shouldn't matter 064 Map<String, String> pathParams = Collections.<String, String> emptyMap(); 065 066 ServerEndpointRegistration endpointConfig = new ServerEndpointRegistration(path, endpoint); 067 endpointConfig.setSubprotocols(Collections.singletonList(selectedProtocol)); 068 endpointConfig.setExtensions(selectedExtensions); 069 070 try { 071 getContainer(servletRequest).doUpgrade(servletRequest, servletResponse, endpointConfig, pathParams); 072 } 073 catch (ServletException ex) { 074 throw new HandshakeFailureException( 075 "Servlet request failed to upgrade to WebSocket: " + requestUrl, ex); 076 } 077 catch (IOException ex) { 078 throw new HandshakeFailureException( 079 "Response update failed during upgrade to WebSocket: " + requestUrl, ex); 080 } 081 } 082 083 @Override 084 public WsServerContainer getContainer(HttpServletRequest request) { 085 return (WsServerContainer) super.getContainer(request); 086 } 087 088}