1.jsp: <%getServletContext().getRequestDispatcher("/2.jsp").forward(request, response);%> 2.jsp: <%out.print(request.getRequestURL());%> The output of 2.jsp is "http://.../1.jsp" but NOT "http://...2.jsp". According to SRV8.4, "The path elements of the request object exposed to the target servlet must reflect the path used to obtain the RequestDispatcher." In this test case, "path used to obtain the RequestDispatcher" is "/2.jsp", so getRequestURL() in 2.jsp should return "http://...2.jsp".
Fixed in CVS for TC4.1.x and TC5.5.x
This fix gives many problems when using frameworks like struts and spring together with templating (i.e. Tiles). It will now always return the JSP of the template, which makes it impossible to find out what the actual request uri was.
I cannot say if the fix is invalid or not. Actually, it seems valid to me, and as a result, it's here to stay. You obviously can retrieve any of the original request paths (you have all the RD request attributes at your disposal for this). Please do not reopen the report.
IMHO this conflicts with the specification of HttpServletRequest.getRequestURL(): "Reconstructs the URL the client used to make the request" It says "the client" but after a forward the returned URL is not the client URL anymore. btw I'm posting this because the "fix" breaks my applications :(
This bug also affects web pages protected by the web.xml constraint: <security-constraint> . . . <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> What happens is if the user access the page via an unsecure URL like: http://localhost:8080/MyAccount Tomcat will redirect to an SSL enable port if the redirectPort pramater is specified for the connector. In my case, the secure port where SSL is enabled is port 8443 The resulting req.getRequestURL() call returns: https://localhost:8080/MyAccount which is incorrect. Tomcat should have returned: https://localhost:8443/MyAccount
*** Bug 35317 has been marked as a duplicate of this bug. ***
*** Bug 35425 has been marked as a duplicate of this bug. ***
As mentioned in some of the previous comments, this fix seems to have broken what was working for me in 5.0. For a demo of what happens, see http://fdis.etg.gc.ca:8080/cdua3 for the Tomcat 5.0 version, and http://fdis.etg.gc.ca:8081/cdua3.3 for the Tomcat 5.5 version. To see the difference in behaviour, click multiple times on the "English" and "Français" hyperlinks at the top left of the screen. You will find out the 5.0 version works, but the 5.5 does not because it uses the jsp URL instead of the Struts action. The code can be downloaded from the same website for inspection (cdua3.tags.LinkTranslateURLTag.java). As far as I am concerned, the only question to ask is: was the behavior of the getRequestURL function broken in 5.0 - i.e., it was being used in the wrong way by my application and I was lucky to get it to work-, or is it broken now? Thank you for your attention on this matter.
5.0 is broken and you were lucky 5.5 has the correct (as required by SRV.8.4) behaviour The fix for your app should be simple, SRV.8.4 explains where you can get the info you require.
The problem is also that tomcat servlet's javadocs were (are still??) misleading and sugesting behaviour of 5.0 tomcat.
The servlet JavaDocs are defined by the servlet spec team and we can't change them.
Sorry for that "tomcat's" thing then. Anyway I am pretty confused right now. If these javadocs are driven by servlet spec then HttpServletRequest.getRequest() states: "Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and server path, but it does not include query string parameters." ( http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletRequest.html#getRequestURL() ) This really stands in the way of specs themselfs. But I guess you can't do anything about it and I should bother someone else about it. Cheers, Radek.
Yep, the JavaDocs are confusing here. The JavaDocs make no mention of the requirements of SRV.8.4. However, SRV.8.4 is very clear on how this should work. The place to send your comments is servletapi-feedback@eng.sun.com In my view, the Javadocs should at least refer to the requirements of SRV.8.4 and shoudl really include the full requirement here.
I just filed Issue 26 ("[javadocs] HttpServletRequest.getRequestURL() does not consider RD.forward() scenario") with the Servlet EG, see https://servlet-spec-eg.dev.java.net/issues/show_bug.cgi?id=26, with the following description: ====================================================================== The javadocs of javax.servlet.http.HttpServletRequest.getRequestURL() have been misleading and causing confusion among developers. See http://issues.apache.org/bugzilla/show_bug.cgi?id=28222, Synopsis: "getRequestURL() in forwarded jsp/servlet doesn't return new url", for details. I am proposing the following clarification to the javadocs of javax.servlet.http.HttpServletRequest.getRequestURL(): Index: HttpServletRequest.java =================================================================== RCS file: /cvs/glassfish/servlet-api/src/jakarta-servletapi-5/jsr154/src/share/javax/servlet/http/HttpServletRequest.java,v retrieving revision 1.2 diff -u -r1.2 HttpServletRequest.java --- HttpServletRequest.java 16 Aug 2005 02:02:08 -0000 1.2 +++ HttpServletRequest.java 1 Nov 2005 18:31:11 -0000 @@ -535,6 +535,11 @@ * number, and server path, but it does not include query * string parameters. * + * <p>If this request has been forwarded using + * {@link javax.servlet.RequestDispatcher#forward}, the server path in the + * reconstructed URL must reflect the path used to obtain the + * RequestDispatcher, and not the server path specified by the client. + * * <p>Because this method returns a <code>StringBuffer</code>, * not a string, you can modify the URL easily, for example, * to append query parameters. =================================================================== We still have a small window of opportunity where clarifications of this kind may be added to the Servlet 2.5 spec.
For those of you affected by this bug, here is a simple utility method for recreating the URL of the current request: /** * Recreates the full URL that originally got the web client to the given * request. This takes into account changes to the request due to request * dispatching. * * <p>Note that if the protocol is HTTP and the port number is 80 or if the * protocol is HTTPS and the port number is 443, then the port number is not * added to the return string as a convenience.</p> */ public final static String getReturnURL(HttpServletRequest request) { if (request == null) { throw new IllegalArgumentException("Cannot take null parameters."); } String scheme = request.getScheme(); String serverName = request.getServerName(); int serverPort = request.getServerPort(); //try to get the forwarder value first, only if it's empty fall back to the current value String requestUri = (String)request.getAttribute("javax.servlet.forward.request_uri"); requestUri = (requestUri == null) ? request.getRequestURI() : requestUri; //try to get the forwarder value first, only if it's empty fall back to the current value String queryString = (String)request.getAttribute("javax.servlet.forward.query_string"); queryString = (queryString == null) ? request.getQueryString() : qs; StringBuffer buffer = new StringBuffer(); buffer.append(scheme); buffer.append("://"); buffer.append(serverName); //if not http:80 or https:443, then add the port number if( !(scheme.equalsIgnoreCase("http") && serverPort == 80) && !(scheme.equalsIgnoreCase("https") && serverPort == 443) ) { buffer.append(String.valueOf(serverPort)); } buffer.append(requestUri); if (queryString != null) { buffer.append("?"); buffer.append(queryString); } return buffer.toString(); }