URL rewriting with WEBrick
WEBrick isn't as fashionable as it once was, but it's still invaluable for development and testing. I recently needed it to handle rewrite rules, and google didn't return anything better than Simon Strandgaard's code.
On that same thread, GOTOU Yuuzou indicated that he wanted to add proper URL rewriting support to HEAD (1.9). It's been two years, but grep -r rewrite webrick says it hasn't happened yet.
Simon's code choked on query arguments, so I extended it as follows:
class WEBrick::HTTPServer alias :__rewrite_old_initialize :initialize alias :__rewrite_old_service :service def initialize(config={}, default=WEBrick::Config::HTTP) __rewrite_old_initialize(config, default) @rewrite_rules = [] end def rewrite(pattern, subst) @logger.info("rewrite rule %s -> %s." % [pattern.inspect, subst]) @rewrite_rules << [pattern, subst] end def service(req, res) olduri = URI.parse(req.path) olduri.query = req.query_string old = olduri.to_s @rewrite_rules.each do |pattern, subst| if pattern =~ old uri = URI.parse(old.gsub(pattern, subst)) req.instance_variable_set("@path", uri.path) req.instance_variable_set("@query_string", uri.query) req.instance_variable_set("@query", nil) # so it gets reparsed @logger.info("Rewrote URL %s -> %s" % [olduri.to_s, uri.to_s]) break end end __rewrite_old_service(req, res) end end
Yes, it doesn't use define_method to redefine the instance methods while keeping the old definitions*1, but it doesn't matter since the above code is sitting in a 50LoC file and there's no danger of it being loaded twice.
Usage
Here's how I'm using it to test my hiki setup locally and rewrite all /hiki/whatever.html requests to /hiki.rb?whatever:
module WEBrick::HTTPServlet FileHandler.add_handler("rb", CGIHandle) end s = HTTPServer.new( :Port => port, :DocumentRoot => dir ) s.mount("/", HTTPServlet::FileHandler, File.join(ENV["HOME"], "public_html"), :FancyIndexing => true) s.rewrite(%r{^/hiki/hiki\.rb$}, '/hiki.rb') s.rewrite(%r{^/hiki/theme/}, '/theme/') s.rewrite(%r{^/hiki/hiki.rb\?(.*)}, '/hiki.rb?\1') s.rewrite(%r{^/hiki/(.*)\.html}, '/hiki.rb?\1') s.rewrite(%r{^/hiki(/?)$}, '/hiki.rb') trap("INT"){ s.shutdown } s.start
Firefox rendering weirdness - hgs (2007-01-16 (Tue) 08:26:24)
When I mouseover the code, the black boxes expand, which should allow me to see the whole line. However, it appears under the menu at the right. Any idea how to make it appear over the "menu" (or list) at the right? With a large font there is code I can't read. Thank you.
mfp 2007-01-16 (Tue) 09:22:58
Typo in the z-index property, should look OK now (works for me with Firefox).
Thanks.
hgs 2007-01-17 (Wed) 03:12:14
That's working for me now. Thank you.
*1 Simon also used alias instead of alias_method, which I much prefer
Keyword(s):[blog] [ruby] [frontpage] [webrick] [url] [rewrite] [subpar]
References: