2010-02-27 3 views
5

Actualmente estoy usando Mongrel para desarrollar un proyecto de aplicación web personalizado.Uso de una expresión regular en el URI de un controlador Mongrel

Me gustaría que Mongrel use un Http Handler definido en base a una expresión regular. Por ejemplo, cada vez que alguien llama a una url como http://test/bla1.js o http://test/bla2.js, se llama al mismo gestor Http para gestionar la solicitud.

Mi código hasta ahora parece un así:

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 

Como se puede ver, estoy tratando de utilizar una expresión regular en lugar de una cadena aquí:

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

pero que no funciona . ¿Alguna solución?

Gracias por eso.

Respuesta

1

Tiene que insertar un nuevo código en la parte de URIClassifier de Mongrel, que de otra manera felizmente ignora los URI de expresiones regulares.

A continuación se muestra una forma de hacer eso:

# 
# 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 

parece funcionar muy bien con Mestizo 1.1.5.

+0

Gracias. Eso es justo lo que necesitaba. – Benjamin

2

En su lugar, debería considerar crear un Rack application. Rack es:

  • el estándar para aplicaciones Web Ruby
  • utilizado internamente por todos los marcos populares Rubí web (Rails, Merb, Sinatra, Camping, Ramaze, ...)
  • mucho más fácil de extender
  • listo para ejecutarse en cualquiera servidor de aplicaciones (mestizo, Webrick, Delgado, Pasajero, ...)

Rack tiene una asignación de URL DSL, Rack::Builder, que le permite asignar diferentes aplicaciones de Rack a prefijos de URL concretos. Normalmente lo guarda como config.ru y lo ejecuta con rackup.

Desafortunadamente, tampoco permite expresiones regulares. Pero debido a la simplicidad de Rack, es realmente fácil escribir una "aplicación" (un lambda, en realidad) que llamará a la aplicación adecuada si la URL coincide con cierta expresión regular.

Basado en su ejemplo, su config.ru puede ser algo como esto:

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 
} 

A continuación, ejecute la aplicación de bastidores en la línea de comandos:

% rackup 

Si ha instalado mestizo, lo hará comenzar en el puerto 9292. ¡Listo!

+0

Gracias por esa respuesta. – Benjamin

Cuestiones relacionadas