page caching urls with space characters broken in webrick and mongrel

Page caching of urls with spaces in them using WEBrick and Mongrel is
broken in Edge Rails (and Rails 1.1.6, where I started). This is due
to the dispatch flow of control in both servers converting '+' in
requested paths into ' ' chars, whereas the page caching system writes
cache files for URLs with spaces in them out as encoded '+' characters

This issue does *not* occur with lighttpd, as the lighttpd.conf url
rewriting to look for <name>.html does not convert '+' to ' ' when it
looks for the file on the local filesystem to serve up.

I claim that we should fix WEBrick/Mongrel to also not convert '+' to '
' when looking for a file on the local filesystem.

Dissenters or those who know more than I before I go down the
ticket/patch/test path? Also, if I'm incorrect thinking this is the
right place to discuss this pre-ticket let me know.

I only hesitate on the proposed fix as one assumes the culprit line in
webrick_server.rb (detail below) was added for a reason, but it's not
clear to me what specific scenario would have one wanting to serve up a
local file with ' ' in its name via a request specified as '+'. And
putting an actual space in filenames is so declasse.

More detail:

While investigating why using caches_page() to cache urls that have a
space in them encoded as either '+' or '%20' doesn't work (the cache
files are generated but never used, and continually regenerated on page
reload) led me to this line in webrick_server.rb handle_file():

      path.gsub!('+', ' ') # Unescape + since FileHandler doesn't do
so.

Commenting this line out restores page caching to proper functionality,
as the filename is written to disk with '+' (and '%20' is also
normalized to a '+' in the cache file filename), but this code converts
them to an actual space character which then means the cache files are
always incorrectly overlooked.

Similar line in mongrel's handlers.rb can_serve():

      req_path =
File.expand_path(File.join(@path,HttpRequest.unescape(path_info)),
@path)

where unescaping the path turns the '+' into a ' '.

- Walter Korman -- http://www.lemurware.com