2009-05-28 4 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) 

URLMap 실제로 pretty simple to grok입니다.

+0

[Rack :: 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'에 매핑 된 앱과 일치합니다.