كيف يمكنني استخدام الحامل الوسيطة فقط لمسارات معينة؟
-
06-09-2019 - |
سؤال
اود الحصول على MyMiddleware
تشغيل في تطبيق رف بلدي، ولكن فقط لبعض المسارات. كنت آمل أن أستخدم Rack::Builder
أو على الأقل Rack::URLMap
, ، لكنني لا أستطيع معرفة كيف.
هذا ما اعتقدت أنه سيعمل، ولكن لا:
# in my rackup file or Rails environment.rb:
map '/foo' do
use MyMiddleware, { :some => 'options' }
end
أو أفضل بعد، مع regexp:
map /^foo/ do
use MyMiddleware, { :some => 'options' }
end
ولكن map
يبدو أن يطلب تطبيقا في النهاية؛ لن تراجع عن السيطرة فقط مرة أخرى إلى الوالد. (الخطأ الفعلي هو "undefined method 'each' for nil:NilClass
"من عندما يحاول الرف تحويل نهاية ذلك do...end
كتلة في app
.)
هل هناك طبيب خارجي يأخذ مجموعة من الأوساد والمسار ويديرها فقط إذا تطابق المسار؟
المحلول
هل يمكن أن يكون لديك 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 هو في الواقع بسيطة جدا ل grok.
نصائح أخرى
هذا لا يعمل بسبب @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'
.