about summary refs log tree commit homepage
path: root/lib/mongrel.rb
diff options
context:
space:
mode:
authorevanweaver <evanweaver@19e92222-5c0b-0410-8929-a290d50e31e9>2007-10-26 02:59:15 +0000
committerevanweaver <evanweaver@19e92222-5c0b-0410-8929-a290d50e31e9>2007-10-26 02:59:15 +0000
commitd4ff84b8d3afa45a69c23eb18899194bf7219140 (patch)
tree4a8e4b4e36ea36a8f543bfaaa2e6ec50fa1e94b6 /lib/mongrel.rb
parent4ff4a7d915f01dabcb87125aa89159fcc5d48534 (diff)
downloadunicorn-d4ff84b8d3afa45a69c23eb18899194bf7219140.tar.gz
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@741 19e92222-5c0b-0410-8929-a290d50e31e9
Diffstat (limited to 'lib/mongrel.rb')
-rw-r--r--lib/mongrel.rb96
1 files changed, 22 insertions, 74 deletions
diff --git a/lib/mongrel.rb b/lib/mongrel.rb
index d5ac6f8..f48552b 100644
--- a/lib/mongrel.rb
+++ b/lib/mongrel.rb
@@ -37,88 +37,27 @@ require 'uri'
 module Mongrel
 
   class URIClassifier
-  
-    class RegistrationError < RuntimeError
-    end
-    class UsageError < RuntimeError
-    end
-
     attr_reader :handler_map  
 
     # Returns the URIs that have been registered with this classifier so far.
+    # The URIs returned should not be modified as this will cause a memory leak.
+    # You can use this to inspect the contents of the URIClassifier.
     def uris
       @handler_map.keys
     end
-
-    def initialize
-      @handler_map = {}
-      @matcher = //
-      @root_handler = nil
+    # Simply does an inspect that looks like a Hash inspect.
+    def inspect
+      @handler_map.inspect
     end
-    
-    # Register a handler object at a particular URI. The handler can be whatever
-    # you want, including an array. It's up to you what to do with it.
-    #
-    # Registering a handler is not necessarily threadsafe, so be careful if you go
-    # mucking around once the server is running.
-    def register(uri, handler)
-      raise RegistrationError, "#{uri.inspect} is already registered" if @handler_map[uri]
-      raise RegistrationError, "URI is empty" if !uri or uri.empty?
-      raise RegistrationError, "URI must begin with a \"#{Const::SLASH}\"" unless uri[0..0] == Const::SLASH
-      @handler_map[uri.dup] = handler
-      rebuild
-    end
-    
-    # Unregister a particular URI and its handler.
-    def unregister(uri)
-      handler = @handler_map.delete(uri)
-      raise RegistrationError, "#{uri.inspect} was not registered" unless handler
-      rebuild
-      handler
-    end
-    
-    # Resolve a request URI by finding the best partial match in the registered
-    # handler URIs.
-    def resolve(request_uri)
-      if @root_handler
-        # Optimization for the pathological case of only one handler on "/"; e.g. Rails
-        [Const::SLASH, request_uri, @root_handler]
-      elsif match = @matcher.match(request_uri)
-        uri = match.to_s
-        # A root mounted ("/") handler must resolve such that path info matches the original URI.
-        [uri, (uri == Const::SLASH ? request_uri : match.post_match), @handler_map[uri]]
-      else
-        [nil, nil, nil]
-      end
-    end
-        
-    private
-    
-    def rebuild
-      if @handler_map.size == 1 and @handler_map[Const::SLASH]
-        @root_handler = @handler_map.values.first
-      else
-        @root_handler = nil
-        routes = @handler_map.keys.sort.sort_by do |uri|
-          -uri.length
-        end
-        @matcher = Regexp.new(routes.map do |uri|
-          Regexp.new('^' + Regexp.escape(uri))
-        end.join('|'))
-      end
-    end    
-    
-  end
 
+  end
 
   # Used to stop the HttpServer via Thread.raise.
   class StopServer < Exception; end
 
-
   # Thrown at a thread when it is timed out.
   class TimeoutError < Exception; end
 
-
   # Every standard HTTP code mapped to the appropriate message.  These are
   # used so frequently that they are placed directly in Mongrel for easy
   # access rather than Mongrel::Const.
@@ -839,16 +778,25 @@ module Mongrel
     # found in the prefix of a request then your handler's HttpHandler::process method
     # is called.  See Mongrel::URIClassifier#register for more information.
     #
-    # If you set in_front=true then the passed in handler will be put in the front of the list
-    # for that particular URI. Otherwise it's placed at the end of the list.
+    # If you set in_front=true then the passed in handler will be put in front in the list.
+    # Otherwise it's placed at the end of the list.
     def register(uri, handler, in_front=false)
-      begin
+      script_name, path_info, handlers = @classifier.resolve(uri)
+
+      if not handlers
         @classifier.register(uri, [handler])
-      rescue URIClassifier::RegistrationError
-        handlers = @classifier.resolve(uri)[2]
-        method_name = in_front ? 'unshift' : 'push'
-        handlers.send(method_name, handler)
+      else
+        if path_info.length == 0 or (script_name == Const::SLASH and path_info == Const::SLASH)
+          if in_front
+            handlers.unshift(handler)
+          else
+            handlers << handler
+          end
+        else
+          @classifier.register(uri, [handler])
+        end
       end
+
       handler.listener = self
     end