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

时间:2013-10-25 20:15:03

标签: java http servlets http-headers httprequest

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

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

我尝试使用:

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

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

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

8 个答案:

答案 0 :(得分:40)

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

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

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

编辑:如果您的servlet容器位于终止SSL的反向代理或负载均衡器后面,那就有点棘手,因为请求会以纯http的形式转发到servlet容器。您有几个选择:

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

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

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

答案 1 :(得分:17)

您可以使用HttpServletRequest.getRequestURLHttpServletRequest.getRequestURI

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

答案 2 :(得分:3)

如果您想要原始网址,请使用jthalborn所述的方法。 如果你想重建网址就像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, ...);
}

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

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

大多数开发人员无论如何都会知道端口80和443,因此常量没有用。

另请参见此类post

答案 3 :(得分:3)

如果您使用负载平衡器& 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引擎:

<Valve className="org.apache.catalina.valves.RemoteIpValve"  
remoteIpHeader="X-Forwarded-For"  
protocolHeader="X-Forwarded-Proto"  
protocolHeaderHttpsValue="https"/> 

如果只修改Nginx配置文件,则java代码应为:

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

似乎您需要从URL中剥离URL,因此可以通过以下方式进行操作:

request.getRequestURL().toString().replace(request.getRequestURI(), "")

答案 6 :(得分:0)

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

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();
}

答案 7 :(得分:0)

我参加聚会很晚,但是在使用Java 8时遇到了同样的问题。

这是对HttpServletRequest request对象有用的东西。

request.getHeader("origin");

request.getHeader("referer");

我如何得出这个结论:

我有一个在 http://localhost:3000 上运行的Java应用程序,向我在 http://localhost:8080 上运行的另一个Java应用程序发出Http Post。

从运行在 http://localhost:8080 的Java代码中,我无法使用 HttpServletRequest http://localhost:3000 上面的答案。对我来说,使用getHeader方法和正确的字符串输入有效。

request.getHeader("origin")给了我http://localhost:3000

request.getHeader("referer")给了我http://localhost:3000/xxxx,其中xxxx是我来自请求应用程序的完整URL。