سؤال

ما هو رف الوسيطة في روبي ؟ لم أجد أي تفسير منطقي لما تعنيه "الوسيطة".

هل كانت مفيدة؟

المحلول

رف التصميم

رف الوسيطة هو أكثر من "وسيلة لتصفية طلب رد" - انها تنفيذ خط أنابيب تصميم نمط على ملقمات ويب باستخدام رف.

أنها نظيفة جدا يفصل من مختلف مراحل معالجة طلب الانفصال من المخاوف تمثل الهدف الرئيسي من كل مصممة بشكل جيد البرمجيات المنتجات.

على سبيل المثال مع رف يمكنني مراحل منفصلة من خط أنابيب به:

  • المصادقة:عند وصول الطلب ، على المستخدمين تسجيل الدخول في تفاصيل صحيح ؟ كيف يمكنني التحقق من صحة هذه أوث, HTTP المصادقة الأساسية الاسم/كلمة المرور ؟

  • إذن:"هو المستخدم المعتمد لتنفيذ هذه المهمة خاصة?", أيدور القائم على الأمن.

  • التخزين المؤقت:هل تتم معالجة هذا الطلب بالفعل ، هل يمكنني العودة مؤقتا النتيجة ؟

  • الديكور:كيف يمكن تعزيز الطلب المصب تجهيز أفضل ؟

  • أداء و استخدام الرصد:ما احصائيات يمكن أن أحصل عليها من طلب الرد ؟

  • التنفيذ:فعلا التعامل مع طلب تقديم رد.

كونها قادرة على فصل مختلف مراحل (و تشمل اختياريا لهم) هو مساعدة كبيرة في تطوير تنظيما جيدا التطبيقات.

المجتمع

هناك أيضا النظام البيئي النامية في جميع أنحاء رف الوسيطة - يجب أن تكون قادرة على العثور بنيت قبل رف مكونات للقيام بكل الخطوات المذكورة أعلاه وأكثر من ذلك.انظر رف جيثب ويكي قائمة الوسيطة.

ما الوسيطة ؟

الوسيطة هي المروعة المصطلح الذي يشير إلى أي عنصر البرنامج/المكتبة التي تساعد ولكن لا تشارك مباشرة في تنفيذ بعض المهام.الأمثلة الشائعة جدا هي التسجيل والتوثيق وغيرها شيوعا ، الأفقي تجهيز المكونات.هذه تميل إلى أن تكون الأشياء التي يحتاج الجميع عبر تطبيقات متعددة ولكن ليس الكثير من الناس مهتمون (أو ينبغي أن تكون) في بناء أنفسهم.

مزيد من المعلومات

نصائح أخرى

أولا وقبل كل شيء ، رف بالضبط أمرين:

  • مزود الويب واجهة الاتفاقية
  • جوهرة

الرف مزود الويب واجهة

أساسيات جدا من رف بسيط الاتفاقية.كل رف متوافقة مع ويب دائما استدعاء استدعاء الأسلوب على كائن تعطيه وخدمة نتيجة هذا الأسلوب.رف يحدد بالضبط كيف هذا استدعاء الأسلوب يجب أن تبدو ، وما لديه من العودة.هذا الرف.

دعونا إعطائها محاولة بسيطة.سوف تستخدم WEBrick كما رف متوافقة مع ويب ، ولكن أي منهم القيام به.دعونا إنشاء تطبيق ويب بسيط إرجاع سلسلة JSON.لهذا سوف نقوم بإنشاء ملف يسمى config.ru.على config.ru سيتم تلقائيا يسمى من قبل حامل جوهرة قيادة rackup التي سوف ببساطة تشغيل محتويات config.ru في رف متوافقة مع ويب.لذلك دعونا إضافة التالية إلى config.ru ملف:

class JSONServer
  def call(env)
    [200, {"Content-Type" => "application/json"}, ['{ "message" : "Hello!" }']]
  end
end

map '/hello.json' do
  run JSONServer.new
end

