I have a client tool I've developed against slide 1.0.16 which has been
working well for quite a while now. I needed to integrate Lucene based
search into my project and found that slide 2.0.0 (cvs head) had an
Interceptor API which I could easily leverage for my needs. Here's the
problem:
I am having trouble with the 2.0.0 release in that any files which result in
a different URI when URLEncoded result in 404 errors from the slide server.
I can perform uploads (PUT) without any issues, but when I do a PROPFIND for
example, a 404 results. The problem seems to be in the
commons-httpclient.jar provided with slide in the cvs tree. Using the
TcpTunnelGui provided in the apache soap project, I am able to monitor the
traffic between my client (using commons-httpclient.jar) and the slide
server to isolate the problem. In case anyone isn't familiar with this tool,
it's very handy and I suggest you check it out.
C:\devapps\soap-2_3_1\lib>java -cp soap.jar
org.apache.soap.util.net.TcpTunnelGui 8081 localhost 8080
What seems to be happening is that the commons-httpclient.jar is performing
the URL encoding twice for some, but not all methods. The sample file I am
using has a space in the filename. "Junk File.txt". It appears correctly in
the property store and object tables after an upload completes, but when I
do a webdavResource.propfindMethod(.) it fails. The request generated by
httpclient converts the filename into "Junk%2520File.txt" instead of the
proper "Junk%20File.txt". Here's how that's happening:
"Junk File.txt" --> (encoded once) "Junk%20File.txt" --> (encoded again)
"Junk%2520File.txt"
I have tracked down where these encoding operations are happening and would
appreciate some guidance from any of those of you more versed in the APIs on
how to properly fix this without breaking other things.
The first encoding seems to be happening in the setPath() methods of the
following classes:
org.apache.webdav.lib.methods.GetMethod
org.apache.webdav.lib.methods.HeadMethod
org.apache.webdav.lib.methods.HttpRequestBodyMethodBase ***
org.apache.webdav.lib.methods.MkcolMethod
org.apache.webdav.lib.methods.PutMethod
org.apache.webdav.lib.methods.UnlockMethod
There are several more classes derived from HttpRequestBodyMethodBase which
have the problem based on their extension of a base class with the problem:
org.apache.webdav.lib.methods.AclMethod
org.apache.webdav.lib.methods.AclReportMethod
. and on and on .
The setPath methods in each of these looks something like this:
/**
* Set the path part of my request.
* It is responsibility of the caller to ensure that the path is
* properly encoded (URL safe).
*
* @param path the path to request. The path is expected
* to be NOT URL-encoded
* @param enc the encoding used to encode the path. UTF-8 is the
default.
*/
public void setPath(String path, String enc ) {
if (enc == null) enc = "UTF-8";
super.setPath(URLUtil.URLEncode(path, enc));
}
I have highlighted in RED an apparent disagreement in the documentation on
whether the paths should or should not be encoded at this point. It seems to
me that this should NOT be encoded based on the implementation of the
following method, which ALL these methods eventually use.
HttpMethodBase.generateRequestLine() line 1519
path = (requestPath == null) ? "/" :
URIUtil.encodePath(requestPath);
What is happening here is that the method-specific setPath for most methods
are doing encoding once and it's happening again just before the outgoing
request is generated.
I believe the fix is to remove the URLUtil.URLEncode(path, enc) from each of
the setPath() methods in which it appears. I am going to try this out now
and if it works, I'll submit some patches if it does. In the mean time if
you know that this will break other things, or you know how to fix this
another way, please let me know.
Thanks.
Brian Johnson