19

Rack アプリで実行したいのMyMiddlewareですが、特定のパスに対してのみです。Rack::Builderまたはを使用したいと思っていましRack::URLMapたが、方法がわかりません。

これは私がうまくいくと思っていたものですが、うまくいきません:

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

または、さらに良いことに、正規表現を使用すると:

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

しかしmap、最後にアプリが必要なようです。コントロールを親に戻すだけではフォールバックしません。(実際のエラーは、Rack がそのブロックundefined method 'each' for nil:NilClassの末尾を に変えようとしたときの " "です。)do...endapp

ミドルウェアの配列とパスを取り、パスが一致する場合にのみそれらを実行するミドルウェアはありますか?

4

2 に答える 2

14

MyMiddleware にパスをチェックさせ、一致する場合はミドルウェアの次の部分に制御を渡さないようにすることができます。

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

または、DSL なしで URLMap を使用することもできます。次のようになります。

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

URLMap は、実際には非常に簡単に理解できます。

于 2009-07-28T16:55:07.973 に答える
10

@appが正しいスコープに存在しないため、これは機能しません。

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

しかし、これは:

# 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最初の引数をmapパスの先頭から取り除くので、無限に再帰することはありません。残念ながら、これは、そのパス プレフィックスが削除された後、パスの残りの部分が他のマッピングと適切に一致する可能性が低いことを意味します。

次に例を示します。

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

に行く/html/xmlと、次のログに移動します。

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

つまり、アプリ'/html'はプレフィックスのストリップにマップされ'/html'、呼び出しは にマップされたアプリと一致するようになりました'/xml'

于 2009-05-28T16:58:45.457 に答える