Tomcat: getHeader("Host") против getServerName()

У меня есть приложение Tomcat, которое обслуживается из нескольких доменов. Предыдущие разработчики создали метод для возврата URL приложения (см. Ниже). В методе они запрашивают имя сервера (request.getServerName()) который, соответственно, возвращает имя_сервера из файла httpd.conf.

Однако я этого не хочу. Мне нужно имя хоста, к которому браузер отправил запрос, т. Е. С какого домена браузер обращается к приложению.

Я старался getHeader("Host"), но это все еще возвращает имя ServerName, установленное в файле httpd.conf.

Вместо request.getServerName(), что я должен использовать, чтобы получить имя сервера, на который браузер отправил запрос?

Например:

  • Имя сервера в httpd.conf: www.myserver.net
  • Пользователь получает доступ к приложению Tomcat на www.yourserver.net

Мне нужно вернуть www.yourserver.net НЕ www.myserver.net. request.getServerName() звоните только кажется, чтобы вернуться www.myserver.net

/**
 * Convenience method to get the application's URL based on request
 * variables.
 * 
 * @param request the current request
 * @return URL to application
 */
public static String getAppURL(HttpServletRequest request) {
    StringBuffer url = new StringBuffer();
    int port = request.getServerPort();
    if (port < 0) {
        port = 80; // Work around java.net.URL bug
    }
    String scheme = request.getScheme();
    url.append(scheme);
    url.append("://");
    url.append(request.getServerName());
    if (("http".equals(scheme) && (port != 80)) || ("https".equals(scheme) && (port != 443))) {
        url.append(':');
        url.append(port);
    }
    url.append(request.getContextPath());
    return url.toString();
}

Заранее спасибо!

4 ответа

Решение

Вы должны убедиться, что httpd проходит Host заголовок, предоставленный клиентом Tomcat. Самый простой способ (если вы используете mod_proxy_http - Вы не сказали) это со следующим:

ProxyPreserveHost On

Как насчет использования чего-то, как я сделал в этом демонстрационном JSP?

<%
  String requestURL = request.getRequestURL().toString();
  String servletPath = request.getServletPath();
  String appURL = requestURL.substring(0, requestURL.indexOf(servletPath));
%>
appURL is <%=appURL%>

Может быть, не связано с этим вопросом. Если вы используете tomcat, вы можете указать любую строку Host в заголовке запроса, даже такую ​​как javascript <script>alert(document.cookie);</script>

Тогда это может быть показано на странице.

<p> host name is : <%= request.getServerName() %> </p>

Таким образом, вы должны проверить это перед использованием.

Это действительно очень проблематично, потому что иногда вы даже не знаете, где был удален хост, который, как вы ожидаете, будет полностью квалифицированным доменом. @rickz предоставил отличное решение, но вот еще одно, которое я считаю более полным и охватывает множество разных URL:

Обычно вы удаляете протокол (http://, https://, ftp://,...), затем порт (если он существует) и весь URI. Это дает вам полный список доменов верхнего уровня и поддоменов.

String requestURL = request.getRequestURL().toString();
String withoutProtocol = requestURL.replaceAll("(.*\\/{2})", "")
String withoutPort = withoutProtocol.replaceAll("(:\\d*)", "") 
String domain = withoutPort.replaceAll("(\\/.*)", "")

Я сделал это в Scala, используя определения встроенного метода, но приведенный выше код более подробный, потому что я нашел, что лучше опубликовать решение в чистом Java. Поэтому, если вы создадите методы для этого, вы можете связать их в цепочку, чтобы сделать что-то вроде этого

removeURI(removePort(removeProtocol(requestURL)))
Другие вопросы по тегам