From version 5.0.4 to 5.0.5 the File org/apache/tomcat/util/http/mapper/Mapper.java was changed to redirect requests which matches a directory but have a missing trailing slash are redirected to the same url with the slash. This breaks some webapps because the redirect is also done for urls which are mapped to servlets. Example: A Servlet is mapped to /. The user calls /page which is handled by the servlet. If a direcory named "page" exists, tomcat redirects to /page/. This is fine for directory indexing but bad for complex applications. See also: http://cvs.apache.org/viewcvs.cgi/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/mapper/Mapper.java?r1=1.23&r2=1.24
When i change the mapping from "/" to "/*" the url i no more redirected. But should'nt it work for "/"?
"/" is if everything else failed. The mapper has to assume that the default servlet will, at least to some extent, be responsible for static page serving.
I have a filter mapped to /* When I call a url without a trailing slash which is a directory, tomcat redirects it to this dir with slash.
In this case, Tomcat will indeed issue a redirect right away. Please do not reopen the issue.
(In reply to comment #4) > In this case, Tomcat will indeed issue a redirect right away. > Please do not reopen the issue. Why does Tomcat redirect right away? Shouldn't the filter be given a chance to process the original (no slash) request? I have an application that was previously deployed using Jetty and I'm currently looking at moving over to Tomcat 5.5 but this is a show stopper for me. I can't rename the directories and the end users expect the original (no slash) paths to work. The application does not do directory listings so adding the slash doesn't help us in the least. Is there a way to disable this? It seems to me that this redirect should be sent by the default servlet *after* any user filters/servlet have had a chance to process the request but then I assume this behaviour is according to the spec? If so where is it specified?
The behavior is not specified anywhere, but the idea is that in the case of a physical folder or the root of a context, the trailing '/' is not relevant. Since this causes recurrent path resolution issues (which made servlets like our default servlet needlessly more complex), we always present the servlet with a training '/' in all cases. It is also the most efficient, so that's the the implementation which is currently used. I regret it would prevent you from using Tomcat, but there's nothing that I will change here.
> The behavior is not specified anywhere Then isn't it clearly a bug? While the slash makes no sematic difference when your using the default servlet it *can* and does make a difference for applications that do not use the default servlet (like mine and clearly others). Also so much for interoperability between Servlet containers. Given that Tomcat is the reference implementation of the Servlet spec should I raise a bug with Jetty (and probably every other implementation) given that it does not exhibit this behaviour? > I regret it would prevent you from using Tomcat, but there's nothing > that I will change here. I understand that I'm not going to persuade you to change this but at the very least there should be a way to disable it. If you point me in the right direction perhaps I could implement a patch?
Unfortunately, I would have to veto your patch. I would appreciate if you were not whining. Thanks.
If you want to modify the HTTP mapping behavior for your own purposes, the mapping class is org.apache.tomcat.util.http.mapper.Mapper in jakarta-tomcat-connectors/util. Rule 7 is the one which sends the HTTP redirect.
> I would appreciate if you were not whining. I'm simply trying to get a decent explanation of why this is not a bug - which you have failed to provide in any of your comments. I understand this behaviour is solving some problem or other but that doesn't mean it not a bug and it's certainly contrary to the spirit of the spec relating to filters and to the mapping of requests. Anyway I'll shutup since I'm clearly wasting my time.
FWIW The redirect to add a trailing slash is required prior to any authentication challenges for correct credential cacheing on the client. The container is correct to 302 + / the request as soon as possible, if the request is missing a trailing slash. When I tested Jetty about a year ago it did this as well.
Keith thanks for making the logic behind this clearer. I understand that this is desirable behaviour *when* the "default" servlet ends up handling the request but the redirect happens in "Rule 7" of the mapper where it is only *possible* that the "default" servlet will handle the request. In my web app a filter forwards the request on so that in the end the "default" servlet is never invoked which means the assumption made at "Rule 7" was invalid. In addition to this the spec is quite clear that a filter that is mapped to "/*" should be given the opportunity to filter all requests - in this special case Tomcat does not fulfil this requirement as it makes the *incorrect* assumption that the redirected request is logically the same as the original. eg. In my web app the request for "/images" is not the same as "/images/" (even though I don't have a servlet mapped to "/images") however Tomcat does not allow our forwarding filter to process the "/images" request and forward it on the the correct servlet as there happens to be a directory called "images" in out web app. I'm currently using Jetty and it allows filters to process the request *before* doing the 302.
Didn't you promise the following: "Anyway I'll shutup since I'm clearly wasting my time" ? ;)
The migration of Tomcat 4.x / Jetty web applications to 5.5.x is not possible because of this 302/redirect for url's with names like existing directories in the web app. This may be a real show stopper! I still do not understand why Tomcat interferes with the url space my web app is responsible for?!
(In reply to comment #9) > If you want to modify the HTTP mapping behavior for your own purposes, the > mapping class is org.apache.tomcat.util.http.mapper.Mapper in > jakarta-tomcat-connectors/util. Rule 7 is the one which sends the HTTP redirect. Is it possible to make this configurable in tomcat 5 or 5.5?
This is definitly a structural bug within Tomcat5, Redirection decisions shouldn't be made by Tomcat but by our own application, otherwise we should constrain our architecture to Tomcats own structure?? or be stuck with using T4.1 or another container... this will surely be a recurent bug declaration. I understand if this simplifies T5's structure but is it acceptable to constraint this way? In my use case I call for url : /login an he sends me to /login/ even though I don't even have a login folder and after login instead of redirect to /myurl he blocks me in that context being: /login/myurl which ofcourse makes no sense. Please reconcider this issue. or atleast make it configurable as Roy requests it.
(In reply to comment #16) > This is definitly a structural bug within Tomcat5, Redirection decisions > shouldn't be made by Tomcat but by our own application, otherwise we should > constrain our architecture to Tomcats own structure?? or be stuck with using > T4.1 or another container... this will surely be a recurent bug declaration. > I understand if this simplifies T5's structure but is it acceptable to > constraint this way? In my use case I call for url : /login an he sends me > to /login/ even though I don't even have a login folder and after login instead > of redirect to /myurl he blocks me in that context being: /login/myurl which > ofcourse makes no sense. > Please reconcider this issue. > or atleast make it configurable as Roy requests it. Unfortunately, the basis for your rant is bad. There will be no redirection of any sort unless you do have a "login" folder. Otherwise, how do you expect Tomcat to be able to match a servlet mapped to, say "/test" ? Indeed, if you do not like this behavior, you should at the moment consider using another container, or change the code to your liking according to my indications. Also, please try to get spelling right. This helps raising credibility of the person making the statement.
After having carefully read all comments here, I still do not understand why it would not make sense to allow disabling rule 7. Why would you serve the content rather than sending an HTTP 301 to the client. To my knowledge search engines consider that URLs sans trailing slash and URLs with trailing slash are different. Consequently tomcat would serve an identical content for two different URLs which can lead to poor SEO ranking. I'd like to know if this behavious also apply to tomcat 6.