80

我正在编写一个代码,其任务是检索请求的 URL 或完整路径。我写了这段代码:

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。的值为urihttp://google.com:443google.com:443所以程序不只在HTTPS使用时。

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

解决办法是什么?

4

4 回答 4

178

按照设计,getRequestURL()为您提供完整的 URL,仅缺少查询字符串。

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"
  • .getScheme()"https"如果这是一个https://domain请求,会给你。
  • .getServerName()放弃。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,如果使用默认端口,则隐藏端口,如果"?"未提供后者,则不添加和查询字符串。


代理请求

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

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

此外,一个常见的标头是X-Forwarded-For,它显示原始请求 IP 而不是代理 IP。

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

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

于 2013-05-21T16:52:14.547 回答
10

只需使用:

String Uri = request.getRequestURL()+"?"+request.getQueryString();
于 2015-12-19T11:35:44.540 回答
4

当您尝试在服务器端构造 URL 时HTTPS请求变为的事实表明,您可能有一个代理/负载平衡器( 、等)在前端卸载 SSL 加密并以普通的方式转发到您的后端服务。HTTPnginxpoundHTTP

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

  1. 您的代理是否已设置为正确转发标头(HostX-forwarded-protoX-forwarded-for等)。
  2. 您的服务容器(例如Tomcat)是否设置为识别前面的代理。例如,Tomcat需要为其添加secure="true" scheme="https" proxyPort="443"属性Connector
  3. 您的代码或服务容器是否正确处理标头。例如,当您添加到其时Tomcat自动替换scheme,remoteAddr等值。(请参阅配置指南JavaDoc),因此您不必在代码中手动处理这些标头。RemoteIpValveEngine

不正确的代理标头值可能会导致在request.getRequestURI()request.getRequestURL()尝试构建原始 URL 时输出不正确。

于 2017-10-05T23:39:16.457 回答
1

我知道这是一个 Java 问题,但如果你使用 Kotlin,你可以很好地做到这一点:

val uri = request.run {
    if (queryString.isNullOrBlank()) requestURI else "$requestURI?$queryString"
}
于 2020-03-10T05:21:07.350 回答