Hi there, I've been investigating bug #7686 since we have similar problems with our application. I think I've found the problem and a way to solve it, but this requires changes to several catalina core files, so I'd like to hear some opinions before sending a patch.
The Bug ======= Here's the problem (easily reproduceable using the attached war file): A servlet ("BugtestServlet") includes another servlet ("IncludedServlet") using ServletContext.getRequestDispatcher. Now IncludedServlet forwards to "/jsp/forwarded.jsp". So in summary we have: "/BugtestServlet" --- includes ---> "/IncludedServlet" --- forwards to ---> "/jsp/forwarded.jsp" Now if you request "/BugtestServlet", Tomcat returns an exception message saying the file "/IncludedServlet" cannot be found. Note that this problem does not occur when using Orion or Resin servlet engines. The Analysis ============ The problem originates from chapter 8 of the Servlet 2.3 spec. In short, it says that - in case of a forward, the resource that is forwarded to sees the servlet path (via getServletPath) used in the request dispatcher - in case of an include, the included resource sees the original servlet path (e.g. "/BugtestServlet") and can retrieve the path used in the request dispatcher (e.g. "/IncludedServlet") via special request attributes The problem starts when Jasper's JspServlet tries to determine which page to deliver. It cannot simply use getServletPath() since this will return the original path when doing an include. Thus, it checks if "javax.servlet.include.servlet_path" is present as a request attribute. If it is, JspServlet uses it instead of getServletPath(). This works in simple cases (e.g. a Servlet including a JSP), but fails for the bugtest webapp. Explanation: - in IncludedServlet, getServletPath() returns "/BugtestServlet" and the "javax.servlet.include.servlet_path" attribute is "/IncludedServlet" - in JspServlet (indirectly invoked by forwarding to "/jsp/forwarded.jsp"), getServletPath() returns "/jsp/forwarded.jsp" and the "javax.servlet.include.servlet_path" attribute is "/IncludedServlet" - since the additional request attribute is present, JspServlet thinks it has to use it instead of getServletPath() - processing "/IncludedServlet" as a JSP fails with a FileNotFoundException This is only the harmless case. As stated in the original bug report, you can easily produce endless forwarding loops when you replace the servlets of the bugtest app with JSPs. And it still get's worse: Let's say you have a JSP "test.jsp" that is included from somewhere. Now this JSP forwards to "/html/test.html". The result is that the ***JSP source code*** of "test.jsp" arrives at the browser! (To reproduce the last case with the attached war file: request "/jsp/including.jsp" and look at the source code of the returned page in your browser.) Proposed Solution ================= I would suggest to add a request attribute "org.apache.catalina.actual_servlet_path" that _always_ contains the path used when retrieving a request dispatcher. This way, the correct path could be determined no matter whether include or forward is used: - check if "org.apache.catalina.actual_servlet_path" is present; if so, use it as the path for accessing resources etc. - if the attribute is not present, fall back to the standard behaviour (i.e. check for "javax.servlet.include.servlet_path" and use getServletPath if this is not present) I've already tested this with JspServlet, and it works fine. However, to be consistent, several source files would have to be changed, for example: - DefaultServlet.java (necessary to solve the "forward to html" problem described above) - HttpRequestBase.java since it uses "javax.servlet.include.servlet_path" to convert a request-relative path to a context-relative one (currently, this probably failes within include/forward chains) - a bunch of other files (basically all that deal with the case of an include specifically) Also, the problem is not limited to "javax.servlet.include.servlet_path" but applies to all request attributes set in an include. For all of these, counterparts that reflect the correct path should be introduced. The best solution would be if the spec mandated such attributes, e.g. "javax.servlet.actual_path.servlet_path" etc. Should I write to [EMAIL PROTECTED] about it or is there a better place? Or maybe I'm missing something and the issue can be solved more elegantly? Final remarks ============= If I receive positive feedback on this, I'll happily send a comprehensive patch. Until now, I've only added an attribute for the servlet path (and not path info etc.) and a check for it in JspServlet. Thanks for your time Andreas Junghans PS Maybe this bug is also present in Tomcat 3.3 (haven't tested that).
bugtest.war
Description: Binary data
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>