[英]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
?但是我如何在
http
或https
之间进行区分?
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.getRequestURL和HttpServletRequest.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,因此常量并没有那么有用。
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.