تطوير مكونات إضافية مخصصة

أنت الآن بصدد الاطّلاع على مستندات Apigee Edge.
انتقِل إلى مستندات Apigee X.
info

الإصدار 3.0.x من Edge Microgateway

الجمهور

هذا الموضوع مخصّص للمطوّرين الذين يريدون توسيع ميزات Edge Microgateway من خلال كتابة مكوّنات إضافية مخصّصة. إذا كنت تريد كتابة إضافة جديدة، يجب أن تكون لديك خبرة في JavaScript وNode.js.

ما هو مكوّن Edge Microgateway الإضافي المخصّص؟

المكوّن الإضافي هو وحدة Node.js تضيف وظائف إلى Edge Microgateway. تتّبع وحدات المكوّنات الإضافية نمطًا متسقًا ويتم تخزينها في موقع جغرافي معروف لـ Edge Microgateway، ما يتيح رصدها وتشغيلها تلقائيًا. يتم توفير العديد من المكوّنات الإضافية المحدّدة مسبقًا عند تثبيت Edge Microgateway. وتشمل هذه الإضافات المصادقة، ومنع الارتفاع المفاجئ في عدد الطلبات، والحصة، والإحصاءات. يتم وصف هذه المكوّنات الإضافية الحالية في مقالة استخدام المكوّنات الإضافية.

يمكنك إضافة ميزات وإمكانات جديدة إلى البوابة المصغّرة من خلال كتابة مكوّنات إضافية مخصّصة. بشكلٍ تلقائي، يكون Edge Microgateway في الأساس وكيل تمرير آمن يمرّر الطلبات والردود بدون تغيير إلى الخدمات المستهدَفة ومنها. باستخدام المكوّنات الإضافية المخصّصة، يمكنك التفاعل آليًا مع الطلبات والردود التي تمر عبر البوابة المصغّرة.

مكان وضع رمز البرنامج المساعد المخصّص

يتم تضمين مجلد للمكوّنات الإضافية المخصّصة كجزء من عملية تثبيت Edge Microgateway هنا:

[prefix]/lib/node_modules/edgemicro/node_modules/microgateway-plugins

حيث [prefix] هو دليل البادئة npm كما هو موضّح في "مكان تثبيت Edge Microgateway" ضمن تثبيت Edge Microgateway.

يمكنك تغيير دليل المكوّنات الإضافية التلقائي هذا. اطّلِع على أماكن العثور على المكوّنات الإضافية.

مراجعة المكوّنات الإضافية المحدّدة مسبقًا

قبل محاولة تطوير إضافة خاصة بك، من المفيد التأكّد من أنّ أيًا من الإضافات المحدّدة مسبقًا لا تستوفي متطلباتك. تتوفّر هذه المكوّنات الإضافية في:

[prefix]/lib/node_modules/edgemicro/node_modules/microgateway-plugins

حيث [prefix] هو دليل البادئة npm. راجِع أيضًا "مكان تثبيت Edge Microgateway" في تثبيت Edge Microgateway.

للحصول على التفاصيل، يمكنك أيضًا الاطّلاع على المكوّنات الإضافية المحدّدة مسبقًا والمضمّنة في Edge Microgateway.

كتابة مكوّن إضافي بسيط

