كيف يمكنني استخدام الحامل الوسيطة فقط لمسارات معينة؟

StackOverflow https://stackoverflow.com/questions/920719

  •  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'.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top