在Servlet中为HTTP和HTTPS请求获取完整的URL和查询string

我正在写一个代码,其任务是检索请求的URL或完整path。 我已经写了这个代码:

HttpServletRequest request;//obtained from other functions String uri = request.getRequestURI(); if (request.getQueryString() != null) uri += "?" + request.getQueryString(); 

所以,当我浏览http://google.com?q=abc ,确定(正确)。 但浏览https://google.com时出现问题。 uri的值是http://google.com:443google.com:443 ,所以程序不仅在使用HTTPS时。

并且request.getRequestURL().toString()的输出是相同的。

解决办法是什么?

通过devise, getRequestURL()为您提供完整的URL,仅缺less查询string。

HttpServletRequest ,您可以使用以下方法获取URI的各个部分:

 // Example: http://myhost:8080/people?lastname=Fox&age=30 String uri = request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort() + // "8080" request.getRequestURI() + // "/people" "?" + // "?" request.getQueryString(); // "lastname=Fox&age=30" 
  • 如果是https://domain请求, .getScheme()会给你"https"
  • .getServerName()http(s)://domain上给出http(s)://domain
  • .getServerPort()会给你端口。

使用下面的代码片段:

 String uri = request.getScheme() + "://" + request.getServerName() + ("http".equals(request.getScheme()) && request.getServerPort() == 80 || "https".equals(request.getScheme()) && request.getServerPort() == 443 ? "" : ":" + request.getServerPort() ) + request.getRequestURI() + (request.getQueryString() != null ? "?" + request.getQueryString() : ""); 

上面的代码片段将得到完整的URI,如果使用默认的URI,则隐藏端口,不添加"?" 和查询string,如果没有提供后者。

代理请求

请注意,如果您的请求通过代理,您需要查看X-Forwarded-Proto头,因为该scheme可能会被更改:

 request.getHeader("X-Forwarded-Proto") 

另外,一个共同的标题是X-Forwarded-For ,它显示原始请求IP而不是代理IP。

 request.getHeader("X-Forwarded-For") 

如果您自己负责代理/负载均衡器的configuration,则需要确保在转发时设置这些头。

简单使用:

 String Uri = request.getRequestURL()+"?"+request.getQueryString(); 

当您尝试在服务器端构buildURL时, HTTPS请求变为HTTP这一事实表明,您可能有一个代理/负载均衡器( nginxpound等)将SSLencryption前后转移到纯后端服务HTTP

如果是这种情况,请检查,

  1. 不pipe你的代理是否已经被正确X-forwarded-protoHostX-forwarded-proto forward X-forwarded-protoX-forwarded-for forward X-forwarded-for等等)。
  2. 无论您的服务容器(如Tomcat )是否设置为识别前面的代理。 例如, Tomcat需要向其Connector添加secure="true" scheme="https" proxyPort="443"属性
  3. 无论您的代码或服务容器是否正确处理标题。 例如,当您将RemoteIpValve添加到其Engine时, Tomcat自动replaceschemeremoteAddr RemoteIpValve 。 (请参阅configuration指南 , JavaDoc ),因此您不必在代码中手动处理这些头文件。

request.getRequestURI()request.getRequestURL()尝试构造原始URL时,错误的代理头值可能会导致错误的输出。