Tomcat: getHeader ( "Хост" ) и getServerName()

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

Однако я не хочу этого. То, что я хочу, - это имя хоста, которое браузер отправил на запрос, т.е. Какой бы домен, к которому браузер обращается к приложению.

Я попробовал getHeader("Host"), но это все еще возвращает Имя_сервера в файле 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 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();
}

Спасибо заранее!

Ответ 1

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

ProxyPreserveHost On

Ответ 2

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

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

Ответ 3

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

Затем он может быть показан на странице.:

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

Поэтому перед тем, как использовать его, вам нужно проверить.

Ответ 4

Это действительно очень проблематично, потому что иногда вы даже не знаете, где был удален хост, который вы ожидаете быть полностью квалифицированным. @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)))