From 364270615b8e6f1bd5cc8611267137f1a83b8124 Mon Sep 17 00:00:00 2001 From: zedshaw Date: Sun, 18 Jun 2006 04:57:26 +0000 Subject: Additional simple feature for upload progress plugin. New redirect header and configuration option. git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@245 19e92222-5c0b-0410-8929-a290d50e31e9 --- examples/simpletest.rb | 2 ++ lib/mongrel.rb | 33 +++++++++++++++++++++--- lib/mongrel/handlers.rb | 59 +++++++++++++++++++++++++++++++++++++++++-- test/test_redirect_handler.rb | 41 ++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 test/test_redirect_handler.rb diff --git a/examples/simpletest.rb b/examples/simpletest.rb index df1ad56..b82e2c6 100644 --- a/examples/simpletest.rb +++ b/examples/simpletest.rb @@ -40,6 +40,8 @@ config = Mongrel::Configurator.new :host => ARGV[0], :port => ARGV[1] do uri "/files", :handler => Mongrel::DirHandler.new(ARGV[2]) uri "/files", :handler => stats uri "/status", :handler => Mongrel::StatusHandler.new(:stats_filter => stats) + redirect "/redir1", "/" + redirect "/to", /to/, 'w' end trap("INT") { stop } diff --git a/lib/mongrel.rb b/lib/mongrel.rb index 6090708..4432a2e 100644 --- a/lib/mongrel.rb +++ b/lib/mongrel.rb @@ -171,6 +171,7 @@ module Mongrel HTTP_X_FORWARDED_FOR="HTTP_X_FORWARDED_FOR".freeze HTTP_IF_UNMODIFIED_SINCE="HTTP_IF_UNMODIFIED_SINCE".freeze HTTP_IF_NONE_MATCH="HTTP_IF_NONE_MATCH".freeze + REDIRECT = "HTTP/1.1 302 Found\r\nLocation: %s\r\nConnection: close\r\n\r\n".freeze end @@ -534,9 +535,15 @@ module Mongrel params[Const::PATH_INFO] = path_info params[Const::SCRIPT_NAME] = script_name params[Const::REMOTE_ADDR] = params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last + data = data[nparsed ... data.length] || "" + + if handlers[0].request_notify + # this first handler wants to be notified when the process starts + handlers[0].request_begins(params) + end # TODO: Find a faster/better way to carve out the range, preferably without copying. - request = HttpRequest.new(params, data[nparsed ... data.length] || "", client) + request = HttpRequest.new(params, data, client) # in the case of large file uploads the user could close the socket, so skip those requests break if request.body == nil # nil signals from HttpRequest::initialize that the request was aborted @@ -926,6 +933,16 @@ module Mongrel GemPlugin::Manager.instance.create(name, ops) end + # Let's you do redirects easily as described in Mongrel::RedirectHandler. + # You use it inside the configurator like this: + # + # redirect("/test", "/to/there") # simple + # redirect("/to", /t/, 'w') # regexp + # redirect("/hey", /(w+)/) {|match| ...} # block + # + def redirect(from, pattern, replacement = nil, &block) + uri from, :handler => Mongrel::RedirectHandler.new(pattern, replacement, &block) + end # Works like a meta run method which goes through all the # configured listeners. Use the Configurator.join method @@ -968,13 +985,21 @@ module Mongrel # found in Rails applications that are either slow or become unresponsive # after a little while. # - # TODO: Document the optional selections from the what parameter + # You can pass an extra parameter *what* to indicate what you want to + # debug. For example, if you just want to dump rails stuff then do: + # + # debug "/", what = [:rails] + # + # And it will only produce the log/mongrel_debug/rails.log file. + # Available options are: :object, :railes, :files, :threads, :params + # + # NOTE: Use [:files] to get acccesses dumped to stderr like with WEBrick. def debug(location, what = [:object, :rails, :files, :threads, :params]) require 'mongrel/debug' handlers = { - :object => "/handlers/requestlog::access", + :files => "/handlers/requestlog::access", :rails => "/handlers/requestlog::files", - :files => "/handlers/requestlog::objects", + :object => "/handlers/requestlog::objects", :threads => "/handlers/requestlog::threads", :params => "/handlers/requestlog::params" } diff --git a/lib/mongrel/handlers.rb b/lib/mongrel/handlers.rb index d20ca17..509d3e9 100644 --- a/lib/mongrel/handlers.rb +++ b/lib/mongrel/handlers.rb @@ -31,11 +31,19 @@ module Mongrel # should be implemented using the HttpHandlerPlugin mixin. # class HttpHandler - attr_reader :header_only + attr_reader :request_notify attr_accessor :listener + # This will be called by Mongrel on the *first* (index 0) handler *if* it has + # HttpHandler.request_notify set to *true*. You only get the parameters + # for the request, with the idea that you'd "bound" the beginning of the + # request processing and the first call to process. + def request_begins(params) + end + def process(request, response) end + end @@ -45,9 +53,12 @@ module Mongrel # the process method later. module HttpHandlerPlugin attr_reader :options - attr_reader :header_only + attr_reader :request_notify attr_accessor :listener + def request_begins(params) + end + def initialize(options={}) @options = options @header_only = false @@ -398,4 +409,48 @@ module Mongrel end end end + + # This handler allows you to redirect one url to another. + # You can use it like String#gsub, where the string is the REQUEST_URI. + # REQUEST_URI is the full path with GET parameters. + # + # Eg. /test/something?help=true&disclaimer=false + # + # == Examples + # + # h = Mongrel::HttpServer.new('0.0.0.0') + # h.register '/test', Mongrel::RedirectHandler.new('/to/there') # simple + # h.register '/to', Mongrel::RedirectHandler.new(/t/, 'w') # regexp + # # and with a block + # h.register '/hey', Mongrel::RedirectHandler.new(/(\w+)/) { |match| ... } + # + class RedirectHandler < Mongrel::HttpHandler + # You set the rewrite rules when building the object. + # + # pattern => What to look for or replacement if used alone + # + # replacement, block => One of them is used to replace the found text + + def initialize(pattern, replacement = nil, &block) + unless replacement or block + @replacement = pattern + else + @pattern, @replacement, @block = pattern, replacement, block + end + end + + # Process the request and return a redirect response + def process(request, response) + unless @pattern + response.socket.write(Mongrel::Const::REDIRECT % @replacement) + else + if @block + new_path = request.params['REQUEST_URI'].gsub(@pattern, &@block) + else + new_path = request.params['REQUEST_URI'].gsub(@pattern, @replacement) + end + response.socket.write(Mongrel::Const::REDIRECT % new_path) + end + end + end end diff --git a/test/test_redirect_handler.rb b/test/test_redirect_handler.rb new file mode 100644 index 0000000..dfd994a --- /dev/null +++ b/test/test_redirect_handler.rb @@ -0,0 +1,41 @@ +require 'test/unit' +require 'mongrel' +require 'mongrel/redirect_handler' +require 'net/http' +require 'uri' +require 'timeout' + +class TC_RedirectHandler < Test::Unit::TestCase + + def setup + @server = Mongrel::HttpServer.new('0.0.0.0', 9998) + @server.run + @client = Net::HTTP.new('0.0.0.0', 9998) + end + + def teardown + @server.stop + end + + def test_simple_redirect + tester = Mongrel::RedirectHandler.new('/yo') + @server.register("/test", tester) + + sleep(1) + res = @client.request_get('/test') + assert res != nil, "Didn't get a response" + assert_equal ['/yo'], res.get_fields('Location') + end + + def test_rewrite + tester = Mongrel::RedirectHandler.new(/(\w+)/, '+\1+') + @server.register("/test", tester) + + sleep(1) + res = @client.request_get('/test/something') + assert_equal ['/+test+/+something+'], res.get_fields('Location') + end + +end + + -- cgit v1.2.3-24-ge0c7