ما هو رف الوسيطة ؟
-
20-09-2019 - |
سؤال
ما هو رف الوسيطة في روبي ؟ لم أجد أي تفسير منطقي لما تعنيه "الوسيطة".
المحلول
رف التصميم
رف الوسيطة هو أكثر من "وسيلة لتصفية طلب رد" - انها تنفيذ خط أنابيب تصميم نمط على ملقمات ويب باستخدام رف.
أنها نظيفة جدا يفصل من مختلف مراحل معالجة طلب الانفصال من المخاوف تمثل الهدف الرئيسي من كل مصممة بشكل جيد البرمجيات المنتجات.
على سبيل المثال مع رف يمكنني مراحل منفصلة من خط أنابيب به:
المصادقة:عند وصول الطلب ، على المستخدمين تسجيل الدخول في تفاصيل صحيح ؟ كيف يمكنني التحقق من صحة هذه أوث, HTTP المصادقة الأساسية الاسم/كلمة المرور ؟
إذن:"هو المستخدم المعتمد لتنفيذ هذه المهمة خاصة?", أيدور القائم على الأمن.
التخزين المؤقت:هل تتم معالجة هذا الطلب بالفعل ، هل يمكنني العودة مؤقتا النتيجة ؟
الديكور:كيف يمكن تعزيز الطلب المصب تجهيز أفضل ؟
أداء و استخدام الرصد:ما احصائيات يمكن أن أحصل عليها من طلب الرد ؟
التنفيذ:فعلا التعامل مع طلب تقديم رد.
كونها قادرة على فصل مختلف مراحل (و تشمل اختياريا لهم) هو مساعدة كبيرة في تطوير تنظيما جيدا التطبيقات.
المجتمع
هناك أيضا النظام البيئي النامية في جميع أنحاء رف الوسيطة - يجب أن تكون قادرة على العثور بنيت قبل رف مكونات للقيام بكل الخطوات المذكورة أعلاه وأكثر من ذلك.انظر رف جيثب ويكي قائمة الوسيطة.
ما الوسيطة ؟
الوسيطة هي المروعة المصطلح الذي يشير إلى أي عنصر البرنامج/المكتبة التي تساعد ولكن لا تشارك مباشرة في تنفيذ بعض المهام.الأمثلة الشائعة جدا هي التسجيل والتوثيق وغيرها شيوعا ، الأفقي تجهيز المكونات.هذه تميل إلى أن تكون الأشياء التي يحتاج الجميع عبر تطبيقات متعددة ولكن ليس الكثير من الناس مهتمون (أو ينبغي أن تكون) في بناء أنفسهم.
مزيد من المعلومات
التعليق عن كونها وسيلة تصفية الطلبات ربما يأتي من RailsCast الحلقة 151:رف الوسيطة يلقي الشاشة.
رف الوسيطة تطور من الرف و هناك مجموعة كبيرة مقدمة في مقدمة رف الوسيطة.
هناك مقدمة الوسيطة في ويكيبيديا هنا.
نصائح أخرى
أولا وقبل كل شيء ، رف بالضبط أمرين:
- مزود الويب واجهة الاتفاقية
- جوهرة
الرف مزود الويب واجهة
أساسيات جدا من رف بسيط الاتفاقية.كل رف متوافقة مع ويب دائما استدعاء استدعاء الأسلوب على كائن تعطيه وخدمة نتيجة هذا الأسلوب.رف يحدد بالضبط كيف هذا استدعاء الأسلوب يجب أن تبدو ، وما لديه من العودة.هذا الرف.
دعونا إعطائها محاولة بسيطة.سوف تستخدم 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
الأسرة الأساليب.
ميزة تنفيذ وظائف في الوسيطة هو أنه يمكنك إعادة استخدامها على أي رف الإطار ، وبالتالي الرئيسية روبي منها ، وليس فقط القضبان.
والرف الوسيطة هو وسيلة لتصفية الطلب والاستجابة حيز التطبيق الخاص بك. يجلس عنصر الوسيطة بين العميل والخادم، وتجهيز طلبات الواردة والصادرة الردود، ولكن كان أكثر من واجهة التي يمكن استخدامها لاجراء محادثات مع خادم الويب. انها تستخدم لوحدات المجموعة والنظام، والتي عادة ما تكون الطبقات روبي، وتحديد تبعية بينهما. الرف وحدة الوسيطة يجب فقط: - أن يكون منشئ التي تأخذ التطبيق التالي في كومة كمعلمة - الاستجابة لأسلوب "الدعوة"، التي تأخذ التجزئة البيئة كمعلمة. عودة قيمة من هذه الدعوة هو مجموعة من: رمز الحالة، التجزئة البيئة والجسم استجابة
لقد استعملت رف الوسيطة إلى حل مشاكل الزوجين:
- اصطياد سلمان تحليل الأخطاء مع رف مخصص الوسيطة وإعادة تنسيق جيد رسائل خطأ عند تقدم العميل ضبطت سلمان
- ضغط المحتوى عبر الرف::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