في هذا القسم، سنشرح الخطوات المطلوبة لإنشاء إضافة بسيطة. تستبدل هذه الإضافة بيانات الاستجابة (مهما كانت) بالسلسلة "Hello, World!‎" وتعرضها في نافذة الأوامر.

  1. إذا كان Edge Microgateway قيد التشغيل، أوقِفه الآن:
    edgemicro stop
  2. cd إلى دليل المكوّنات الإضافية المخصّصة:

    cd [prefix]/lib/node_modules/edgemicro/plugins

    حيث [prefix] هو دليل البادئة npm كما هو موضّح في "مكان تثبيت Edge Microgateway" في تثبيت Edge Microgateway.

  3. أنشئ مشروع مكوّن إضافي جديدًا باسم response-override وأضِف cd إليه:
    mkdir response-override && cd response-override
  4. إنشاء مشروع Node.js جديد:
    npm init
    اضغط على Return عدة مرات لقبول الإعدادات التلقائية.
  5. استخدِم محرِّر نصوص لإنشاء ملف جديد باسم index.js.
  6. انسخ الرمز التالي في index.js، واحفظ الملف.
    'use strict';
    var debug = require('debug')
    
    module.exports.init = function(config, logger, stats) {
    
      return {
       
        ondata_response: function(req, res, data, next) {
          debug('***** plugin ondata_response');
          next(null, null);
        },
        
        onend_response: function(req, res, data, next) {
          debug('***** plugin onend_response');
          next(null, "Hello, World!\n\n");
        }
      };
    }
  7. بعد إنشاء مكوّن إضافي، عليك إضافته إلى إعدادات Edge Microgateway. افتح الملف $HOME/.edgemicro/[org]-[env]-config.yaml، حيث يمثّل org وenv اسمَي مؤسسة Edge وبيئتها.
  8. أضِف المكوّن الإضافي response-override إلى العنصر plugins:sequence كما هو موضّح أدناه.
          ...
          
          plugins:
            dir: ../plugins
            sequence:
              - oauth
              - response-override
              
          ...
  9. أعِد تشغيل Edge Microgateway.
  10. إرسال طلب إلى واجهة برمجة تطبيقات من خلال Edge Microgateway (يفترض طلب البيانات من واجهة برمجة التطبيقات هذا أنّك أعددت الإعداد نفسه كما هو موضّح في البرنامج التعليمي مع أمان مفتاح واجهة برمجة التطبيقات، كما هو موضّح في إعداد Edge Microgateway وضبطه:
    curl -H 'x-api-key: uAM4gBSb6YoMvTHfx5lXJizYIpr5Jd' http://localhost:8000/hello/echo
    Hello, World!

بنية المكوّن الإضافي

يوضّح نموذج المكوّن الإضافي التالي في Edge Microgateway النمط الذي يجب اتّباعه عند تطوير المكوّنات الإضافية الخاصة بك. يمكنك العثور على الرمز المصدر للبرنامج الإضافي النموذجي الذي تمت مناقشته في هذا القسم في plugins/header-uppercase/index.js.

  • المكوّنات الإضافية هي وحدات NPM عادية تتضمّن package.json وindex.js في المجلد الجذر.
  • يجب أن يصدّر المكوّن الإضافي الدالة init()‎.
  • تتلقّى الدالة init() ثلاث وسيطات: config وlogger وstats. يتم توضيح هذه الوسيطات في وسيطات الدالة init() الخاصة بـ Plugin.
  • تعرض الدالة init() عنصرًا يتضمّن معالِجات دوال مُسمّاة يتم استدعاؤها عند وقوع أحداث معيّنة خلال مدة صلاحية الطلب.

دوال معالجة الأحداث

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

معالِجات أحداث مسار الطلب

يُطلق على هذه الدوال اسم أحداث الطلبات في Edge Microgateway.

  • onrequest
  • ondata_request
  • onend_request
  • onclose_request
  • onerror_request

onrequest الوظيفة

يتم استدعاؤه في بداية طلب العميل. يتم تشغيل هذه الدالة عندما تتلقّى Edge Microgateway البايت الأول من الطلب. تتيح لك هذه الدالة الوصول إلى عناوين الطلبات وعنوان URL ومعلَمات طلب البحث وطريقة HTTP. إذا استدعيت الدالة next بعد ذلك باستخدام وسيطة أولى ذات قيمة صحيحة (مثل مثيل من Error)، سيتوقف معالجة الطلب ولن يتم بدء طلب مستهدف.

مثال:

onrequest: function(req, res, next) {
      debug('plugin onrequest');
      req.headers['x-foo-request-start'] = Date.now();
      next();
    }

ondata_request الوظيفة

يتم استدعاؤها عند تلقّي جزء من البيانات من العميل. تمرِّر هذه السمة بيانات الطلب إلى المكوّن الإضافي التالي في تسلسل المكوّنات الإضافية. يتم إرسال القيمة التي تم عرضها من المكوّن الإضافي الأخير في التسلسل إلى الهدف. في ما يلي حالة استخدام نموذجية لتحويل بيانات الطلب قبل إرسالها إلى الوجهة.

مثال:

ondata_request: function(req, res, data, next) {
      debug('plugin ondata_request ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    }

onend_request الوظيفة

يتم استدعاؤه عند تلقّي جميع بيانات الطلب من العميل.

مثال:

onend_request: function(req, res, data, next) {
      debug('plugin onend_request');
      next(null, data);
    }

دالة onclose_request

تشير إلى أنّ اتصال العميل قد تم إغلاقه. يمكنك استخدام هذه الدالة في الحالات التي يكون فيها اتصال العميل غير موثوق به. يتم استدعاؤه عند إغلاق اتصال المقبس بالعميل.

مثال:

onclose_request: function(req, res, next) {
      debug('plugin onclose_request');
      next();
    }

دالة onerror_request

يتم استدعاء هذه الطريقة في حال حدوث خطأ أثناء تلقّي طلب العميل.

مثال:

onerror_request: function(req, res, err, next) {
      debug('plugin onerror_request ' + err);
      next();
    }

معالِجات أحداث مسار الردود

يتم استدعاء هذه الدوال عند وقوع أحداث الاستجابة في Edge Microgateway.

  • onresponse
  • ondata_response
  • onend_response
  • onclose_response
  • onerror_response

دالة onresponse

يتم استدعاؤها في بداية الردّ المستهدف. يتم تشغيل هذه الدالة عندما يتلقّى Edge Microgateway أول بايت من الرد. تتيح لك هذه الدالة الوصول إلى عناوين الرد ورمز الحالة.

مثال:

onresponse: function(req, res, next) {      
    debug('plugin onresponse');     
    res.setHeader('x-foo-response-time', Date.now() - req.headers['x-foo-request-start'])    
    next();    
}


دالة ondata_response

يتم استدعاء هذه الطريقة عند تلقّي جزء من البيانات من الهدف.

مثال:

ondata_response: function(req, res, data, next) {
      debug('plugin ondata_response ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    }


دالة onend_response

يتم استدعاؤه عند استلام جميع بيانات الرد من الهدف.

مثال:

onend_response: function(req, res, data, next) {
      debug('plugin onend_response');
      next(null, data);
    }

دالة onclose_response

تشير إلى أنّ الاتصال المستهدَف قد تم إغلاقه. يمكنك استخدام هذه الدالة في الحالات التي يكون فيها الاتصال بالهدف غير موثوق به. يتم استدعاؤه عند إغلاق اتصال المقبس بالجهاز المستهدف.

مثال:

onclose_response: function(req, res, next) {
      debug('plugin onclose_response');
      next();
    }


دالة onerror_response

يتم استدعاء هذه الدالة في حال حدوث خطأ أثناء تلقّي الردّ المستهدَف.

مثال:

onerror_response: function(req, res, err, next) {
      debug('plugin onerror_response ' + err);
      next();
    }

معلومات يجب معرفتها عن دوال معالجة أحداث المكوّن الإضافي

يتم استدعاء دوال معالجة أحداث المكوّن الإضافي استجابةً لأحداث معيّنة تحدث أثناء معالجة Edge Microgateway لطلب بيانات من واجهة برمجة التطبيقات.

  • يجب أن يستدعي كل معالج من معالجات الدالة init() (مثل ondata_request وondata_response وغيرهما) دالة ردّ الاتصال next() عند الانتهاء من المعالجة. إذا لم تستدعِ الدالة next()، ستتوقف المعالجة وسيتعذّر إكمال الطلب.
  • يمكن أن تكون الوسيطة الأولى للدالة next() عبارة عن خطأ يؤدي إلى إنهاء معالجة الطلب.
  • يجب أن تستدعي معالجات ondata_ وonend_ الدالة next() مع وسيط ثانٍ يحتوي على البيانات التي سيتم تمريرها إلى الهدف أو العميل. يمكن أن تكون قيمة هذا الوسيط فارغة إذا كان المكوّن الإضافي يخزّن مؤقتًا ولم تتوفّر لديه بيانات كافية لتحويلها في الوقت الحالي.
  • يُرجى العِلم أنّه يتم استخدام نسخة واحدة من المكوّن الإضافي للتعامل مع جميع الطلبات والردود. إذا أرادت إضافة الاحتفاظ بحالة كل طلب بين عمليات الاستدعاء، يمكنها حفظ هذه الحالة في سمة تمت إضافتها إلى عنصر الطلب (req) المقدَّم، والذي تكون مدة بقائه هي مدة طلب البيانات من واجهة برمجة التطبيقات.
  • احرص على رصد جميع الأخطاء واستدعاء next() مع الخطأ. سيؤدي عدم استدعاء next() إلى تعليق طلب البيانات من واجهة برمجة التطبيقات.
  • يجب الحرص على عدم حدوث تسرّب للذاكرة لأنّ ذلك قد يؤثر في الأداء العام لـ Edge Microgateway وقد يؤدي إلى تعطّله إذا نفدت الذاكرة.
  • يجب الحرص على اتّباع نموذج Node.js من خلال عدم تنفيذ مهام تتطلّب قدرًا كبيرًا من الحوسبة في سلسلة التعليمات الرئيسية، لأنّ ذلك قد يؤثّر سلبًا في أداء Edge Microgateway.

لمحة عن الدالة init() الخاصة بالمكوّن الإضافي

يوضّح هذا القسم الوسيطات التي يتم تمريرها إلى الدالة init(): config وlogger وstats.

config

كائن إعداد تم الحصول عليه بعد دمج ملف إعداد Edge Microgateway مع المعلومات التي يتم تنزيلها من Apigee Edge، مثل المنتجات والحصص. يمكنك العثور على إعدادات خاصة بالمكوّن الإضافي في هذا العنصر: config.<plugin-name>.

لإضافة مَعلمة إعداد باسم param بقيمة foo إلى إضافة باسم response-override، ضَع ما يلي في ملف default.yaml:

response-override:
    param: foo

بعد ذلك، يمكنك الوصول إلى المَعلمة في رمز المكوّن الإضافي، على النحو التالي:

// Called when response data is received
    ondata_response: function(req, res, data, next) {
      debug('***** plugin ondata_response');
      debug('***** plugin ondata_response: config.param: ' + config.param);
      next(null, data);
    },

في هذه الحالة، سيظهر foo في ناتج تصحيح الأخطاء للمكوّن الإضافي:

Sun, 13 Dec 2015 21:25:08 GMT plugin:response-override ***** plugin ondata_response: config.param: foo

أداة التسجيل

مسجّل النظام يصدّر برنامج التسجيل المستخدَم حاليًا هذه الدوال، حيث يمكن أن يكون العنصر سلسلة أو طلب HTTP أو استجابة HTTP أو مثيلاً للخطأ.

  • info(object, message)
  • warn(object, message)
  • error(object, message)

الإحصاءات

كائن يتضمّن عدد الطلبات والاستجابات والأخطاء والإحصاءات المجمّعة الأخرى ذات الصلة بالطلبات والاستجابات التي تمرّ عبر مثيل بوابة مصغّرة.

  • treqErrors: عدد طلبات الاستهداف التي تتضمّن أخطاء.
  • treqErrors: عدد الردود المستهدَفة التي تتضمّن أخطاء
  • statusCodes: عنصر يحتوي على عدد رموز الاستجابة:
{
  1: number of target responses with 1xx response codes
  2: number of target responses with 2xx response codes
  3: number of target responses with 3xx response codes
  4: number of target responses with 4xx response codes
  5: number of target responses with 5xx response codes
  }
  
  • الطلبات: إجمالي عدد الطلبات.
  • الردود: إجمالي عدد الردود
  • عمليات الربط: عدد عمليات الربط النشطة بالمصدر المستهدف.

لمحة عن الدالة next()

يجب أن تستدعي جميع طرق المكوّن الإضافي next() لمواصلة معالجة الطريقة التالية في السلسلة (وإلا ستتوقف عملية المكوّن الإضافي). في دورة حياة الطلب، تكون الدالة الأولى التي يتم استدعاؤها هي onrequest(). أما الدالة التالية التي يتم استدعاؤها فهي الدالة ondata_request()، ولكن لا يتم استدعاء ondata_request إلا إذا كان الطلب يتضمّن بيانات، كما هو الحال مثلاً في طلب POST. ستكون الطريقة التالية التي يتم استدعاؤها هي onend_request()، ويتم استدعاؤها عند اكتمال معالجة الطلب. لا يتم استدعاء دوال onerror_* إلا في حال حدوث خطأ، وهي تتيح لك معالجة الأخطاء باستخدام رمز مخصّص إذا أردت ذلك.

لنفترض أنّه يتم إرسال البيانات في الطلب، ويتم استدعاء ondata_request(). لاحظ أنّ الدالة تستدعي next() مع مَعلمتَين:

next(null, data);

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

تنقل المَعلمة الثانية بيانات الطلب إلى الدالة التالية في السلسلة. في حال عدم إجراء أي معالجة إضافية، يتم تمرير بيانات الطلب بدون تغيير إلى هدف واجهة برمجة التطبيقات. ومع ذلك، لديك فرصة لتعديل بيانات الطلب ضمن هذه الطريقة، وتمرير الطلب المعدَّل إلى الهدف. على سبيل المثال، إذا كانت بيانات الطلب بتنسيق XML وكان الهدف يتوقّع JSON، يمكنك إضافة رمز إلى طريقة ondata_request() يغيّر (أ) نوع المحتوى لعنوان الطلب إلى application/json ويحوّل بيانات الطلب إلى JSON بأي وسيلة تريدها (على سبيل المثال، يمكنك استخدام محوّل xml2json Node.js الذي تم الحصول عليه من NPM).

إليك كيف قد يبدو ذلك:

ondata_request: function(req, res, data, next) {
  debug('****** plugin ondata_request');
  var translated_data = parser.toJson(data);
  next(null, translated_data);
},

في هذه الحالة، يتم تحويل بيانات الطلب (التي يُفترض أنّها بتنسيق XML) إلى JSON، ويتم تمرير البيانات المحوَّلة عبر next() إلى الدالة التالية في سلسلة الطلبات، قبل تمريرها إلى الخلفية المستهدَفة.

يُرجى العِلم أنّه يمكنك إضافة عبارة تصحيح أخطاء أخرى لعرض البيانات المحوّلة لأغراض تصحيح الأخطاء. على سبيل المثال:

ondata_request: function(req, res, data, next) {
  debug('****** plugin ondata_request');
  var translated_data = parser.toJson(data);
  debug('****** plugin ondata_response: translated_json: ' + translated_json);
  next(null, translated_data);
},

لمحة عن ترتيب تنفيذ معالج المكوّن الإضافي

إذا كنت تكتب مكوّنات إضافية لـ Edge Microgateway، عليك فهم ترتيب تنفيذ معالجات أحداث المكوّنات الإضافية.

النقطة المهمة التي يجب تذكُّرها هي أنّه عند تحديد تسلسل مكوّن إضافي في ملف إعداد Edge Microgateway، يتم تنفيذ معالجات الطلبات بترتيب تصاعدي، بينما يتم تنفيذ معالجات الردود بترتيب تنازلي.

تم تصميم المثال التالي لمساعدتك في فهم تسلسل التنفيذ هذا.

1. إنشاء ثلاث إضافات بسيطة

ضع في اعتبارك المكوّن الإضافي التالي. كل ما يفعله هو طباعة نتائج وحدة التحكّم عند استدعاء معالجات الأحداث الخاصة به:

plugins/plugin-1/index.js

module.exports.init = function(config, logger, stats) {

  return {

    onrequest: function(req, res, next) {
      console.log('plugin-1: onrequest');
      next();
    },

    onend_request: function(req, res, data, next) {
      console.log('plugin-1: onend_request');
      next(null, data);
    },

    ondata_response: function(req, res, data, next) {
      console.log('plugin-1: ondata_response ' + data.length);
      next(null, data);
    },

    onend_response: function(req, res, data, next) {
      console.log('plugin-1: onend_response');
      next(null, data);
    }
  };
}

الآن، فكِّر في إنشاء مكوّنَين إضافيَّين، plugin-2 وplugin-3، باستخدام الرمز البرمجي نفسه (باستثناء تغيير عبارات console.log() إلى plugin-2 وplugin-3 على التوالي).

2. مراجعة رمز المكوّن الإضافي

إنّ وظائف الإضافة التي يتم تصديرها في <microgateway-root-dir>/plugins/plugin-1/index.js هي معالجات أحداث يتم تنفيذها في أوقات محدّدة أثناء معالجة الطلبات والردود. على سبيل المثال، onrequest ينفّذ البايت الأول من عناوين الطلبات التي تم تلقّيها. بينما يتم تنفيذ onend_response بعد تلقّي آخر بايت من بيانات الرد.

ألقِ نظرة على معالج ondata_response، ويتم استدعاؤه كلما تم تلقّي جزء من بيانات الرد. من المهم معرفة أنّ بيانات الردود لا يتم تلقّيها بالضرورة دفعة واحدة. بدلاً من ذلك، قد يتم تلقّي البيانات في أجزاء ذات طول عشوائي.

3- إضافة المكوّنات الإضافية إلى تسلسل المكوّنات الإضافية

بالاستمرار في هذا المثال، سنضيف المكوّنات الإضافية إلى تسلسل المكوّنات الإضافية في ملف إعداد Edge Microgateway (~./edgemicro/config.yaml) على النحو التالي. ويجب الالتزام بهذا الترتيب. تحدّد هذه السمة ترتيب تنفيذ معالجات المكوّن الإضافي.

  plugins:
    dir: ../plugins
    sequence:
      - plugin-1
      - plugin-2
      - plugin-3
  

4. فحص نتائج تصحيح الأخطاء

لنلقِ نظرة الآن على الناتج الذي سيتم إنتاجه عند استدعاء هذه المكوّنات الإضافية. في ما يلي بعض النقاط المهمة التي يجب ملاحظتها:

  • يحدّد تسلسل المكوّنات الإضافية في ملف إعداد Edge Microgateway (~./edgemicro/config.yaml) ترتيب استدعاء معالجات الأحداث.
  • يتم استدعاء معالجات الطلبات بترتيب تصاعدي (الترتيب الذي تظهر به في تسلسل المكوّنات الإضافية، أي 1 و2 و3).
  • يتم استدعاء معالِجات الردود بترتيب تنازلي: 3 و2 و1.
  • يتم استدعاء معالج ondata_response مرة واحدة لكل جزء من البيانات التي تصل. في هذا المثال (النتائج معروضة أدناه)، يتم تلقّي جزأين.

في ما يلي نموذج لإخراج تصحيح الأخطاء تم إنشاؤه عند استخدام هذه المكوّنات الإضافية الثلاثة وإرسال طلب من خلال Edge Microgateway. ما عليك سوى ملاحظة ترتيب استدعاء المعالِجات:

  plugin-1: onrequest
  plugin-2: onrequest
  plugin-3: onrequest

  plugin-1: onend_request
  plugin-2: onend_request
  plugin-3: onend_request

  plugin-3: ondata_response 931
  plugin-2: ondata_response 931
  plugin-1: ondata_response 931

  plugin-3: ondata_response 1808
  plugin-3: onend_response

  plugin-2: ondata_response 1808
  plugin-2: onend_response

  plugin-1: ondata_response 1808
  plugin-1: onend_response

ملخّص

من المهم جدًا فهم ترتيب استدعاء معالجات المكوّنات الإضافية عند محاولة تنفيذ وظائف مكوّنات إضافية مخصّصة، مثل تجميع بيانات الطلبات أو الردود وتحويلها.

تذكَّر فقط أنّ معالجات الطلبات يتم تنفيذها بالترتيب الذي تم تحديد المكوّنات الإضافية به في ملف إعداد Edge Microgateway، وأنّ معالجات الردود يتم تنفيذها بالترتيب المعاكس.

لمحة عن استخدام المتغيّرات العامة في المكوّنات الإضافية

يتم إرسال كل طلب إلى Edge Microgateway إلى مثيل المكوّن الإضافي نفسه، وبالتالي، سيؤدي طلب ثانٍ من عميل آخر إلى الكتابة فوق حالة الطلب الأول. الطريقة الآمنة الوحيدة لحفظ حالة المكوّن الإضافي هي تخزين الحالة في سمة ضمن عنصر الطلب أو الاستجابة (الذي يقتصر عمره على عمر الطلب).

إعادة كتابة عناوين URL المستهدَفة في المكوّنات الإضافية

تمت الإضافة في: الإصدار 2.3.3

يمكنك تجاهل عنوان URL التلقائي المستهدَف في إضافة بشكلٍ ديناميكي عن طريق تعديل المتغيّرات التالية في رمز الإضافة: req.targetHostname وreq.targetPath.

تمت الإضافة في: الإصدار 2.4.x

يمكنك أيضًا تجاهل منفذ نقطة النهاية المستهدَفة والاختيار بين HTTP وHTTPS. عدِّل المتغيّرين req.targetPort وreq.targetSecure في رمز المكوّن الإضافي. لاختيار HTTPS، اضبط req.targetSecure على true، ولبروتوكول HTTP، اضبطه على false. إذا ضبطت req.targetSecure على "صحيح"، يُرجى الاطّلاع على سلسلة المناقشة هذه للحصول على مزيد من المعلومات.

تمت إضافة نموذج مكوّن إضافي باسم eurekaclient إلى Edge Microgateway. يوضّح هذا المكوّن الإضافي كيفية استخدام المتغيّرَين req.targetPort وreq.targetSecure، كما يوضّح كيفية إجراء Edge Microgateway لعملية بحث ديناميكية عن نقطة نهاية باستخدام Eureka كفهرس لنقاط نهاية الخدمة.


المكوّنات الإضافية النموذجية

يتم توفير هذه المكوّنات الإضافية مع عملية تثبيت Edge Microgateway. يمكنك العثور عليها في عملية تثبيت Edge Microgateway هنا:

[prefix]/lib/node_modules/edgemicro/plugins

حيث [prefix] هو دليل البادئة npm كما هو موضّح في "مكان تثبيت Edge Microgateway" ضمن تثبيت Edge Microgateway.

accumulate-request

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

module.exports.init = function(config, logger, stats) {

  function accumulate(req, data) {

    if (!req._chunks) req._chunks = [];
    req._chunks.push(data);

  }

  return {

    ondata_request: function(req, res, data, next) {

      if (data && data.length > 0) accumulate(req, data);

      next(null, null);

    },


    onend_request: function(req, res, data, next) {

      if (data && data.length > 0) accumulate(req, data);

      var content = null;

      if (req._chunks && req._chunks.length) {

        content = Buffer.concat(req._chunks);

      }

      delete req._chunks;

      next(null, content);

    }

  };

}

accumulate-response

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

module.exports.init = function(config, logger, stats) {

  function accumulate(res, data) {
    if (!res._chunks) res._chunks = [];
    res._chunks.push(data);
  }

  return {

    ondata_response: function(req, res, data, next) {
      if (data && data.length > 0) accumulate(res, data);
      next(null, null);
    },

    onend_response: function(req, res, data, next) {
      if (data && data.length > 0) accumulate(res, data);
      var content = Buffer.concat(res._chunks);
      delete res._chunks;
      next(null, content);
    }

  };

}

مكوّن header-uppercase الإضافي

تتضمّن توزيعات Edge Microgateway مكوّنًا إضافيًا نموذجيًا باسم <microgateway-root-dir>/plugins/header-uppercase. يتضمّن النموذج تعليقات تصف كل معالج من معالجات الدوال. ينفّذ هذا النموذج بعض عمليات تحويل البيانات البسيطة للرد المستهدف، ويضيف عناوين مخصّصة إلى طلب العميل والرد المستهدف.

إليك الرمز المصدر الخاص بـ <microgateway-root-dir>/plugins/header-uppercase/index.js:

'use strict';

var debug = require('debug')('plugin:header-uppercase');

// required
module.exports.init = function(config, logger, stats) {

  var counter = 0;

  return {

    // indicates start of client request
    // request headers, url, query params, method should be available at this time
    // request processing stops (and a target request is not initiated) if
    // next is called with a truthy first argument (an instance of Error, for example)
    onrequest: function(req, res, next) {
      debug('plugin onrequest');
      req.headers['x-foo-request-id'] = counter++;
      req.headers['x-foo-request-start'] = Date.now();
      next();
    },

    // indicates start of target response
    // response headers and status code should be available at this time
    onresponse: function(req, res, next) {
      debug('plugin onresponse');
      res.setHeader('x-foo-response-id', req.headers['x-foo-request-id']);
      res.setHeader('x-foo-response-time', Date.now() - req.headers['x-foo-request-start']);
      next();
    },

    // chunk of request body data received from client
    // should return (potentially) transformed data for next plugin in chain
    // the returned value from the last plugin in the chain is written to the target
    ondata_request: function(req, res, data, next) {
      debug('plugin ondata_request ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    },

    // chunk of response body data received from target
    // should return (potentially) transformed data for next plugin in chain
    // the returned value from the last plugin in the chain is written to the client
    ondata_response: function(req, res, data, next) {
      debug('plugin ondata_response ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    },

    // indicates end of client request
    onend_request: function(req, res, data, next) {
      debug('plugin onend_request');
      next(null, data);
    },

    // indicates end of target response
    onend_response: function(req, res, data, next) {
      debug('plugin onend_response');
      next(null, data);
    },

    // error receiving client request
    onerror_request: function(req, res, err, next) {
      debug('plugin onerror_request ' + err);
      next();
    },

    // error receiving target response
    onerror_response: function(req, res, err, next) {
      debug('plugin onerror_response ' + err);
      next();
    },

    // indicates client connection closed
    onclose_request: function(req, res, next) {
      debug('plugin onclose_request');
      next();
    },

    // indicates target connection closed
    onclose_response: function(req, res, next) {
      debug('plugin onclose_response');
      next();
    }

  };

}

transform-uppercase

هذه إضافة عامة للتحويل يمكنك تعديلها لإجراء أي نوع من التحويلات التي تريدها. يحوّل هذا المثال ببساطة بيانات الاستجابة والطلب إلى أحرف كبيرة.

 */
module.exports.init = function(config, logger, stats) {

  // perform content transformation here
  // the result of the transformation must be another Buffer
  function transform(data) {
    return new Buffer(data.toString().toUpperCase());
  }

  return {

    ondata_response: function(req, res, data, next) {
      // transform each chunk as it is received
      next(null, data ? transform(data) : null);
    },

    onend_response: function(req, res, data, next) {
      // transform accumulated data, if any
      next(null, data ? transform(data) : null);
    },

    ondata_request: function(req, res, data, next) {
      // transform each chunk as it is received
      next(null, data ? transform(data) : null);
    },

    onend_request: function(req, res, data, next) {
      // transform accumulated data, if any
      next(null, data ? transform(data) : null);
    }

  };

}