42

我有两个应用程序部署在 JBoss 容器(同一个 unix 盒子)中。如果我收到来自 app1 的请求,我需要为 app2 发送相应的请求。

一个例子:如果 app1 请求:http://example.com/context?param1=123,那么我需要提取http://example.com/,以便我可以发送第二个应用程序的请求。

我尝试使用

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

但我如何区分httpor https

4

7 回答 7

65

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

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

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

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

  1. 改为使用HttpServletRequest.getHeader("x-forwarded-proto");这仅在您的负载均衡器正确设置标头时才有效(Apache 应该 afaik)。

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

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

于 2013-10-25T20:45:10.137 回答
22

您可以使用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
}
于 2013-10-25T20:25:52.477 回答
5

如果您使用负载均衡器和 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");
于 2015-08-19T08:50:30.883 回答
4

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

request.getRequestURL().toString().replace(request.getRequestURI(), "")
于 2020-05-07T08:07:06.403 回答
3

如果您想要原始 URL,只需使用 jthalborn 描述的方法。如果您想像 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, ...);
}

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

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

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

另请参阅此类似帖子

于 2015-04-28T09:50:38.443 回答
3

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

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();
}
于 2018-06-27T07:35:26.527 回答
2

我迟到了,但我在使用 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。

于 2019-03-21T12:45:15.363 回答