لأن الاتفاقية تنص على الخادم لدينا لديه طريقة تسمى الدعوة الذي يقبل بيئة تجزئة بإرجاع صفيف مع شكل [مركز, رؤوس, الجسم] عن خادم لخدمة.دعونا نحاول ذلك ببساطة الاتصال rackup.افتراضي رف متوافقة مع الخادم, وربما WEBrick أو الهجين سوف تبدأ على الفور انتظر طلبات للعمل.

$ rackup
[2012-02-19 22:39:26] INFO  WEBrick 1.3.1
[2012-02-19 22:39:26] INFO  ruby 1.9.3 (2012-01-17) [x86_64-darwin11.2.0]
[2012-02-19 22:39:26] INFO  WEBrick::HTTPServer#start: pid=16121 port=9292

دعونا اختبار الجديد سلمان خادم إما عن طريق الشباك أو زيارة url http://localhost:9292/hello.json وفويلا:

$ curl http://localhost:9292/hello.json
{ message: "Hello!" }

أنه يعمل.كبيرة!هذا هو أساس كل إطار الشبكة ، القضبان أو سيناترا.في مرحلة تنفيذ مكالمة طريقة العمل من خلال كل إطار القانون ، وأخيرا العودة ردا في نموذجي [مركز, رؤوس, الجسم] شكل.

في روبي على القضبان على سبيل المثال رف طلبات يضرب ActionDispatch::Routing.Mapper الدرجة التي تبدو مثل هذا:

module ActionDispatch
  module Routing
    class Mapper
      ...
      def initialize(app, constraints, request)
        @app, @constraints, @request = app, constraints, request
      end

      def matches?(env)
        req = @request.new(env)
        ...
        return true
      end

      def call(env)
        matches?(env) ? @app.call(env) : [ 404, {'X-Cascade' => 'pass'}, [] ]
      end
      ...
  end
end

وذلك أساسا القضبان الشيكات ، تعتمد على الحياة الفطرية التجزئة إذا كان أي مسار المباريات.إذا كان الأمر كذلك فإنه يمر env تجزئة على تطبيق لحساب استجابة, وإلا فإنه يستجيب مباشرة مع 404.لذلك أي الويب الذي هو متوافق مع رف واجهة الاتفاقية ، قادرة على خدمة بالكامل في مهب القضبان التطبيق.

الوسيطة

رف يدعم أيضا إنشاء الطبقات الوسيطة.أنها في الأساس اعتراض طلب ، أن تفعل شيئا مع ذلك تمر عليه.هذا مفيد جدا بالنسبة متعددة المهام.

دعونا نقول أننا نريد إضافة تسجيل إلى سلمان الخادم الذي يقيس أيضا متى طلب يأخذ.يمكننا ببساطة إنشاء الوسيطة المسجل أن يفعل هذا بالضبط:

class RackLogger
  def initialize(app)
    @app = app
  end

  def call(env)
    @start = Time.now
    @status, @headers, @body = @app.call(env)
    @duration = ((Time.now - @start).to_f * 1000).round(2)

    puts "#{env['REQUEST_METHOD']} #{env['REQUEST_PATH']} - Took: #{@duration} ms"
    [@status, @headers, @body]
  end
end

عندما يحصل إنشاؤها ، فإنه يحفظ نفسه نسخة من الفعلية رف التطبيق.في حالتنا هذه مثيل من JSONServer.رف تلقائيا المكالمات المكالمة الأسلوب على الوسيطة وتتوقع مرة أخرى [status, headers, body] مجموعة, مثل JSONServer العوائد.

حتى في هذه الوسيطة ، نقطة البداية ، ثم الفعلية الدعوة إلى JSONServer مع @app.call(env), ثم مسجل النواتج تسجيل دخول وأخيرا ترجع الرد [@status, @headers, @body].

لجعل لدينا القليل rackup.ru استخدام هذه الوسيطة ، إضافة إلى استخدام RackLogger مثل هذا:

class JSONServer
  def call(env)
    [200, {"Content-Type" => "application/json"}, ['{ "message" : "Hello!" }']]
  end
end

