简体   繁体   English

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

[英]How to get host name with port from a http or https request

I have two applications deployed in a JBoss container (same unix box).我在 JBoss 容器(同一个 unix box)中部署了两个应用程序。 If I receive a request from app1, I need to send a corresponding request for app2.如果我收到来自app1的请求,我需要向app2发送相应的请求。

An Example: If app1 requests: http://example.com/context?param1=123 , then I need to extract http://example.com/ , so that I can send the request for the second app.一个例子:如果 app1 请求: http://example.com/context?param1=123 ,那么我需要提取http://example.com/ ,以便我可以发送第二个应用程序的请求。

I tried using我尝试使用

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

but how can I destinguish between http or https ?但是我如何在httphttps之间进行区分?

You can use HttpServletRequest.getScheme() to retrieve either "http" or "https".您可以使用HttpServletRequest.getScheme()来检索“http”或“https”。

Using it along with HttpServletRequest.getServerName() should be enough to rebuild the portion of the URL you need.将它与HttpServletRequest.getServerName()一起使用应该足以重建您需要的 URL 部分。

You don't need to explicitly put the port in the URL if you're using the standard ones (80 for http and 443 for https).如果您使用标准端口(http 为 80,https 为 443),则不需要明确地将端口放入 URL。

Edit : If your servlet container is behind a reverse proxy or load balancer that terminates the SSL, it's a bit trickier because the requests are forwarded to the servlet container as plain http.编辑:如果您的 servlet 容器位于终止 SSL 的反向代理或负载平衡器之后,则有点棘手,因为请求将作为普通 http 转发到 servlet 容器。 You have a few options:您有几个选择:

1) Use HttpServletRequest.getHeader("x-forwarded-proto") instead; 1) 使用HttpServletRequest.getHeader("x-forwarded-proto")代替; this only works if your load balancer sets the header correctly (Apache should afaik).这仅在您的负载均衡器正确设置标头时才有效(Apache 应该是错误的)。

2) Configure a RemoteIpValve in JBoss/Tomcat that will make getScheme() work as expected. 2) 在 JBoss/Tomcat 中配置一个RemoteIpValve ,这将使getScheme()按预期工作。 Again, this will only work if the load balancer sets the correct headers.同样,这仅在负载均衡器设置正确的标头时才有效。

3) If the above don't work, you could configure two different connectors in Tomcat/JBoss, one for http and one for https, as described in this article . 3) 如果以上方法都不起作用,您可以在 Tomcat/JBoss 中配置两种不同的连接器,一种用于 http,一种用于 https,如本文所述

You can use HttpServletRequest.getRequestURL and HttpServletRequest.getRequestURI .您可以使用HttpServletRequest.getRequestURLHttpServletRequest.getRequestURI

StringBuffer url = request.getRequestURL();
String uri = request.getRequestURI();
int idx = (((uri != null) && (uri.length() > 0)) ? url.indexOf(uri) : url.length());
String host = url.substring(0, idx); //base url
idx = host.indexOf("://");
if(idx > 0) {
  host = host.substring(idx); //remove scheme if present
}

If you use the load balancer & Nginx, config them without modify code.如果您使用负载均衡器和 Nginx,请在不修改代码的情况下配置它们。

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's server.xml Engine: Tomcat 的 server.xml 引擎:

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

If only modify Nginx config file, the java code should be:如果只修改Nginx配置文件,java代码应该是:

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

If you want the original URL just use the method as described by jthalborn.如果您想要原始 URL,只需使用 jthalborn 描述的方法。 If you want to rebuild the url do like David Levesque explained, here is a code snippet for it:如果你想像 David Levesque 解释的那样重建 url,这里有一个代码片段:

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, ...);
}

You still need to consider the case of a reverse-proxy:您仍然需要考虑反向代理的情况:

Could use constants for the ports but not sure if there is a reliable source for them, default ports:可以为端口使用常量,但不确定是否有可靠的来源,默认端口:

Most developers will know about port 80 and 443 anyways, so constants are not that helpful.无论如何,大多数开发人员都会知道端口 80 和 443,因此常量并没有那么有用。

Also see this similar post .另请参阅此类似帖子

If your server is running behind a proxy server, make sure your proxy header is set:如果您的服务器在代理服务器后面运行,请确保设置了代理标头:

proxy_set_header X-Forwarded-Proto  $scheme;

Then to get the right scheme & url you can use springframework's classes:然后要获得正确的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();
}

I'm late to the party, but I had this same issue working with Java 8.我迟到了,但我在使用 Java 8 时遇到了同样的问题。

This is what worked for me, on the HttpServletRequest request object.这对我HttpServletRequest request ,在HttpServletRequest request对象上。

request.getHeader("origin");

and

request.getHeader("referer");

How I came to that conclusion:我是如何得出这个结论的:

I have a java app running on http://localhost:3000 making a Http Post to another java app I have running on http://localhost:8080 .我有一个在http://localhost:3000 上运行的 java 应用程序,向我在http://localhost:8080上运行的另一个 java 应用程序制作了一个 Http Post。

From the Java code running on http://localhost:8080 I couldn't get the http://localhost:3000 from the HttpServletRequest using the answers above.http://localhost:8080上运行的 Java 代码中,我无法使用上述答案从HttpServletRequest 中获取http://localhost:3000 For me using the getHeader method with the correct string input worked.对我来说,使用具有正确字符串输入的getHeader方法有效。

request.getHeader("origin") gave me " http://localhost:3000 " which is what I wanted. request.getHeader("origin")给了我http://localhost:3000 ,这正是我想要的。

request.getHeader("referer") gave me " http://localhost:3000/xxxx " where xxxx is full URL I have from the requesting app. request.getHeader("referer")给了我http://localhost:3000/xxxx ,其中 xxxx 是我从请求应用程序获得的完整 URL。

好像你需要从 URL 中剥离 URL,所以你可以通过以下方式进行:

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

Refer to http://docs.oracle.com/javase/tutorial/networking/urls/urlInfo.html . 请参阅http://docs.oracle.com/javase/tutorial/networking/urls/urlInfo.html This is the most concise coverage on url parsing. 这是关于url解析的最简洁的报道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM