2009-05-28 20 views
16

我想在我的Rack应用中运行MyMiddleware,但仅限于某些路径。我希望使用Rack::Builder或至少Rack::URLMap,但我不能完全弄清楚。如何仅将Rack中间件用于特定路径?

这是我认为会工作,但不会:

# 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似乎在结束时要求的应用程序;它不会只是将控制权交还给其父母。 (实际的错误是“undefined method 'each' for nil:NilClass”从当机架试图把这一do...end块的端插入app

是否有一个中间件,在那里,采用中间件和一个路径的阵列,并且只有运行它们,如果路径匹配?

+1

愚蠢的错字 - 感谢纠正这一点,AnthonyWJones! ::挂在头: – 2009-05-28 15:04:10

回答

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的URLMap。这将是这个样子:

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

URLMap实际上是pretty simple to grok

+0

[Rack :: URLMap](http://rack.rubyforge.org/doc/Rack/URLMap.html)不幸的是不支持使用正则表达式作为位置(散列键)部分,所以这个答案的第二部分是不正确的。 – 2013-07-10 17:06:32

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'的应用程序。

相关问题