class RackLogger
  def initialize(app)
    @app = app
  end

  def call(env)
    @start = Time.now
    @status, @headers, @body = @app.call(env)
    @duration = ((Time.now - @start).to_f * 1000).round(2)

    puts "#{env['REQUEST_METHOD']} #{env['REQUEST_PATH']} - Took: #{@duration} ms"
    [@status, @headers, @body]
  end
end

use RackLogger

map '/hello.json' do
  run JSONServer.new
end   

إعادة تشغيل الملقم وفويلا ، النواتج سجل على كل طلب.رف يتيح لك إضافة عدة middlewares التي تسمى في النظام يتم إضافتها.انها مجرد وسيلة رائعة لإضافة وظائف دون تغيير جوهر رف التطبيق.

رف - Gem

على الرغم من أن رف - في المقام الأول - هو الاتفاقية كما هو الجوهرة التي توفر وظائف كبيرة.أحد منهم ونحن بالفعل المستخدمة لدينا سلمان الخادم ، rackup الأمر.ولكن هناك ما هو أكثر!رف جوهرة يوفر طلبات الكثير من حالات الاستخدام, مثل خدمة الملفات الثابتة أو حتى كل الدلائل.دعونا نرى كيف يمكننا خدمة بسيطة الملف ، على سبيل المثال ملف HTML الأساسي للغاية يقع في htmls/index.html:

<!DOCTYPE HTML>
  <html>
  <head>
    <title>The Index</title>
  </head>

  <body>
    <p>Index Page</p>
  </body>
</html>

ربما تريد أن تخدم هذا الملف من موقع ويب الجذر ، لذلك دعونا إضافة التالية إلى config.ru:

map '/' do
  run Rack::File.new "htmls/index.html"
end

إذا كان لنا زيارة http://localhost:9292 ونحن نرى لدينا ملف html المقدمة تماما.هذا كان سهلا, أليس كذلك ؟

دعونا إضافة كله دليل من ملفات جافا سكريبت عن طريق إنشاء بعض الملفات جافا سكريبت تحت /javascripts و إضافة ما يلي إلى config.ru:

map '/javascripts' do
  run Rack::Directory.new "javascripts"
end

إعادة تشغيل الملقم ثم قم بزيارة http://localhost:9292/javascript و سترى قائمة من جميع ملفات جافا سكريبت يمكنك تضمين الآن مباشرة من أي مكان.

وكان لي مشكلة في فهم الرف نفسي لكمية لا بأس بها من الزمن. فهمت بشكل كامل فقط بعد العمل على جعل هذا مصغرة روبي خادم الويب نفسي. لقد قمت بمشاركة التعلم نظري حول الرف (في شكل قصة) هنا على بلدي بلوق: <لأ href = "http://gauravchande.com/what-is-rack-in-ruby-rails" يختلط = "noreferrer "> http://gauravchande.com/what-is-rack-in-ruby-rails

وردود الفعل هو أكثر من موضع ترحيب.

config.ru الحد الأدنى runnable سبيل المثال

app = Proc.new do |env|
  [
    200,
    {
      'Content-Type' => 'text/plain'
    },
    ["main\n"]
  ]
end

class Middleware
  def initialize(app)
    @app = app
  end

  def call(env)
    @status, @headers, @body = @app.call(env)
    [@status, @headers, @body << "Middleware\n"]
  end
end

use(Middleware)

run(app)

تشغيل rackup وزيارة localhost:9292.الناتج هو:

main
Middleware

لذا فمن الواضح أن Middleware يلتف المكالمات التطبيق الرئيسي.وبالتالي فإنه قادر على ما قبل عملية الطلب ، وبعد عملية الاستجابة بأي شكل من الأشكال.

كما هو موضح في: http://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack , القضبان يستخدم رف middlewares لكثير من الوظائف ، يمكنك إضافة الخاصة جدا مع config.middleware.use الأسرة الأساليب.

ميزة تنفيذ وظائف في الوسيطة هو أنه يمكنك إعادة استخدامها على أي رف الإطار ، وبالتالي الرئيسية روبي منها ، وليس فقط القضبان.

