2009-05-28 9 views
16

मैं अपने रैक ऐप में MyMiddleware चला सकता हूं, लेकिन केवल कुछ पथों के लिए। मैं Rack::Builder या कम से कम Rack::URLMap का उपयोग करने की उम्मीद कर रहा था, लेकिन मुझे यह पता नहीं लगा सकता कि कैसे। एक Regexp साथ, या, बेहतर अभी तकमैं केवल कुछ पथों के लिए रैक मिडलवेयर का उपयोग कैसे करूं?

# 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" से जब रैक एक app में है कि do...end ब्लॉक के अंत चालू करने के लिए प्रयास करता है।)

वहाँ एक मिडलवेयर कि middlewares और एक पथ की एक सरणी लेता है और केवल उन्हें अगर चलाता है पथ मैच?

+1

बेवकूफ टाइपो - इसे ठीक करने के लिए धन्यवाद, एंथनी WJones! :: शर्म में सिर लटका :: –

उत्तर

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 

या, आप URLMap w/o dslness का उपयोग कर सकते हैं। यह कुछ इस तरह दिखेगा:

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

URLMap वास्तव में pretty simple to grok है।

+0

[रैक :: URLMap] (http://rack.rubyforge.org/doc/Rack/URLMap.html) दुर्भाग्यवश नियमित अभिव्यक्तियों का उपयोग स्थान (हैश कुंजी) भाग के रूप में करने का समर्थन नहीं करता है , इसलिए इस उत्तर का दूसरा भाग सही नहीं है। –

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' पर मैप किए गए ऐप से मेल खाता है।