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?
This question is related to
java
servlets
httprequest
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.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.
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.
String Uri = request.getRequestURL()+"?"+request.getQueryString();
The fact that a HTTPS
request becomes HTTP
when you tried to construct the URL on server side indicates that you might have a proxy/load balancer (nginx
, pound
, etc.) offloading SSL encryption in front and forward to your back end service in plain HTTP
.
If that's case, check,
Host
, X-forwarded-proto
, X-forwarded-for
, etc). Tomcat
) is set up to recognize the proxy in front. For example, Tomcat
requires adding secure="true" scheme="https" proxyPort="443"
attributes to its Connector
Tomcat
automatically replaces scheme
, remoteAddr
, etc. values when you add RemoteIpValve
to its Engine
. (see Configuration guide, JavaDoc) so you don't have to process these headers in your code manually.Incorrect proxy header values could result in incorrect output when request.getRequestURI()
or request.getRequestURL()
attempts to construct the originating URL.
I know this is a Java question, but if you're using Kotlin you can do this quite nicely:
val uri = request.run {
if (queryString.isNullOrBlank()) requestURI else "$requestURI?$queryString"
}
Source: Stackoverflow.com