Question

Je voudrais avoir courir MyMiddleware dans mon application Rack, mais seulement pour certains chemins. J'espérais utiliser Rack::Builder ou au moins Rack::URLMap, mais je ne peux pas tout à fait comprendre comment.

est ce que je pensais travailler, mais n'a pas:

# in my rackup file or Rails environment.rb:
map '/foo' do
  use MyMiddleware, { :some => 'options' }
end

Ou, mieux encore, avec une expression rationnelle:

map /^foo/ do
  use MyMiddleware, { :some => 'options' }
end

Mais map semble exiger une application à la fin; il ne retombera pas sur le contrôle de passage à son parent. (L'erreur réelle est « undefined method 'each' for nil:NilClass » de rack lorsque tente de tourner l'extrémité de ce bloc de do...end dans un app).

Y at-il un middleware là-bas qui prend un tableau de intergiciels et un chemin et ne les exécute si le chemin correspond?

Était-ce utile?

La solution

Vous pourriez avoir MyMiddleware vérifier le chemin et passez pas le contrôle à la prochaine pièce de vaisselle moyenne si elle correspond.

class MyMiddleware
  def initialize app
    @app = app
  end
  def call env
    middlewary_stuff if env['PATH_INFO'] == '/foo'
    @app.call env
  end

  def middlewary_stuff
    #...
  end
end

Ou, vous pouvez utiliser URLMap w / o la dslness. Il ressemblerait à quelque chose comme ceci:

main_app = MainApp.new
Rack::URLMap.new '/'=>main_app, /^(foo|bar)/ => MyMiddleWare.new(main_app)

assez simple à grok .

Autres conseils

Cela ne fonctionne pas parce que @app n'existe pas dans le champ d'application droite:

# in my_app.ru or any Rack::Builder context:
@app = self
map '/foo' do
  use MyMiddleware
  run lambda { |env| @app.call(env) }
end

Mais cette volonté:

# in my_app.ru or any Rack::Builder context:
::MAIN_RACK_APP = self
map '/foo' do
  use MyMiddleware
  run lambda { |env| ::MAIN_RACK_APP.call(env) }
end

Rack::Builder supprime le premier argument de map de la face de la piste, de sorte qu'il n'a pas indéfiniment récursion. Malheureusement, cela signifie que, après ce préfixe de chemin est enlevé, il est peu probable que le reste du chemin sera bien correspondre à d'autres applications.

Voici un exemple:

::MAIN_APP = self
use Rack::ShowExceptions
use Rack::Lint
use Rack::Reloader, 0
use Rack::ContentLength

map '/html' do
  use MyContentTypeSettingMiddleware, 'text/html'
  run lambda { |env| puts 'HTML!'; ::MAIN_APP.call(env) }
end

map '/xml' do
  use MyContentTypeSettingMiddleware, 'application/xml'
  run lambda { |env| puts 'XML!'; ::MAIN_APP.call(env) }
end

map '/' do
  use ContentType, 'text/plain'
  run lambda { |env| [ 200, {}, "<p>Hello!</p>" ] }
end

Aller à /html/xml cause ce qui suit pour aller dans le journal:

HTML!
XML!
127.0.0.1 - - [28/May/2009 17:41:42] "GET /html/xml HTTP/1.1" 200 13 0.3626

C'est, l'application mappée à '/html' bandes du préfixe '/html' et l'appel correspond maintenant à l'application mappée à '/xml'.

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