What's the difference between getRequestURI and getPathInfo methods in HttpServletRequest?
I'm making a simple, very lightweight front-controller. I need to match request paths to different handlers (actions) in order to choose the correct one.
On my local machine HttpServletRequest.getPathInfo()
and HttpServletRequest.getRequestURI()
return the same results. But I'm not sure what will they return in the production environment.
So, what's the difference between these method and what should I choose?
I will put a small comparison table here (just to have it somewhere):
Servlet is mapped as /test%3F/*
and the application is deployed under /app
.
http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=S%3F+ID?p+1=c+d&p+2=e+f#a
Method URL-Decoded Result
----------------------------------------------------
getContextPath() no /app
getLocalAddr() 127.0.0.1
getLocalName() 30thh.loc
getLocalPort() 8480
getMethod() GET
getPathInfo() yes /a?+b
getProtocol() HTTP/1.1
getQueryString() no p+1=c+d&p+2=e+f
getRequestedSessionId() no S%3F+ID
getRequestURI() no /app/test%3F/a%3F+b;jsessionid=S+ID
getRequestURL() no http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=S+ID
getScheme() http
getServerName() 30thh.loc
getServerPort() 8480
getServletPath() yes /test?
getParameterNames() yes [p 2, p 1]
getParameter("p 1") yes c d
In the example above the server is running on the localhost:8480
and the name 30thh.loc
was put into OS hosts
file.
Comments
"+" is handled as space only in the query string
Anchor "#a" is not transferred to the server. Only the browser can work with it.
If the
url-pattern
in the servlet mapping does not end with*
(for example/test
or*.jsp
),getPathInfo()
returnsnull
.
If Spring MVC is used
Method
getPathInfo()
returnsnull
.Method
getServletPath()
returns the part between the context path and the session ID. In the example above the value would be/test?/a?+b
Be careful with URL encoded parts of
@RequestMapping
and@RequestParam
in Spring. It is buggy (current version 3.2.4) and is usually not working as expected.
getPathInfo()
gives the extra path information after the URI, used to access your Servlet, where as getRequestURI()
gives the complete URI.
I would have thought they would be different, given a Servlet must be configured with its own URI pattern in the first place; I don't think I've ever served a Servlet from root (/).
For example if Servlet 'Foo' is mapped to URI '/foo' then I would have thought the URI:
/foo/path/to/resource
Would result in:
RequestURI = /foo/path/to/resource
and
PathInfo = /path/to/resource
Let's break down the full URL that a client would type into their address bar to reach your servlet:
http://www.example.com:80/awesome-application/path/to/servlet/path/info?a=1&b=2#boo
The parts are:
- scheme:
http
- hostname:
www.example.com
- port:
80
- context path:
awesome-application
- servlet path:
path/to/servlet
- path info:
path/info
- query:
a=1&b=2
- fragment:
boo
The request URI (returned by getRequestURI) corresponds to parts 4, 5 and 6.
(incidentally, even though you're not asking for this, the method getRequestURL would give you parts 1, 2, 3, 4, 5 and 6).
Now:
- part 4 (the context path) is used to select your particular application out of many other applications that may be running in the server
- part 5 (the servlet path) is used to select a particular servlet out of many other servlets that may be bundled in your application's WAR
- part 6 (the path info) is interpreted by your servlet's logic (e.g. it may point to some resource controlled by your servlet).
- part 7 (the query) is also made available to your servlet using getQueryString
- part 8 (the fragment) is not even sent to the server and is relevant and known only to the client
The following always holds (except for URL encoding differences):
requestURI = contextPath + servletPath + pathInfo
The following example from the Servlet 3.0 specification is very helpful:
Note: image follows, I don't have the time to recreate in HTML:
Consider the following servlet conf:
<servlet>
<servlet-name>NewServlet</servlet-name>
<servlet-class>NewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>NewServlet</servlet-name>
<url-pattern>/NewServlet/*</url-pattern>
</servlet-mapping>
Now, when I hit the URL http://localhost:8084/JSPTemp1/NewServlet/jhi
, it will invoke NewServlet
as it is mapped with the pattern described above.
Here:
getRequestURI() = /JSPTemp1/NewServlet/jhi
getPathInfo() = /jhi
We have those ones:
-
getPathInfo()
returns
a String, decoded by the web container, specifying extra path information that comes after the servlet path but before the query string in the request URL; or null if the URL does not have any extra path information -
getRequestURI()
returns
a String containing the part of the URL from the protocol name up to the query string