2010-02-27 7 views
5

Ich verwende derzeit Mongrel, um ein benutzerdefiniertes Webanwendungsprojekt zu entwickeln.Verwenden eines Regex in der URI eines Mongrel-Handlers

Ich möchte Mongrel einen definierten Http Handler basierend auf einem regulären Ausdruck verwenden. Zum Beispiel wird jedes Mal, wenn jemand eine URL wie http://test/bla1.js oder http://test/bla2.js aufruft, derselbe Http-Handler aufgerufen, um die Anfrage zu verwalten.

Mein Code so weit ein, wie das aussieht:

http_server = Mongrel::Configurator.new :host => config.get("http_host") do 
    listener :port => config.get("http_port") do 

    uri Regexp.escape("/[a-z0-9]+.js"), :handler => BLAH::CustomHandler.new 
    uri '/ui/public', :handler => Mongrel::DirHandler.new("#{$d}/public/") 
    uri '/favicon', :handler => Mongrel::Error404Handler.new('') 

    trap("INT") { stop } 
    run 
    end 
end 

Wie Sie sehen können, ich versuche, einen regulären Ausdruck anstelle einer Zeichenfolge zu verwenden hier:

uri Regexp.escape("/[a-z0-9]+.js"), :handler => BLAH::CustomHandler.new 

aber das funktioniert nicht . Irgendeine Lösungsmöglichkeit?

Danke dafür.

Antwort

1

Sie müssen neuen Code in einen Teil von Mongrels URIClassifier injizieren, der ansonsten die regulären Ausdruck-URIs nicht kennt.

Im Folgenden finden Sie eine Möglichkeit, nur zu tun, dass:

# 
# Must do the following BEFORE Mongrel::Configurator.new 
# Augment some of the key methods in Mongrel::URIClassifier 
# See lib/ruby/gems/XXX/gems/mongrel-1.1.5/lib/mongrel/uri_classifier.rb 
# 
Mongrel::URIClassifier.class_eval <<-EOS, __FILE__, __LINE__ 
    # Save original methods 
    alias_method :register_without_regexp, :register 
    alias_method :unregister_without_regexp, :unregister 
    alias_method :resolve_without_regexp, :resolve 

    def register(uri, handler) 
    if uri.is_a?(Regexp) 
     unless (@regexp_handlers ||= []).any? { |(re,h)| re==uri ? h.concat(handler) : false } 
     @regexp_handlers << [ uri, handler ] 
     end 
    else 
     # Original behaviour 
     register_without_regexp(uri, handler) 
    end 
    end 

    def unregister(uri) 
    if uri.is_a?(Regexp) 
     raise Mongrel::URIClassifier::RegistrationError, "\#{uri.inspect} was not registered" unless (@regexp_handlers ||= []).reject! { |(re,h)| re==uri } 
    else 
     # Original behaviour 
     unregister_without_regexp(uri) 
    end 
    end 

    def resolve(request_uri) 
    # Try original behaviour FIRST 
    result = resolve_without_regexp(request_uri) 
    # If a match is not found with non-regexp URIs, try regexp 
    if result[0].blank? 
     (@regexp_handlers ||= []).any? { |(re,h)| (m = re.match(request_uri)) ? (result = [ m.pre_match + m.to_s, (m.to_s == Mongrel::Const::SLASH ? request_uri : m.post_match), h ]) : false } 
    end 
    result 
    end 
EOS 

http_server = Mongrel::Configurator.new :host => config.get("http_host") do 
    listener :port => config.get("http_port") do 

    # Can pass a regular expression as URI 
    # (URI must be of type Regexp, no escaping please!) 
    # Regular expression can match any part of an URL, start with "^/..." to 
    # anchor match at URI beginning. 
    # The way this is implemented, regexp matches are only evaluated AFTER 
    # all non-regexp matches have failed (mostly for performance reasons.) 
    # Also, for regexp URIs, the :in_front is ignored; adding multiple handlers 
    # to the same URI regexp behaves as if :in_front => false 
    uri /^[a-z0-9]+.js/, :handler => BLAH::CustomHandler.new 

    uri '/ui/public', :handler => Mongrel::DirHandler.new("#{$d}/public/") 
    uri '/favicon', :handler => Mongrel::Error404Handler.new('') 

    trap("INT") { stop } 
    run 
    end 
end 

scheint mit Mischlings 1.1.5 gut zu funktionieren.

+0

Danke. Genau das habe ich gebraucht. – Benjamin

2

Sie sollten stattdessen eine Rack application erstellen. Rack ist:

  • der Standard für Ruby Web-Anwendungen
  • intern von allen gängigen Ruby-Web-Frameworks verwendet (Rails, Merb, Sinatra, Camping, Ramaze, ...)
  • viel einfacher zu erweitern
  • bereit, auf beliebig Anwendungsserver ausgeführt werden (Mongrel, Webrick, Thin, Passagier, ...)

Rack verfügt über eine URL-Zuordnung DSL, Rack::Builder, mit der Sie verschiedene Rack-Anwendungen bestimmten URL-Präfixen zuordnen können. Normalerweise speichern Sie es als config.ru, und führen Sie es mit rackup.

Leider erlaubt es auch keine regulären Ausdrücke. Aber wegen der Einfachheit von Rack ist es wirklich einfach, eine "Anwendung" zu schreiben (eigentlich eine lambda), die die richtige App aufruft, wenn die URL mit einer bestimmten Regex übereinstimmt.

Basierend auf Ihrem Beispiel Ihre config.ru kann wie folgt aussehen:

require "my_custom_rack_app" # Whatever provides your MyCustomRackApp. 

js_handler = MyCustomRackApp.new 

default_handlers = Rack::Builder.new do 
    map "/public" do 
    run Rack::Directory.new("my_dir/public") 
    end 

    # Uncomment this to replace Rack::Builder's 404 handler with your own: 
    # map "/" do 
    # run lambda { |env| 
    #  [404, {"Content-Type" => "text/plain"}, ["My 404 response"]] 
    # } 
    # end 
end 

run lambda { |env| 
    if env["PATH_INFO"] =~ %r{/[a-z0-9]+\.js} 
    js_handler.call(env) 
    else 
    default_handlers.call(env) 
    end 
} 

Als nächstes Ihre Rack-App auf dem Zeilenbefehl:

% rackup 

Wenn Sie Mischlings installiert haben, wird es an Port 9292 gestartet werden. Fertig!

+0

Danke für diese Antwort. – Benjamin

Verwandte Themen