Java Tomcat:getHeader(“主机”)与getServerName()

Java Tomcat:getHeader(“主机”)与getServerName(),java,tomcat,httprequest,Java,Tomcat,Httprequest,我有一个Tomcat应用程序,它是从多个域提供的。以前的开发人员构建了一个方法来返回应用程序URL(见下文)。在该方法中,他们请求服务器名(request.getServerName()),该服务器名从httpd.conf文件返回ServerName 然而,我不想这样。我想要的是浏览器将请求发送到的主机名,即浏览器从哪个域访问应用程序 我尝试了getHeader(“Host”),但仍然返回httpd.conf文件中设置的ServerName 我应该使用什么来获取浏览器向其发送请求的服务器名称,而

我有一个Tomcat应用程序,它是从多个域提供的。以前的开发人员构建了一个方法来返回应用程序URL(见下文)。在该方法中,他们请求服务器名(
request.getServerName()
),该服务器名从httpd.conf文件返回ServerName

然而,我不想这样。我想要的是浏览器将请求发送到的主机名,即浏览器从哪个域访问应用程序

我尝试了
getHeader(“Host”)
,但仍然返回httpd.conf文件中设置的ServerName

我应该使用什么来获取浏览器向其发送请求的服务器名称,而不是
request.getServerName()

例如:

  • httpd.conf中的服务器名:www.myserver.net
  • 用户访问www.yourserver.net上的Tomcat应用程序
我需要返回www.yourserver.net而不是www.myserver.net。
request.getServerName()
调用似乎只返回www.myserver.net

/**
*基于请求获取应用程序URL的便捷方法
*变量。
* 
*@param请求当前请求
*@返回应用程序的URL
*/
公共静态字符串getAppURL(HttpServletRequest请求){
StringBuffer url=新的StringBuffer();
int-port=request.getServerPort();
如果(端口<0){
port=80;//解决java.net.URL错误
}
字符串scheme=request.getScheme();
追加(方案);
url.append(“:/”);
append(request.getServerName());
if(((“http.equals(scheme)&&(port!=80))| |((“https.equals(scheme)&&(port!=443))){
append(“:”);
url.append(端口);
}
append(request.getContextPath());
返回url.toString();
}

提前谢谢

像我在这个演示JSP中做的那样使用怎么样

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

appURL是

您需要确保
httpd
将客户机提供的
Host
头传递给Tomcat。最简单的方法(假设您使用的是
mod\u proxy\u http
——您没有说)是以下方法:

ProxyPreserveHost On

这确实是一个很大的问题,因为有时您甚至不知道您希望成为完全限定域的主机已被删除@Rikz提供了一个很好的解决方案,但是这里有另外一个我认为是更完整的,涵盖了很多不同的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)))

可能与这个问题无关。 如果您使用的是tomcat,那么您可以在请求头中指定任何主机字符串,甚至像
alert(document.cookie)这样的javascript

然后它可以显示在页面上:

<p> host name is : <%= request.getServerName() %> </p>
主机名是:


因此,在使用它之前,您需要验证它。

Rick,这非常有效-尽管我最终使用了上面Mark的建议,因为它不需要更改代码。@rickz这样的单元测试是如何进行的?关键问题是如何为单元测试创建HttpServletRequest实例?Google search提出了一些建议来模拟这个类,但是如果你模拟它的方法,你就没有真正测试任何东西。我也遇到了httpunit库,但这也没什么帮助。我有同样的要求,要获得VirtualHost中提到的服务器名,如下所示。DocumentRoot/usr/local/apache/htdocs/EMPTY ServerName xxx.yyy.com RewriteEngine On#将所有请求重定向到本地apache服务器到端口8000 RewriteRule^/?(.)https://%{server_NAME}/$1[R,L]由于未使用mod_代理配置,因此“ProxyPreserveHost On”似乎未应用于此配置。请告诉我没有解决办法。您应该问一个新问题,Tomcat甚至看不到
httpd.conf
文件,更不用说从中返回值了。Tomcat从请求中获取服务器主机。
<p> host name is : <%= request.getServerName() %> </p>