views:

87

answers:

2

Suppose my Tomcat webapps directory looks like this:

webapps/
webapps/fooapp/
webapps/fooapp/WEB-INF/
webapps/fooapp/WEB-INF/web.xml
webapps/fooapp/bardir/

When I make a GET request for /fooapp/bardir, Tomcat sees that webapps/fooapp/bardir is a directory and sends back a 302 to /fooapp/bardir/ (with a slash at the end).

Here is my question: Where in the Tomcat source code does this take place? (I'm looking at 6.0.x but a correct answer for any version would be a great starting point.)

The only reference material I can find on this subject is in the Catalina Functional Specifications which states, regarding the Default Servlet:

On each HTTP GET request processed by this servlet, the following processing shall be performed:

[...]

  • If the requested resource is a directory:
    • If the request path does not end with "/", redirect to a corresponding path with "/" appended so that relative references in welcome files are resolved correctly.

However, this functionality does not appear to be in org.apache.catalina.servlets.DefaultServlet; or at least, it's not there exclusively: if I replace the default servlet in web.xml with a servlet whose servlet-class does not exist, directory paths still come back 302 to add the slash, while every other request comes back with an error as expected.

+1  A: 

I think it happens in org.apache.tomcat.util.http.mapper.Mapper, namely in the internalMapWrapper (Context, CharChunk, MappingData) method.

But unfortunately I'm not really sure -- maybe this really is a question better suited for the tomcat-users mailing list. Sorry for not having a better answer.

Henning
I think you found it! And the 'default servlet' comment seems to show that someone was a bit confused on when servlet mapping ought to happen, exactly as I suspected. Thanks for your help.
Anonymouse
A: 

The Eclipse debugger learnt me that the redirect happens in line 504 of CoyoteAdapter class, almost in the end of the postParseRequest() method.

    // Possible redirect
    MessageBytes redirectPathMB = request.getMappingData().redirectPath;
    if (!redirectPathMB.isNull()) {
        // ...
        response.sendRedirect(redirectPath); // <--- Here.
        return false;
    }

Tomcat 6.0.20 btw.

Update: actually, the redirectPath is indeed filled by the Mapper as mentioned in @Henning's answer, indeed in the internalMapWrapper() method. Checkout the source code here.

    if(mappingData.wrapper == null && noServletPath) {
        // The path is empty, redirect to "/"
        mappingData.redirectPath.setChars
            (path.getBuffer(), pathOffset, pathEnd);
        path.setEnd(pathEnd - 1);
        return;
    }
BalusC