craftsman
craftsman

Reputation: 15623

How to get request URI without context path?

The Method request.getRequestURI() returns URI with context path.

For example, if the base URL of an application is http://localhost:8080/myapp/ (i.e. the context path is myapp), and I call request.getRequestURI() for http://localhost:8080/myapp/secure/users, it will return /myapp/secure/users.

Is there any way we can get only this part /secure/users, i.e. the URI without context path?

Upvotes: 152

Views: 327672

Answers (8)

Devabc
Devabc

Reputation: 5271

Short Answer

String requestUriWithinApp = req.getPathInfo() == null
        ? req.getServletPath()
        : req.getServletPath() + req.getPathInfo();

ServletPath gets the part of the URL that calls the servlet. And PathInforeturns any extra path information associated with the URL the client sent when it made this request. PathInfo may be null, depending on the URL used by the client.

For a more complete URI, you could also include the queryString. You could then use:

StringBuilder sb = new StringBuilder();
sb.append(req.getServletPath());
if (req.getPathInfo() != null) {
    sb.append(req.getPathInfo());
}
if (req.getQueryString() != null) {
    sb.append("?").append(req.getQueryString());
}

Additional info

The formula of the requestURI is:

requestURI = contextPath + servletPath + pathInfo

In your question you don't want to use the contextPath, so you need:

servletPath + pathInfo

For example, if you have:

  • a webapp context at /catalog and
  • a GardenServlet for pattern /garden/* and
  • a request send by the client for /catalog/lawn/index.html
  • then the pathInfo is /index.html

This example is described in more detail in Servlet Specification - 3.6 Request Path Elements.

The documentation of Tuckey's UrlRewriteFilter contains a more complete example of how the URL is composed in a ServletRequest.

    // http://hostname.com:80/mywebapp/servlet/MyServlet/a/b;c=123?d=789
    public static String getUrl(HttpServletRequest req) {
        String scheme = req.getScheme();             // http
        String serverName = req.getServerName();     // hostname.com
        int serverPort = req.getServerPort();        // 80
        String contextPath = req.getContextPath();   // /mywebapp
        String servletPath = req.getServletPath();   // /servlet/MyServlet
        String pathInfo = req.getPathInfo();         // /a/b;c=123
        String queryString = req.getQueryString();   // d=789

        // Reconstruct original requesting URL
        String url = scheme + "://" + serverName + ":" + serverPort + contextPath + servletPath;
        if (pathInfo != null) {
            url += pathInfo;
        }
        if (queryString != null) {
            url += "?" + queryString;
        }
        return url;
    }

Upvotes: 0

BalusC
BalusC

Reputation: 1108742

If you're inside a front contoller servlet which is mapped on a prefix pattern such as /foo/*, then you can just use HttpServletRequest#getPathInfo().

String pathInfo = request.getPathInfo();
// ...

Assuming that the servlet in your example is mapped on /secure/*, then this will return /users which would be the information of sole interest inside a typical front controller servlet.

If the servlet is however mapped on a suffix pattern such as *.foo (your URL examples however does not indicate that this is the case), or when you're actually inside a filter (when the to-be-invoked servlet is not necessarily determined yet, so getPathInfo() could return null), then your best bet is to substring the request URI yourself based on the context path's length using the usual String method:

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...

Upvotes: 178

James
James

Reputation: 12182

With Spring you can do:

String path = new UrlPathHelper().getPathWithinApplication(request);

Upvotes: 42

thetoolman
thetoolman

Reputation: 2164

If you use request.getPathInfo() inside a Filter, you always seem to get null (at least with jetty).

This terse invalid bug + response alludes to the issue I think:

https://issues.apache.org/bugzilla/show_bug.cgi?id=28323

I suspect it is related to the fact that filters run before the servlet gets the request. It may be a container bug, or expected behaviour that I haven't been able to identify.

The contextPath is available though, so fforws solution works even in filters. I don't like having to do it by hand, but the implementation is broken or

Upvotes: 9

lukastymo
lukastymo

Reputation: 26809

getPathInfo() sometimes return null. In documentation HttpServletRequest

This method returns null if there was no extra path information.

I need get path to file without context path in Filter and getPathInfo() return me null. So I use another method: httpRequest.getServletPath()

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String newPath = parsePathToFile(httpRequest.getServletPath());
    ...

}

Upvotes: 16

fforw
fforw

Reputation: 5491

request.getRequestURI().substring(request.getContextPath().length())

Upvotes: 90

Colin
Colin

Reputation: 551

May be you can just use the split method to eliminate the '/myapp' for example:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];

Upvotes: -1

PeterMmm
PeterMmm

Reputation: 24630

A way to do this is to rest the servelet context path from request URI.

String p = request.getRequestURI();
String cp = getServletContext().getContextPath();

if (p.startsWith(cp)) {
  String.err.println(p.substring(cp.length());
}

Read here .

Upvotes: 5

Related Questions