在 Servlet 中获取 HTTP 和 HTTPS 请求的完整 URL 和查询字符串

新手上路,请多包涵

我正在编写一个代码,其任务是检索请求的 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.comuri 的值是 http://google.com:443google.com:443 ,所以程序不仅仅在使用 HTTPS 时。

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

解决办法是什么?

原文由 progrrammer 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 971
1 个回答

按照设计, 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")

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

原文由 acdcjunior 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题