والرف الوسيطة هو وسيلة لتصفية الطلب والاستجابة حيز التطبيق الخاص بك. يجلس عنصر الوسيطة بين العميل والخادم، وتجهيز طلبات الواردة والصادرة الردود، ولكن كان أكثر من واجهة التي يمكن استخدامها لاجراء محادثات مع خادم الويب. انها تستخدم لوحدات المجموعة والنظام، والتي عادة ما تكون الطبقات روبي، وتحديد تبعية بينهما. الرف وحدة الوسيطة يجب فقط: - أن يكون منشئ التي تأخذ التطبيق التالي في كومة كمعلمة - الاستجابة لأسلوب "الدعوة"، التي تأخذ التجزئة البيئة كمعلمة. عودة قيمة من هذه الدعوة هو مجموعة من: رمز الحالة، التجزئة البيئة والجسم استجابة

لقد استعملت رف الوسيطة إلى حل مشاكل الزوجين:

  1. اصطياد سلمان تحليل الأخطاء مع رف مخصص الوسيطة وإعادة تنسيق جيد رسائل خطأ عند تقدم العميل ضبطت سلمان
  2. ضغط المحتوى عبر الرف::Deflater

وأتاحت جميلة أنيقة إصلاحات في كلتا الحالتين.

ما هو الرف ؟

رف يوفر الحد الأدنى من واجهة بين بين مزودات الويب دعم روبي روبي الأطر.

باستخدام رف يمكنك كتابة رف التطبيق.

رف سوف تمر البيئة تجزئة (تجزئة الواردة داخل HTTP طلب من العميل ، تتكون من CGI-مثل رؤوس) على الرف الخاص بك التطبيق التي يمكن أن تستخدم الأشياء الواردة في هذه التجزئة أن يفعل كل ما يريد.

ما هو رف التطبيق ؟

استخدام الرف ، يجب توفير 'التطبيق' - كائن يستجيب #call الطريقة مع البيئة تجزئة كمعلمة (يعرف عادة env). #call يجب إرجاع صفيف من القيم الثلاث:

  • على رمز الحالة (على سبيل المثال '200'),
  • a تجزئة رؤوس,
  • على استجابة الجسم (التي يجب أن تستجيب روبي الأسلوب ، each).

يمكنك كتابة رف التطبيق بإرجاع هذه مجموعة - سوف يتم إرسال مرة أخرى إلى العميل الخاص بك ، رف داخل رد (وهذا سوف يكون في الواقع غير سبيل المثال الطبقة Rack::Response [اضغط للذهاب إلى مستندات]).

بسيط جدا رف التطبيق:

  • gem install rack
  • إنشاء config.ru file - Rack يعرف هذا.

سوف نقوم بإنشاء صغيرة رف التطبيقات التي تقوم بإرجاع استجابة (مثيل Rack::Response) من استجابة الجسم هو مجموعة التي تحتوي على سلسلة: "Hello, World!".

سوف تصل النار الخادم المحلي باستخدام الأمر rackup.

عند زيارة الميناء المعني في المتصفح سوف نرى "مرحبا العالم!" المقدمة في العرض.

#./message_app.rb
class MessageApp
  def call(env)
    [200, {}, ['Hello, World!']]
  end
end

#./config.ru
require_relative './message_app'

run MessageApp.new

اطلاق النار حتى الخادم المحلي مع rackup وزيارة localhost:بريد 9292 و يجب أن نرى 'Hello, World!' المقدمة.

هذا ليس شرحا شاملا ، ولكن أساسا ما يحدث هنا هو أن العميل (المستعرض) بإرسال طلب HTTP إلى الرف ، عبر الخادم المحلي ، و رف instantiates MessageApp ويعمل call, يمر في بيئة التجزئة كمعلمة في الأسلوب ، ( env حجة).

رف يأخذ قيمة الإرجاع (مجموعة) ويستخدم لإنشاء مثيل Rack::Response و يرسل هذا مرة أخرى إلى العميل.يستخدم هذا المتصفح السحر طباعة مرحبا العالم!' على الشاشة.

