001/* 002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id$ 018 */ 019 020package org.nuxeo.ecm.platform.web.common.vh; 021 022import javax.servlet.ServletRequest; 023import javax.servlet.http.HttpServletRequest; 024 025import org.apache.commons.lang.StringUtils; 026import org.apache.commons.logging.Log; 027import org.apache.commons.logging.LogFactory; 028import org.nuxeo.runtime.api.Framework; 029 030public class VirtualHostHelper { 031 032 private static final int HTTP_PORT_NUMBER = 80; 033 034 private static final int HTTPS_PORT_NUMBER = 443; 035 036 private static final Log log = LogFactory.getLog(VirtualHostHelper.class); 037 038 private static final String X_FORWARDED_HOST = "x-forwarded-host"; 039 040 private static final String X_FORWARDED_PROTO = "x-forwarded-proto"; 041 042 private static final String X_FORWARDED_PORT = "x-forwarded-port"; 043 044 private static final String VH_HEADER = "nuxeo-virtual-host"; 045 046 private static final String VH_PARAM = "nuxeo.virtual.host"; 047 048 // Utility class. 049 private VirtualHostHelper() { 050 } 051 052 private static HttpServletRequest getHttpServletRequest(ServletRequest request) { 053 if (request instanceof HttpServletRequest) { 054 return (HttpServletRequest) request; 055 } 056 return null; 057 } 058 059 /** 060 * @return WebApp name : ie : nuxeo 061 */ 062 public static String getWebAppName(ServletRequest request) { 063 return getContextPath(request).replace("/", ""); 064 } 065 066 /** 067 * @return Server URL as : protocol://serverName:port/ 068 */ 069 public static String getServerURL(ServletRequest request) { 070 return getServerURL(request, false); 071 } 072 073 private static String getServerUrl(String scheme, String serverName, int serverPort) { 074 StringBuilder sbaseURL = new StringBuilder(); 075 sbaseURL.append(scheme); 076 sbaseURL.append("://"); 077 sbaseURL.append(serverName); 078 if (serverPort != 0) { 079 if ("http".equals(scheme) && serverPort != HTTP_PORT_NUMBER || "https".equals(scheme) 080 && serverPort != HTTPS_PORT_NUMBER) { 081 sbaseURL.append(':'); 082 sbaseURL.append(serverPort); 083 } 084 } 085 sbaseURL.append('/'); 086 return sbaseURL.toString(); 087 } 088 089 /** 090 * @return Server URL as : protocol://serverName:port/ 091 */ 092 public static String getServerURL(ServletRequest request, boolean local) { 093 String baseURL = null; 094 HttpServletRequest httpRequest = getHttpServletRequest(request); 095 if (httpRequest != null) { 096 // Detect Nuxeo specific header for VH 097 String nuxeoVH = httpRequest.getHeader(VH_HEADER); 098 if (nuxeoVH == null) { 099 nuxeoVH = Framework.getProperty(VH_PARAM); 100 } 101 if (!local && nuxeoVH != null && nuxeoVH.contains("http")) { 102 baseURL = nuxeoVH; 103 } else { 104 // default values 105 String serverName = httpRequest.getServerName(); 106 int serverPort = httpRequest.getServerPort(); 107 String scheme = httpRequest.getScheme(); 108 109 if (!local) { 110 String forwardedPort = httpRequest.getHeader(X_FORWARDED_PORT); 111 112 if (forwardedPort != null) { 113 try { 114 serverPort = Integer.parseInt(forwardedPort); 115 } catch (NumberFormatException e) { 116 log.error("Unable to get forwarded port from header", e); 117 } 118 } 119 120 String forwardedProto = httpRequest.getHeader(X_FORWARDED_PROTO); 121 if (forwardedProto != null) { 122 scheme = forwardedProto; 123 } 124 125 // Detect virtual hosting based in standard header 126 String forwardedHost = httpRequest.getHeader(X_FORWARDED_HOST); 127 if (forwardedHost != null) { 128 if (forwardedHost.contains(":")) { 129 serverName = forwardedHost.split(":")[0]; 130 serverPort = Integer.valueOf(forwardedHost.split(":")[1]); 131 } else { 132 serverName = forwardedHost; 133 serverPort = "https".equals(scheme) ? HTTPS_PORT_NUMBER : HTTP_PORT_NUMBER; 134 } 135 } 136 } 137 138 baseURL = getServerUrl(scheme, serverName, serverPort); 139 } 140 } 141 if (baseURL == null) { 142 log.error("Could not retrieve base url correctly"); 143 log.debug("Could not retrieve base url correctly", new Throwable()); 144 } 145 return baseURL; 146 } 147 148 /** 149 * @return base URL as protocol://serverName:port/webappName/ 150 */ 151 public static String getBaseURL(ServletRequest request) { 152 String baseURL = null; 153 String serverUrl = getServerURL(request, false); 154 if (serverUrl != null) { 155 String webAppName = getWebAppName(request); 156 157 baseURL = StringUtils.isNotBlank(webAppName) ? serverUrl + webAppName + '/' : serverUrl; 158 159 } 160 return baseURL; 161 } 162 163 /** 164 * Returns the context path of the application. Try to get it from the {@code ServletRequest} and then from the 165 * {@code org.nuxeo.ecm.contextPath} system property. Fallback on default context path {@code /nuxeo}. 166 */ 167 public static String getContextPath(ServletRequest request) { 168 HttpServletRequest httpRequest = getHttpServletRequest(request); 169 String contextPath = null; 170 if (httpRequest != null) { 171 contextPath = httpRequest.getContextPath(); 172 } 173 return contextPath != null ? contextPath : getContextPathProperty(); 174 } 175 176 public static String getContextPathProperty() { 177 return Framework.getProperty("org.nuxeo.ecm.contextPath", "/nuxeo"); 178 } 179 180}