Well, I am not quite sure it is a bug, but I lost one day to find where my problem was, so it may be helpful :) When the context name contains a space character (' ') everything works fine , except that the session object in the request is null (and a new session is created when getSession is invoked ) even if a session has already been initialized. For example: public class MyServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html><body><a href=\"MyServlet\"> click me!</a><br>"); out.println(request.getSession().getAttribute("hello")); out.println("</body></html>"); request.getSession().setAttribute("hello", "Hello!"); } } When the context name contains a space (fo example: "Sample Project") and you load the page and click on the link, the result is always : click me null When you change the name to "SampleProject", the problem is gone.
Where are you defining this context name? In the web.xml (display-name attribute)? In the context.xml file for the context? Or explicitly by making it a directory in the webapps directory?
In the server.xml. I am using Eclipse and a tomcat plugin for it. It defines the context in the server.xml file.
Can you attach your server.xml file to this report please?
Created attachment 12843 [details] server.xml
Created attachment 12844 [details] The Eclipse project for testing
I've verified your bug outside Eclipse, and I'm attaching a WAR that lets one reproduce it on an out-of-the-box tomcat. Deploying this war as SessionSpace.war versus "Session Space.war" shows the bug. I'm updating the comopnent, platform, OS, version fields of the bug report as well.
Created attachment 12851 [details] WAR to reproduce bug
This is due to browsers not recognizing spaces in the session cookie's path. See the headers from two hits to the example (from the war file by Yoav Shapira). I'm attaching a patch to fix this. Tested with MSIE 6 and Mozilla 1.7.2 Headers ======================================================== http://localhost:8080/Sample%20App/test GET /Sample%20App/test HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040803 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Cache-Control: max-age=0 HTTP/1.x 200 OK Server: Apache-Coyote/1.1 Set-Cookie: JSESSIONID=33047CF84AA4E7159F1262C21D4FEA83; Path=/Sample App Content-Type: text/html;charset=ISO-8859-1 Content-Length: 165 Date: Wed, 13 Oct 2004 01:31:50 GMT ---------------------------------------------------------- http://localhost:8080/Sample%20App/test GET /Sample%20App/test HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040803 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8080/Sample%20App/test Cache-Control: max-age=0 HTTP/1.x 200 OK Server: Apache-Coyote/1.1 Set-Cookie: JSESSIONID=82313411257D1DA54FDFD741D4E1FE78; Path=/Sample App Content-Type: text/html;charset=ISO-8859-1 Content-Length: 165 Date: Wed, 13 Oct 2004 01:32:03 GMT ----------------------------------------------------------
Created attachment 13058 [details] Patch to encode spaces in session cookie path
Good investigation and finding, OK patch. OK because replaceAll is in JDK 1.4, so I can use the patch as-is for Tomcat 5.5, but for Tomcat 5.0 we need the same thing in JDK 1.3-compatible format. Maybe I'll just URLEncoder.encode the cookie's path?
Ahh, good point. I originally went with the URLEncoder but it was encoding the "/" at the beginning. So, to go this route, I would either need to strip out the "/" before encoding or do a replace afterwards.
If characters other than spaces don't need to be considered, maybe use this patch on 5.5x. and use the URLEncoder for the older release? Note: The Request class doesn't import URLEncoder yet so this means one more object created for each request. This needs to be added to the object creation involved with pulling and replacing the "/". Probably trivial but I know there is a lot of effort being made to increase performance and it's a shame to add more overhead just to support spaces in a context path.
Maybe add a URL encoded path field on the Context. (URL encoding stuff all the time is a bit expensive, and it could be needed) I'll try it later today. BTW, before making any changes: cookie values should be URL encoded then ? I don't remember that, but maybe it's true. Can anyone confirm ?
Actually, I think cookies shouldn't be URL encoded. See the ServerCookie class, and in particular the maybeQuote and isToken methods. Now ' ' isn't part of the "special" list anymore, for some reason. OTOH, the Cookie class from the servlet API includes: private static final String tspecials = ",; "; I think the bug will only need a change there.
IMHO, Remy's idea is best. But it will throw an IAE since the session cookie is v0. Probably we could just remove the version check in maybeQuote, since I'm guessing that most UAs probably support quoted values, even if they don't support all of RFC2019. Using the JDK1.3 j.n.URLEncoder is going to cause more problems then it will ever solve, given that it uses the platform encoding (which is unlikely to be utf-8 :). If you have to encode the path, use the UEncoder in the Response.
Ah, yes, I missed that "small" point. I thought I had a really good idea here ;) BTW, can you explain the tspecials descrepancy between the two cookies classes for the tspecial field ?
It looks like the ServerCookie value is the one from jakarta-servletapi (aka servlet-2.2), and simply hasn't been updated.
After discussion on the tomcat-dev list, I'm closing this as WONTFIX because it's a contrived use-case: the browser will never send a request with a space character in it (it'd be encoded as %20, which is handled fine by Tomcat).
Yes, but the problem is that TC will set a cookie based on the unencoded path, and the browser doesn't make the association between that and the URL (somehow). In theory, we would need to URL encode the context path using straight conversion.
.
It is fixed now, but the fix assumes UTF-8 encoding for URLs. I guess even if it doesn't work always, it's better than it it never works.
Forgot to mention: for really tricky situations (i18n ...), you can also choose to set the cookie path to "/" by using emptySessionPath="true" on the Connector.