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; 023 024import javax.servlet.ServletException; 025import javax.servlet.http.HttpServletRequest; 026import javax.servlet.http.HttpServletResponse; 027import javax.websocket.Endpoint; 028import javax.websocket.Extension; 029 030import org.apache.tomcat.websocket.server.WsServerContainer; 031 032import org.springframework.http.server.ServerHttpRequest; 033import org.springframework.http.server.ServerHttpResponse; 034import org.springframework.lang.Nullable; 035import org.springframework.web.socket.server.HandshakeFailureException; 036 037/** 038 * A WebSocket {@code RequestUpgradeStrategy} for Apache Tomcat. Compatible with 039 * all versions of Tomcat that support JSR-356, i.e. Tomcat 7.0.47+ and higher. 040 * 041 * <p>To modify properties of the underlying {@link javax.websocket.server.ServerContainer} 042 * you can use {@link ServletServerContainerFactoryBean} in XML configuration or, 043 * when using Java configuration, access the container instance through the 044 * "javax.websocket.server.ServerContainer" ServletContext attribute. 045 * 046 * @author Rossen Stoyanchev 047 * @since 4.0 048 */ 049public class TomcatRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy { 050 051 @Override 052 public String[] getSupportedVersions() { 053 return new String[] {"13"}; 054 } 055 056 @Override 057 public void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response, 058 @Nullable String selectedProtocol, List<Extension> selectedExtensions, Endpoint endpoint) 059 throws HandshakeFailureException { 060 061 HttpServletRequest servletRequest = getHttpServletRequest(request); 062 HttpServletResponse servletResponse = getHttpServletResponse(response); 063 064 StringBuffer requestUrl = servletRequest.getRequestURL(); 065 String path = servletRequest.getRequestURI(); // shouldn't matter 066 Map<String, String> pathParams = Collections.<String, String> emptyMap(); 067 068 ServerEndpointRegistration endpointConfig = new ServerEndpointRegistration(path, endpoint); 069 endpointConfig.setSubprotocols(Collections.singletonList(selectedProtocol)); 070 endpointConfig.setExtensions(selectedExtensions); 071 072 try { 073 getContainer(servletRequest).doUpgrade(servletRequest, servletResponse, endpointConfig, pathParams); 074 } 075 catch (ServletException ex) { 076 throw new HandshakeFailureException( 077 "Servlet request failed to upgrade to WebSocket: " + requestUrl, ex); 078 } 079 catch (IOException ex) { 080 throw new HandshakeFailureException( 081 "Response update failed during upgrade to WebSocket: " + requestUrl, ex); 082 } 083 } 084 085 @Override 086 public WsServerContainer getContainer(HttpServletRequest request) { 087 return (WsServerContainer) super.getContainer(request); 088 } 089 090}