بالمناسبة, إذا كنت تريد أن ترى ماذا البيئة تجزئة يبدو مجرد وضع puts env تحت def call(env).

الحد الأدنى كما هو ، ما كنت قد كتبت هنا رف التطبيق!

صنع رف تطبيق التفاعل مع البيئة المقبل تجزئة

في رف التطبيق ، ونحن يمكن أن تتفاعل مع env تجزئة (انظر هنا لمزيد من المعلومات حول البيئة التجزئة).

سننفذ القدرة للمستخدم على المدخلات الخاصة بهم سلسلة الاستعلام في URL ، وبالتالي ، فإن هذه السلسلة سيكون حاضرا في طلب HTTP, مغلفة في واحدة من أزواج مفتاح/قيمة البيئة التجزئة.

لدينا رف التطبيق الوصول إلى هذا الاستعلام سلسلة من البيئة التجزئة ثم ترسل مرة أخرى إلى العميل (المستعرض ، في هذه الحالة) عبر الجسم في الاستجابة.

من رف مستندات على البيئة التجزئة:"QUERY_STRING:جزء من طلب عنوان URL التالي ؟ ، إذا كان أي.قد تكون فارغة ، ولكن مطلوب دائما!"

#./message_app.rb
class MessageApp
  def call(env)
    message = env['QUERY_STRING']
    [200, {}, [message]]
  end
end

الآن ، rackup وزيارة localhost:9292?hello (?hello يجري سلسلة الاستعلام) و يجب أن نرى 'مرحبا' المقدمة في العرض.

رف الوسيطة

ونحن سوف:

  • إدراج قطعة من الرف الوسيطة في مصدر الصف: MessageSetter,
  • البيئة التجزئة سوف تصل إلى هذه الدرجة الأولى و سيتم تمريرها في كمعلمة: env,
  • MessageSetter سيتم إدراج 'MESSAGE' المفتاح في env تجزئة القيمة يجري 'Hello, World!' إذا env['QUERY_STRING'] فارغة ، env['QUERY_STRING'] إذا لم يكن كذلك ،
  • وأخيرا ، فإنه سيعود @app.call(env) - @app يجري التطبيق المقبل في كومة': MessageApp.

أولا, من ناحية' الإصدار:

#./middleware/message_setter.rb
class MessageSetter
  def initialize(app)
    @app = app
  end

  def call(env)
    if env['QUERY_STRING'].empty?
      env['MESSAGE'] = 'Hello, World!'
    else
      env['MESSAGE'] = env['QUERY_STRING']
    end
    @app.call(env)
  end
end

#./message_app.rb (same as before)
class MessageApp
  def call(env)
    message = env['QUERY_STRING']
    [200, {}, [message]]
  end
end

#config.ru
require_relative './message_app'
require_relative './middleware/message_setter'

app = Rack::Builder.new do
  use MessageSetter
  run MessageApp.new
end

run app

من رف::باني مستندات ونحن نرى أن Rack::Builder تنفذ صغيرة DSL إلى تكرارا بناء رف التطبيقات.هذا يعني أنه يمكنك بناء كومة ' تتكون من واحد أو أكثر Middlewares و 'أسفل مستوى التطبيق إلى إيفاد.جميع الطلبات التي يمر إلى أسفل مستوى التطبيق سوف تكون أول معالجتها قبل الوسيطة(s).

#use تحدد الوسيطة لاستخدامها في كومة.فإنه يأخذ الوسيطة كحجة.

رف الوسيطة يجب أن:

  • يكون منشئ أن يأخذ التطبيق التالي في كومة كمعلمة.
  • الاستجابة call الأسلوب الذي يأخذ بيئة التجزئة كمعلمة.

في حالتنا, 'الوسيطة' هو MessageSetter, ، 'منشئ' هو MessageSetter هو initialize طريقة القادم تطبيق' في المكدس MessageApp.

حتى هنا ، بسبب ما Rack::Builder لا تحت غطاء محرك السيارة ، app حجة MessageSetter's initialize الطريقة MessageApp.

