Get full URL and query string in Servlet for both HTTP and HTTPS requests

progrrammer picture progrrammer · May 21, 2013 · Viewed 224.2k times · Source

I am writing a code which task is to retrieve a requested URL or full path. I've written this code:

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

So, when I browse http://google.com?q=abc it is OK (correct). But there is problem when I browse https://google.com. The value of uri is http://google.com:443google.com:443, So the program doesn't only when HTTPS is used.

And the output is same for request.getRequestURL().toString().

What is the solution?

Answer

acdcjunior picture acdcjunior · May 21, 2013

By design, getRequestURL() gives you the full URL, missing only the query string.

In HttpServletRequest, you can get individual parts of the URI using the methods below:

// 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() will give you "https" if it was a https://domain request.
  • .getServerName() gives domain on http(s)://domain.
  • .getServerPort() will give you the port.

Use the snippet below:

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() : "");

This snippet above will get the full URI, hiding the port if the default one was used, and not adding the "?" and the query string if the latter was not provided.


Proxied requests

Note, that if your request passes through a proxy, you need to look at the X-Forwarded-Proto header since the scheme might be altered:

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

Also, a common header is X-Forwarded-For, which show the original request IP instead of the proxys IP.

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

If you are responsible for the configuration of the proxy/load balancer yourself, you need to ensure that these headers are set upon forwarding.