Question

J'utilise actuellement Mongrel pour développer un projet d'application web personnalisé.

Je voudrais Mongrel d'utiliser un gestionnaire Http défini sur la base d'une expression régulière. Par exemple, chaque fois que quelqu'un appelle une URL comme http: //test/bla1.js ou http:. //test/bla2.js le même gestionnaire Http est appelé à gérer la demande

Mon code si loin ressemble un comme ça:

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

Comme vous pouvez le voir, je suis en train d'utiliser une expression régulière au lieu d'une chaîne ici:

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

mais cela ne fonctionne pas. Toute solution?

Merci pour cela.

Était-ce utile?

La solution

Vous devez injecter un nouveau code dans une partie de la URIClassifier de Mongrel, qui est par ailleurs parfaitement au courant des URIs d'expression régulière.

Voici une façon de faire cela:

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

Semble fonctionner très bien avec Mongrel 1.1.5.

Autres conseils

Vous devriez envisager de créer un application rack à la place. Rack est:

  • standard pour les applications Web Ruby
  • utilisé en interne par tous les cadres web Ruby populaires ( Rails , Merb , Sinatra , Camping , Ramaze , ...)
  • beaucoup plus facile d'étendre
  • prêt à être exécuté sur tout serveur d'applications (Mongrel, Webrick, mince, passager, ...)

rack a un DSL mappage d'URL, rack :: Builder, qui vous permet de cartographier les différentes applications de rack à préfixes d'URL particuliers. Vous enregistrez généralement comme config.ru, et l'exécuter avec rackup.

Malheureusement, il ne permet pas non plus d'expressions régulières. Mais à cause de la simplicité du rack, il est vraiment facile d'écrire une « application » (un lambda, en fait) qui appelle l'application appropriée si l'URL correspond à un certain regex.

Selon votre exemple, votre config.ru peut ressembler à ceci:

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
}

Ensuite, exécutez votre application Rack sur la ligne de commande:

% rackup

Si vous avez installé bâtarde, il sera lancé sur le port 9292. Fait!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top