(الحصول على رأسك حول المذكورة أعلاه قبل الانتقال)

لذلك كل قطعة من الوسيطة أساسا يمر أسفل القائمة بيئة التجزئة إلى التطبيق التالي في السلسلة - حتى يكون لديك الفرصة على التحور أن بيئة التجزئة داخل الوسيطة قبل أن يمر على التطبيق التالي في المكدس.

#run يأخذ حجة هو كائن يستجيب #call وإرجاع رف الاستجابة (مثيل Rack::Response).

الاستنتاجات

باستخدام Rack::Builder يمكنك بناء سلاسل من Middlewares و أي طلب إلى التطبيق الخاص بك سيتم معالجتها من قبل كل الوسيطة بدوره قبل النهاية يتم معالجتها بواسطة قطعة النهائي في المكدس (في حالتنا ، MessageApp).وهذا مفيد للغاية لأنه يفصل بها مختلف مراحل تجهيز الطلبات.حيث فصل من الشواغل', لا يمكن أن يكون أنظف بكثير!

يمكنك بناء على طلب خط أنابيب' تتكون من عدة Middlewares التي تتعامل مع أشياء مثل:

  • المصادقة
  • إذن
  • التخزين المؤقت
  • الديكور
  • أداء و استخدام الرصد
  • التنفيذ (التعامل مع الواقع على طلب تقدم ردا)

(فوق النقاط من إجابة أخرى على هذا الموضوع)

غالبا ما نرى هذا في المهنية سيناترا التطبيقات.سيناترا يستخدم الرف!انظر هنا من أجل تعريف ما سيناترا هو!

وفي ملاحظة أخيرة ، config.ru يمكن أن تكون مكتوبة في القصير اليد نمط إنتاج بالضبط نفس الوظائف (و هذا ما سوف نرى عادة):

require_relative './message_app'
require_relative './middleware/message_setter'

use MessageSetter
run MessageApp.new

وتظهر أكثر صراحة ما MessageApp تفعله هنا هو 'يد طويلة' نسخة صراحة يدل على أن #call يتم إنشاء مثيل جديد من Rack::Response, مع ثلاث حجج.

class MessageApp
  def call(env)
    Rack::Response.new([env['MESSAGE']], 200, {})
  end
end

روابط مفيدة

رف - واجهة ب/ث Web & App Server

رف روبي حزمة الذي يوفر واجهة ملقم ويب للتواصل مع التطبيق.فمن السهل لإضافة المكونات الوسيطة بين خادم الويب التطبيق لتعديل طريقة طلب/الاستجابة يتصرف.الوسيطة مكون يجلس بين العميل والخادم ، تجهيز الطلبات الواردة والصادرة الردود.

في العادي الكلمات ، بل هو في الأساس مجرد مجموعة من المبادئ التوجيهية لكيفية خادم القضبان التطبيق (أو أي الأخرى روبي التطبيق على شبكة الإنترنت) يجب أن نتحدث إلى بعضنا البعض.

استخدام الرف ، توفر "التطبيق":كائن يستجيب استدعاء الأسلوب ، مع البيئة تجزئة كمعلمة ، وإعادة مجموعة مع ثلاثة عناصر:

  • استجابة HTTP رمز
  • تجزئة رؤوس
  • على استجابة الجسم, التي يجب أن تستجيب كل طلب.

لمزيد من التوضيح يمكنك اتباع الروابط أدناه.

1. https://rack.github.io/
2. https://redpanthers.co/rack-middleware/
3. https://blog.engineyard.com/2015/understanding-rack-apps-and-middleware
4. https://guides.rubyonrails.org/rails_on_rack.html#resources

في القضبان ، لدينا config.ru كما رف ملفات, يمكنك تشغيل أي رف الملف مع rackup الأوامر.و المنفذ الافتراضي لهذا 9292.لاختبار هذا ، يمكنك ببساطة تشغيل rackup في القضبان دليل ونرى النتيجة.يمكنك أيضا تعيين المنفذ الذي تريد تشغيله.قم بتشغيل الأمر رف الملف على أي منفذ معين هو

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