2009-05-28 17 views
16

私はMyMiddlewareを自分のRackアプリで実行したいと思いますが、特定のパスについてのみ実行します。私は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は、最後にアプリを求めているようです;コントロールを親に戻すだけで元に戻りません。 (実際のエラーがあるラックがappにそのdo...endブロックの終わりをオンにしようとしたときから。「undefined method 'each' for nil:NilClass」)

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

+1

愚かなタイプミス - それを修正してくれてありがとう、AnthonyWJones! :: –

答えて

13

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 

または、dslnessのないURLマップを使用できます。

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

URLマップは実際にはpretty simple to grokのようになります。

+0

[Rack :: URLMap](http://rack.rubyforge.org/doc/Rack/URLMap.html)は残念なことに正規表現を場所(ハッシュキー)部分として使用することをサポートしていません、この答えの2番目の部分は正しくありません。 –

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への最初の引数を取り除きそれは無限に繰り返されるわけではありません。残念ながら、これは、パス接頭辞が取り除かれた後、残りのパスが他のマッピングと適切にマッチする可能性は低いことを意味します。ここで

は例です:/html/xmlに行く

::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' '/html'プレフィックスのストリップと呼び出しにマップされている
HTML! 
XML! 
127.0.0.1 - - [28/May/2009 17:41:42] "GET /html/xml HTTP/1.1" 200 13 0.3626 

今すぐ'/xml'にマップされたアプリに一致します。

関連する問題