What's the difference between getRequestURI and getPathInfo methods in HttpServletRequest?

JavaServlets

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

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() returns null.

If Spring MVC is used

  • Method getPathInfo() returns null.

  • 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.

Solution 2 - Java

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

Solution 3 - Java

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:

  1. scheme: http
  2. hostname: www.example.com
  3. port: 80
  4. context path: awesome-application
  5. servlet path: path/to/servlet
  6. path info: path/info
  7. query: a=1&b=2
  8. 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:

enter image description here

Solution 4 - Java

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRomanView Question on Stackoverflow
Solution 1 - Java30thhView Answer on Stackoverflow
Solution 2 - JavatrojanfoeView Answer on Stackoverflow
Solution 3 - JavaMarcus Junius BrutusView Answer on Stackoverflow
Solution 4 - JavajmjView Answer on Stackoverflow