如何从http或https请求获取带端口的主机名

我在jboss容器中部署了两个应用程序(相同的unix框)。 如果我从app1收到请求,我需要为app2构建相应的请求。

例如:
如果app1请求是: http : //example.com/context? param1 = 123
然后我需要提取“ http://example.com/ ”,以便我可以构建第二个应用程序的请求。

我试过用:

HttpServletRequest.getServerName() & HttpServletRequest.getServerPort() & \ HttpServletRequest.getHeader("host") 

方法,但请求可能是http或https。

如果还有其他更好的方法,请告诉我。 谢谢!

您可以使用HttpServletRequest.getScheme()来检索“http”或“https”。

将它与HttpServletRequest.getServerName()一起使用应足以重建所需URL的部分。

如果您使用的是标准端口(80为http,443为https),则无需在URL中明确放置端口。

编辑 :如果您的servlet容器位于终止SSL的反向代理或负载平衡器后面,则它有点棘手,因为请求将以纯http的forms转发到servlet容器。 你有几个选择:

1)使用HttpServletRequest.getHeader("x-forwarded-proto")代替; 这只适用于您的负载均衡器正确设置标头(Apache应该是afaik)。

2)在JBoss / Tomcat中配置RemoteIpValve ,使getScheme()按预期工作。 同样,这仅在负载均衡器设置正确的标头时才有效。

3)如果上述方法不起作用,您可以在Tomcat / JBoss中配置两个不同的连接器,一个用于http,另一个用于https,如本文所述 。

您可以使用HttpServletRequest.getRequestURL和HttpServletRequest.getRequestURI 。

 StringBuffer url = request.getRequestURL(); String uri = request.getRequestURI(); String host = url.substring(0, url.indexOf(uri)); //result 

如果您使用负载均衡器和Nginx,请在没有修改代码的情况下对其进行配置。

Nginx的:

 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; 

Tomcat的server.xml引擎:

  

如果只修改Nginx配置文件,那么java代码应该是:

 String XForwardedProto = request.getHeader("X-Forwarded-Proto"); 

如果您想要原始URL,请使用jthalborn描述的方法。 如果你想重建url就像David Levesque解释的那样,这里有一个代码片段:

 final javax.servlet.http.HttpServletRequest req = (javax.servlet.http.HttpServletRequest) ...; final int serverPort = req.getServerPort(); if ((serverPort == 80) || (serverPort == 443)) { // No need to add the server port for standard HTTP and HTTPS ports, the scheme will help determine it. url = String.format("%s://%s/...", req.getScheme(), req.getServerName(), ...); } else { url = String.format("%s://%s:%s...", req.getScheme(), req.getServerName(), serverPort, ...); } 

您仍需要考虑反向代理的情况:

  • request.getScheme()返回http而不是在java中返回https

可以为端口使用常量,但不确定是否有可靠的源,默认端口:

  • 是否在JDK中定义了HTTP和HTTPS默认端口号?

大多数开发人员无论如何都会知道端口80和443,所以常量不是那么有用。

另见这篇类似的post 。

请参阅http://docs.oracle.com/javase/tutorial/networking/urls/urlInfo.html 。 这是关于url解析的最简洁的报道。

如果您的服务器在代理服务器后面运行,请确保设置了代理标头:

 proxy_set_header X-Forwarded-Proto $scheme; 

然后,为了获得正确的scheme & url您可以使用springframework的类:

 public String getUrl(HttpServletRequest request) { HttpRequest httpRequest = new ServletServerHttpRequest(request); UriComponents uriComponents = UriComponentsBuilder.fromHttpRequest(httpRequest).build(); String scheme = uriComponents.getScheme(); // http / https String serverName = request.getServerName(); // hostname.com int serverPort = request.getServerPort(); // 80 String contextPath = request.getContextPath(); // /app // Reconstruct original requesting URL StringBuilder url = new StringBuilder(); url.append(scheme).append("://"); url.append(serverName); if (serverPort != 80 && serverPort != 443) { url.append(":").append(serverPort); } url.append(contextPath); return url.toString(); }