Frage

Ich mag MyMiddleware läuft in meinem Rack-App haben, aber nur für bestimmte Pfade. Ich hatte gehofft, Rack::Builder zu verwenden oder zumindest Rack::URLMap, aber ich kann nicht ganz herausfinden, wie.

Das ist, was ich dachte funktionieren würde, aber nicht:

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

Oder, noch besser, mit einem Regexp:

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

Aber map scheint eine App am Ende zu verlangen; es fällt zurück nicht nur auf übergeordneten Steuerelement vorbei zurück. (Der tatsächliche Fehler „undefined method 'each' for nil:NilClass“ aus, wenn Gestell versucht das Ende dieses do...end Blockes in eine app einzuschalten.)

Gibt es eine Middleware aus, dass es eine Reihe von Middleware und einem Weg nimmt und läuft sie nur, wenn der Pfad entspricht?

War es hilfreich?

Lösung

Sie können den Pfad MyMiddleware überprüfen und nicht die Steuerung weiter zum nächsten Stück Middleware übergeben, wenn es passt.

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

Oder Sie URLMap w / o der dslness nutzen könnten. Es würde wie folgt aussehen:

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

URLMap ist eigentlich ziemlich einfach grok .

Andere Tipps

Das funktioniert nicht, weil @app nicht im richtigen Umfang existiert:

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

Aber dieser Wille:

# 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 streift das erste Argument die Vorderseite des Wegs zum map ab, damit es nicht endlos recurse. Leider bedeutet dies, dass nach diesem Pfadpräfix abgezogen wird, ist es unwahrscheinlich, dass der Rest des Weges richtig andere Zuordnungen übereinstimmen.

Hier ist ein Beispiel:

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

zu /html/xml Gehen verursacht die folgende in das Protokoll zu gehen:

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

Das heißt, die App abgebildet Streifen des '/html' Präfix '/html' und den Anruf jetzt passt die App '/xml' abgebildet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top