Bug 40160 - Webdav Context path must be /*
Webdav Context path must be /*
Status: RESOLVED FIXED
Product: Tomcat 5
Classification: Unclassified
Component: Servlets:WebDAV
Unknown
PC Windows XP
: P2 enhancement (vote)
: ---
Assigned To: Tomcat Developers Mailing List
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2006-08-02 04:35 UTC by Andrew Conway
Modified: 2006-12-26 06:22 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Conway 2006-08-02 04:35:45 UTC
The context path at which the webdav servlet is run must be
/*. That is, a web.xml entry like the following does
not work:

<servlet-mapping>
<servlet-name>webdavsf</servlet-name>
<url-pattern>/dav/*</url-pattern>
</servlet-mapping>

This is tested on 5.5.17

This is unfortunate if you want to have one WAR file
containing some other servlets and a dav area with
content autogenerated by the servlets.

I have made patches to "webdav servlet" on SourceForge, which is derived from
the apache code and has the same problem. My patches seem to fix it, and I
suspect that very similar patches would fix the original version. I am not a dav
expert though, and I haven't tested it on the original version, nor any locking
etc. So the patches described bel

There seem to be two reasons for this requirement for /* instead of, say /dav/*

(1) The internal path generated for a null entry is
wrong. This can be fixed by removing the following
lines from getRelativePath() [in DefaultServlet]:
            if (result == null)
                result = (String) request.getAttribute(
                                            Globals.INCLUDE_SERVLET_PATH_ATTR);

and
if (result == null) {
            result = request.getServletPath();
        }
I don't see how these lines could ever help in the WebDav context, though I am
not an expert in dav, and they may be important in some other use of DefaultServlet.

The second required modification that I posted for "webdav servlet" on
sourceforge has already been fixed (or something equivalent) in 5.5.17., so you
should be able to ignore that.
Comment 1 Peter Fassev 2006-09-08 13:42:28 UTC
This is actually a Micorosft problem, and it is du to the implementation of the 
MS Client, which requests some information against the root "/", regardles of 
the resource and the real root of WebDAV. To solve this problem, I am using a 
simple Filter to filter the MS WebDAV requests:

/**
 * The webdav interceptor blocks some FrontPage requests and determinate the 
encoding of the underlying request
 *
 */
public class WebdavInterceptor implements Filter {

    public static final String MICROSOFT_PROTOCOL_AGENT = 
        "Microsoft Data Access Internet Publishing Provider Protocol Discovery";

    /** Creates a new instance of LoginInterceptor */
    public WebdavInterceptor()
    {
    }

    public void init(javax.servlet.FilterConfig filterConfig) throws 
javax.servlet.ServletException
    {
    }

    public void destroy()
    {
    }

    /** Filter some invalid calls from the Microsoft WebDAV clients (Windows 
2000, Windows XP and Office 2003) */
    public void doFilter(ServletRequest servletRequest, ServletResponse 
servletResponse, 
        FilterChain filterChain) throws IOException, ServletException
    {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String path = request.getServletPath();
        if (path != null) {
            if (path.endsWith("/index.jsp")) {
                // a very strange microsoft webdav handling... (because of the 
front page extensions!)
                // Microsoft (protocol discoverer) is asking the root of the 
server
                // whether it can handles a WebDAV, so we have to catch it 
here. Unfortunately we can't
                // redirect the root URL ("/") to a servlet, because we will 
intercept any other
                // path handling...
                String agent = request.getHeader("user-agent");
                if (MICROSOFT_PROTOCOL_AGENT.equals(agent)) {
                    HttpServletResponse response = (HttpServletResponse)
servletResponse;
                    response.addHeader("DAV", "1,2");

                    response.addHeader("Allow", "OPTIONS, TRACE, PROPFIND");
                    response.addHeader("MS-AUTHOR-VIA", "DAV");
                    return;
                }
            }
            // block, front page and m$ office extensions requests...
            if (path.startsWith("/_vti") || path.startsWith("/MSOffice")) {
                ((HttpServletResponse)servletResponse).setStatus
(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
        }

        request.setCharacterEncoding(WebdavServlet.getEnconding(request));
        filterChain.doFilter(servletRequest, servletResponse);
    }

}

Please note, that the root "/" is mapped to "/index.jsp", this is the standard 
welcome file whithin my container. Thus the filter is mapped to:
  <filter-mapping>
    <filter-name>webdavFilter</filter-name>
    <url-pattern>*.jsp</url-pattern>
  </filter-mapping>

and also to the WebDAV Servlet:
  <filter-mapping>
    <filter-name>webdavFilter</filter-name>
    <servlet-name>webdav</servlet-name>
  </filter-mapping>

The WebDAV servket should map additionaly the following paths:
  <servlet-mapping>
    <servlet-name>webdav</servlet-name>
    <url-pattern>/_vti_inf.html</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>webdav</servlet-name>
    <url-pattern>/_vti_bin/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>webdav</servlet-name>
    <url-pattern>/MSOffice/*</url-pattern>
  </servlet-mapping>


I hope, this helps you. My WebDAV root is for instance "/webdav/*", and it 
works within a container togther with a web application.

Regards
Peter
Comment 2 Yoav Shapira 2006-12-26 06:22:49 UTC
Peter, thank you for posting the filter: I like it as a nice, clean solution to
an unfortunate (but non-Tomcat) problem.   Andrew, thank you for posting your
suggestions: the second one is good and as you've noted, it's already been
implemented.  I hope Peter's filter works well for you.  I'm going to link to it
from the actual WebdavServlet class JavaDoc as well.