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