001/* 002 * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others. 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 * http://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 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.ecm.platform.web.common.vh; 023 024import static org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants.REQUESTED_URL; 025 026import javax.servlet.ServletRequest; 027import javax.servlet.http.HttpServletRequest; 028 029import org.apache.commons.lang.StringUtils; 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter; 033import org.nuxeo.runtime.api.Framework; 034 035public class VirtualHostHelper { 036 037 private static final int HTTP_PORT_NUMBER = 80; 038 039 private static final int HTTPS_PORT_NUMBER = 443; 040 041 private static final Log log = LogFactory.getLog(VirtualHostHelper.class); 042 043 private static final String X_FORWARDED_HOST = "x-forwarded-host"; 044 045 private static final String X_FORWARDED_PROTO = "x-forwarded-proto"; 046 047 private static final String X_FORWARDED_PORT = "x-forwarded-port"; 048 049 private static final String VH_HEADER = "nuxeo-virtual-host"; 050 051 private static final String VH_PARAM = "nuxeo.virtual.host"; 052 053 // Utility class. 054 private VirtualHostHelper() { 055 } 056 057 private static HttpServletRequest getHttpServletRequest(ServletRequest request) { 058 if (request instanceof HttpServletRequest) { 059 return (HttpServletRequest) request; 060 } 061 return null; 062 } 063 064 /** 065 * @return WebApp name : ie : nuxeo 066 */ 067 public static String getWebAppName(ServletRequest request) { 068 return getContextPath(request).replace("/", ""); 069 } 070 071 /** 072 * @return Server URL as : protocol://serverName:port/ 073 */ 074 public static String getServerURL(ServletRequest request) { 075 return getServerURL(request, false); 076 } 077 078 private static String getServerUrl(String scheme, String serverName, int serverPort) { 079 StringBuilder sbaseURL = new StringBuilder(); 080 sbaseURL.append(scheme); 081 sbaseURL.append("://"); 082 sbaseURL.append(serverName); 083 if (serverPort != 0) { 084 if ("http".equals(scheme) && serverPort != HTTP_PORT_NUMBER || "https".equals(scheme) 085 && serverPort != HTTPS_PORT_NUMBER) { 086 sbaseURL.append(':'); 087 sbaseURL.append(serverPort); 088 } 089 } 090 sbaseURL.append('/'); 091 return sbaseURL.toString(); 092 } 093 094 /** 095 * @return Server URL as : protocol://serverName:port/ 096 */ 097 public static String getServerURL(ServletRequest request, boolean local) { 098 String baseURL = null; 099 HttpServletRequest httpRequest = getHttpServletRequest(request); 100 if (httpRequest != null) { 101 // Detect Nuxeo specific header for VH 102 String nuxeoVH = httpRequest.getHeader(VH_HEADER); 103 if (nuxeoVH == null) { 104 nuxeoVH = Framework.getProperty(VH_PARAM); 105 } 106 if (!local && nuxeoVH != null && nuxeoVH.contains("http")) { 107 baseURL = nuxeoVH; 108 } else { 109 // default values 110 String serverName = httpRequest.getServerName(); 111 int serverPort = httpRequest.getServerPort(); 112 String scheme = httpRequest.getScheme(); 113 114 if (!local) { 115 String forwardedPort = httpRequest.getHeader(X_FORWARDED_PORT); 116 117 if (forwardedPort != null) { 118 try { 119 serverPort = Integer.parseInt(forwardedPort); 120 } catch (NumberFormatException e) { 121 log.error("Unable to get forwarded port from header", e); 122 } 123 } 124 125 String forwardedProto = httpRequest.getHeader(X_FORWARDED_PROTO); 126 if (forwardedProto != null) { 127 scheme = forwardedProto; 128 } 129 130 // Detect virtual hosting based in standard header 131 String forwardedHost = httpRequest.getHeader(X_FORWARDED_HOST); 132 if (forwardedHost != null) { 133 if (forwardedHost.contains(":")) { 134 serverName = forwardedHost.split(":")[0]; 135 serverPort = Integer.valueOf(forwardedHost.split(":")[1]); 136 } else { 137 serverName = forwardedHost; 138 serverPort = "https".equals(scheme) ? HTTPS_PORT_NUMBER : HTTP_PORT_NUMBER; 139 } 140 } 141 } 142 143 baseURL = getServerUrl(scheme, serverName, serverPort); 144 } 145 } 146 if (baseURL == null) { 147 log.error("Could not retrieve base url correctly"); 148 log.debug("Could not retrieve base url correctly", new Throwable()); 149 } 150 return baseURL; 151 } 152 153 /** 154 * @return base URL as protocol://serverName:port/webappName/ 155 */ 156 public static String getBaseURL(ServletRequest request) { 157 String baseURL = null; 158 String serverUrl = getServerURL(request, false); 159 if (serverUrl != null) { 160 String webAppName = getWebAppName(request); 161 162 baseURL = StringUtils.isNotBlank(webAppName) ? serverUrl + webAppName + '/' : serverUrl; 163 164 } 165 return baseURL; 166 } 167 168 /** 169 * Returns the context path of the application. Try to get it from the {@code ServletRequest} and then from the 170 * {@code org.nuxeo.ecm.contextPath} system property. Fallback on default context path {@code /nuxeo}. 171 */ 172 public static String getContextPath(ServletRequest request) { 173 HttpServletRequest httpRequest = getHttpServletRequest(request); 174 String contextPath = null; 175 if (httpRequest != null) { 176 contextPath = httpRequest.getContextPath(); 177 } 178 return contextPath != null ? contextPath : getContextPathProperty(); 179 } 180 181 public static String getContextPathProperty() { 182 return Framework.getProperty("org.nuxeo.ecm.contextPath", "/nuxeo"); 183 } 184 185 /** 186 * Computes the url to be redirected when logging out 187 * 188 * @return redirect URL as protocol://serverName:port/webappName/... 189 * @since 9.1 190 */ 191 public static String getRedirectUrl(HttpServletRequest request) { 192 String redirectURL = getBaseURL(request); 193 if (request.getAttribute(REQUESTED_URL) != null) { 194 redirectURL += request.getAttribute(REQUESTED_URL); 195 } else if (request.getParameter(REQUESTED_URL) != null) { 196 redirectURL += request.getParameter(REQUESTED_URL); 197 } else if (NuxeoAuthenticationFilter.getRequestedUrl(request) != null) { 198 redirectURL += NuxeoAuthenticationFilter.getRequestedUrl(request); 199 } else { 200 redirectURL = request.getRequestURL().toString(); 201 String queryString = request.getQueryString(); 202 if (queryString != null) { 203 redirectURL += '?' + queryString; 204 } 205 } 206 return redirectURL; 207 } 208 209}