DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=22013>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=22013

RequestDispatcher.forward doesn't work with a relative path on a forwarded request





------- Additional Comments From [EMAIL PROTECTED]  2004-02-04 22:51 -------
I also think this really is a bug.

For me, this bug is from the org.apache.catalina.core.ApplicationHttpRequest 
class. 

When a dispath is done, the original request is wrapped with a 
ApplicationHttpRequest (that extends HttpServletRequestWrapper). The path 
elements of the ApplicationHttpRequest are set to reflect the path used to 
obtain the RequestDispatcher.

The problem is that the ApplicationHttpRequest doesn't overload 
getRequestDispatcher(String). So if the targeted servlet call the 
getRequestDispatcher method, the call will be delegated to the nested request 
(ie the original request) that will convert the request-relative path to a 
context-relative using its own path elements.

The servlet specification doesn't explain what to do in such a case (when two 
forward are done for the same request) but its seems normal that the relative 
path used to get the RequestDispatcher (by the 
HttpServletRequest.getRequestDispatcher(String)) uses the path elements of the 
curent request instead of using the ones of the original request.

This problem could be solve by adding in the ApplicationHttpRequest the code of 
the getRequestDispatcher method of the HttpRequestBase class : 

    /**
     * Return a RequestDispatcher that wraps the resource at the specified
     * path, which may be interpreted as relative to the current request path.
     *
     * @param path Path of the resource to be wrapped
     */
    public RequestDispatcher getRequestDispatcher(String path) {

        if (context == null)
            return (null);

        // If the path is already context-relative, just pass it through
        if (path == null)
            return (null);
        else if (path.startsWith("/"))
            return (context.getServletContext().getRequestDispatcher(path));

        // Convert a request-relative path to a context-relative one
        String servletPath = (String) getAttribute(Globals.SERVLET_PATH_ATTR);
        if (servletPath == null)
            servletPath = getServletPath();

        int pos = servletPath.lastIndexOf('/');
        String relative = null;
        if (pos >= 0) {
            relative = RequestUtil.normalize
                (servletPath.substring(0, pos + 1) + path);
        } else {
            relative = RequestUtil.normalize(servletPath + path);
        }

        return (context.getServletContext().getRequestDispatcher(relative));

    }

This method need the context object so the context must be added in the 
ApplicationHttpRequest constructor parameters. The constructor is only called 
from the ApplicationDispatcher that have the context object => it's not a 
problem. Here is the addition of the attribute and the modification on the 
constructor : 

import org.apache.catalina.Context;

// ...

    /**
     * The Context this ApplicationHttpRequest is associated with.
     */
    private final Context context;

    /**
     * Construct a new wrapped request around the specified servlet request in 
the specified context.
     *
     * @param request The servlet request being wrapped
     * @param context The Context this ApplicationHttpRequest is associated with
     */
    public ApplicationHttpRequest(HttpServletRequest request, Context context) {
        super(request);
        setRequest(request);
        this.context = context;
    }


and finally the modification of the constructor call in the wrapRequest() 
method of the ApplicationDispatcher class : 

        // Instantiate a new wrapper at this point and insert it in the chain
        ServletRequest wrapper = null;
        if ((current instanceof ApplicationHttpRequest) ||
            (current instanceof HttpRequest) ||
            (current instanceof HttpServletRequest))
            wrapper = new ApplicationHttpRequest((HttpServletRequest) current, 
context);



Hope it helps.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to