Bug 32424 - Redirecting directiories with missing trailing slash breaks web applications
Summary: Redirecting directiories with missing trailing slash breaks web applications
Status: RESOLVED INVALID
Alias: None
Product: Tomcat 5
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 5.0.30
Hardware: PC Linux
: P2 major with 1 vote (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-11-29 11:08 UTC by Michael Wyraz
Modified: 2010-08-21 08:55 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Wyraz 2004-11-29 11:08:48 UTC
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
Comment 1 Michael Wyraz 2004-11-29 11:31:11 UTC
When i change the mapping from "/" to "/*" the url i no more redirected. But
should'nt it work for "/"?
Comment 2 Remy Maucherat 2004-11-29 11:38:45 UTC
"/" 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.
Comment 3 Sander de Boer 2004-12-13 15:28:12 UTC
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.
Comment 4 Remy Maucherat 2004-12-13 15:32:01 UTC
In this case, Tomcat will indeed issue a redirect right away.
Please do not reopen the issue.
Comment 5 Oliver Hutchison 2005-02-08 22:22:12 UTC
(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?
Comment 6 Remy Maucherat 2005-02-08 22:39:45 UTC
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.
Comment 7 Oliver Hutchison 2005-02-09 23:17:11 UTC
> 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?
Comment 8 Remy Maucherat 2005-02-10 00:04:54 UTC
Unfortunately, I would have to veto your patch. I would appreciate if you were
not whining. Thanks.
Comment 9 Remy Maucherat 2005-02-10 00:13:59 UTC
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.
Comment 10 Oliver Hutchison 2005-02-10 01:28:08 UTC
> 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.
Comment 11 Keith Wannamaker 2005-02-10 06:58:31 UTC
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.
Comment 12 Oliver Hutchison 2005-02-10 23:04:30 UTC
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. 
Comment 13 Remy Maucherat 2005-02-10 23:34:40 UTC
Didn't you promise the following: "Anyway I'll shutup since I'm clearly wasting
my time" ? ;)
Comment 14 Felix Roethenbacher 2005-02-21 00:05:32 UTC
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?!
Comment 15 roy huang 2005-04-25 05:45:46 UTC
(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?
Comment 16 Tibor Katelbach 2005-04-25 10:52:50 UTC
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. 
Comment 17 Remy Maucherat 2005-04-25 11:03:33 UTC
(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.
Comment 18 franck93 2010-08-21 08:55:53 UTC
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.