কাস্টম প্লাগ-ইন ডেভেলপ করা

আপনি Apigee Edge ডকুমেন্টেশন দেখছেন।
Apigee X ডকুমেন্টেশন দেখুন।
তথ্য

Edge Microgateway v. 3.3.x

দর্শক

এই বিষয় সেইসব ডেভেলপারদের জন্য যারা কাস্টম প্লাগ-ইন লিখে 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. নিচে দেখানো মতো plugins:sequence এলিমেন্টে response-override প্লাগ-ইন যোগ করুন।
          ...
          
          plugins:
            dir: ../plugins
            sequence:
              - oauth
              - response-override
              
          ...
  9. Edge Microgateway রিস্টার্ট করুন।
  10. Edge Microgateway-এর মাধ্যমে API কল করুন। (এই API কল ধরে নেয় যে আপনি API কী সুরক্ষার সাথে টিউটোরিয়ালের মতো একই কনফিগারেশন সেট-আপ করেছেন, যেমন 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. এইসব আর্গুমেন্ট Plugin init() ফাংশন আর্গুমেন্টে বর্ণনা করা হয়েছে।
  • init() নামযুক্ত ফাংশন হ্যান্ডলার সহ একটি অবজেক্ট রিটার্ন করে যা কোনও অনুরোধের লাইফটাইম চলাকালীন নির্দিষ্ট ইভেন্ট ঘটলে কল করা হয়।

ইভেন্ট হ্যান্ডলার ফাংশন

প্লাগ-ইনকে অবশ্যই এইসব ইভেন্ট হ্যান্ডলার ফাংশনের কিছু বা সবকটি প্রয়োগ করতে হবে। এইসব ফাংশন প্রয়োগ করার দায়িত্ব আপনার। যেকোনও ফাংশন ঐচ্ছিক এবং একটি সাধারণ প্লাগ-ইন এইসব ফাংশনের অন্তত একটি সাবসেট ইমপ্লিমেন্ট করবে।

অনুরোধ ফ্লো ইভেন্ট হ্যান্ডলার

Edge Microgateway-তে এইসব ফাংশনকে অন রিকোয়েস্ট ইভেন্ট বলা হয়।

  • onrequest
  • ondata_request
  • onend_request
  • onclose_request
  • onerror_request

onrequest ফাংশন

ক্লায়েন্টের অনুরোধের শুরুতে কল করা হয়। Edge Microgateway-তে অনুরোধের প্রথম বাইটটি পেলে এই ফাংশনটি ফায়ার হয়। এই ফাংশন আপনাকে অনুরোধ হেডার, URL, কোয়েরি প্যারামিটার ও HTTP মেথড অ্যাক্সেস করার সুবিধা দেয়। আপনি যদি সত্য প্রথম আর্গুমেন্ট (যেমন, 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 কোনও API অনুরোধ প্রসেস করার সময় নির্দিষ্ট ইভেন্ট ঘটলে, তার প্রতিক্রিয়ায় প্লাগ-ইন ইভেন্ট হ্যান্ডলার ফাংশন কল করা হয়।

  • init() ফাংশন হ্যান্ডলারের (ondata_request, ondata_response, ইত্যাদি) প্রত্যেকটিকে প্রসেসিং সম্পূর্ণ হয়ে গেলে next() কলব্যাককে কল করতে হবে। আপনি next() কল না করলে, প্রসেসিং বন্ধ হয়ে যাবে এবং অনুরোধটি হ্যাং হয়ে যাবে।
  • next()-এর প্রথম আর্গুমেন্ট একটি সমস্যা হতে পারে যার ফলে অনুরোধ প্রসেসিং বন্ধ হয়ে যাবে।
  • ondata_ এবং onend_ হ্যান্ডলারকে অবশ্যই next() কল করতে হবে, যার দ্বিতীয় আর্গুমেন্টে টার্গেট বা ক্লায়েন্টকে পাস করার জন্য ডেটা থাকতে হবে। প্লাগ-ইন বাফারিং করলে এবং এই মুহূর্তে ট্রান্সফর্ম করার জন্য পর্যাপ্ত ডেটা না থাকলে এই আর্গুমেন্টটি নাল হতে পারে।
  • মনে রাখবেন, সব অনুরোধ ও উত্তর পরিষেবা দেওয়ার জন্য প্লাগ-ইনের একটি সিঙ্গেল ইনস্ট্যান্স ব্যবহার করা হয়। কলের মধ্যে কোনও প্লাগ-ইন যদি প্রতি-অনুরোধ স্টেট ধরে রাখতে চায়, তাহলে সেটি সাপ্লাই করা অনুরোধ অবজেক্টে (req) যোগ করা প্রপার্টিতে সেই স্টেট সেভ করতে পারে, যার লাইফটাইম হল API কলের সময়সীমা।
  • সব সমস্যা ধরা পড়েছে কিনা তা ভালো করে দেখে নিন এবং সমস্যার সাথে next() কল করুন। next() কল করতে না পারলে API কল আর কাজ করবে না।
  • মেমরি লিক যাতে না হয় সেই ব্যাপারে সতর্ক থাকুন, কারণ এটি Edge Microgateway-এর সামগ্রিক পারফর্ম্যান্সকে প্রভাবিত করতে পারে এবং মেমরি শেষ হয়ে গেলে এটি ক্র্যাশ করতে পারে।
  • Node.js মডেল মেনে চলার ব্যাপারে সতর্ক থাকুন, অর্থাৎ মূল থ্রেডে কম্পিউট-ইনটেনসিভ টাস্ক করবেন না, কারণ এটি Edge Microgateway-এর পারফর্ম্যান্সের উপর বিরূপ প্রভাব ফেলতে পারে।

প্লাগ-ইন init() ফাংশন সম্পর্কে

এই বিভাগে init() ফাংশনে পাস করা আর্গুমেন্টগুলি বর্ণনা করা হয়েছে: config, logger এবং stats.

কনফিগারেশন

Edge Microgateway কনফিগারেশন ফাইলের সাথে Apigee Edge থেকে ডাউনলোড করা ডেটা মার্জ করে পাওয়া কনফিগারেশন ডেটা config নামের একটি অবজেক্টে রাখা হয়।

response-override নামের একটি প্লাগ-ইনে foo ভ্যালু সহ param নামের একটি কনফিগারেশন প্যারামিটার যোগ করতে, 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

আপনি মার্জ করা মাইক্রোগেটওয়ে কনফিগারেশন এবং ডাউনলোড করা Apigee Edge ডেটা চাইল্ড অবজেক্ট config.emgConfigs-এ অ্যাক্সেস করতে পারবেন। যেমন, আপনি এই কনফিগারেশন ডেটা init ফাংশনে নিম্নলিখিত উপায়ে অ্যাক্সেস করতে পারবেন:

module.exports.init = function(config, logger, stats) {
   let emgconfigs = config.emgConfigs;

নিচে এমন ডেটার উদাহরণ দেওয়া হল যা emgConfigs-এ থাকে:

{
    edgemicro:
    {
        port: 8000,
        max_connections: 1000,
        config_change_poll_interval: 600,
        logging:
        {
            level: 'error',
            dir: '/var/tmp',
            stats_log_interval: 60,
            rotate_interval: 24,
            stack_trace: false
        },
        plugins: { sequence: [Array] },
        global: { org: 'Your Org', env: 'test' }
    },
    headers:
    {
        'x-forwarded-for': true,
        'x-forwarded-host': true,
        'x-request-id': true,
        'x-response-time': true,
        via: true
    },
    proxies:
    [    {
                max_connections: 1000,
                name: 'edgemicro_delayed',
                revision: '1',
                proxy_name: 'default',
                base_path: '/edgemicro_delayed',
                target_name: 'default',
                url: 'https://httpbin.org/delay/10',
                timeout: 0
            }
    ],
    product_to_proxy: { EdgeMicroTestProduct: [ 'edgemicro-auth','edgemicro_delayed',] },
    product_to_scopes: {prod4: [ 'Admin', 'Guest', 'Student' ] },
    product_to_api_resource: { EdgeMicroTestProduct: [ '/*' ] },
    _hash: 0,
    keys: { key: 'Your key', secret: 'Your key ' },
    uid: 'Internally generated uuid',
    targets: []
  }

লগার

সিস্টেম লগার। বর্তমানে ব্যবহৃত লগার এই ফাংশনগুলি এক্সপোর্ট করে, যেখানে অবজেক্ট হতে পারে একটি স্ট্রিং, HTTP অনুরোধ, HTTP উত্তর বা একটি Error ইনস্ট্যান্স।

  • info(object, message)
  • warn(object, message)
  • error(object, message)
  • trace(object, message)
  • debug(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(), এটি অনুরোধ প্রসেস করা সম্পূর্ণ হলে কল করা হয়। The onerror_* ফাংশনগুলি শুধুমাত্র কোনও সমস্যা হলে কল করা হয় এবং এগুলি আপনাকে ইচ্ছা হলে কাস্টম কোডের মাধ্যমে সমস্যাগুলি সমাধান করতে দেয়।

ধরা যাক, অনুরোধে ডেটা পাঠানো হয়েছে এবং ondata_request() কল করা হয়েছে। লক্ষ্য করুন যে ফাংশনটি দুটি প্যারামিটার সহ next()-কে কল করে:

next(null, data);

প্রথা অনুযায়ী, প্রথম প্যারামিটারটি ত্রুটি সংক্রান্ত তথ্য জানাতে ব্যবহার করা হয়, যা আপনি পরে চেনের পরবর্তী ফাংশনে হ্যান্ডেল করতে পারবেন। null-এ সেট করে, একটি মিথ্যা আর্গুমেন্ট দিয়ে, আমরা বলছি যে কোনও সমস্যা নেই এবং অনুরোধ প্রসেস করার কাজ স্বাভাবিকভাবে চলতে পারে। এই আর্গুমেন্টটি সত্য হলে (যেমন, কোনও Error অবজেক্ট), তাহলে অনুরোধ প্রসেস করা বন্ধ হয়ে যায় এবং অনুরোধটি টার্গেটে পাঠানো হয়।

দ্বিতীয় প্যারামিটারটি চেনের পরবর্তী ফাংশনে অনুরোধ ডেটা পাস করে। আপনি যদি কোনও অতিরিক্ত প্রসেসিং না করেন, তাহলে অনুরোধ করা ডেটা অপরিবর্তিত অবস্থায় API-এর টার্গেটে পাস করা হয়। তবে, এই পদ্ধতির মধ্যে আপনি অনুরোধের ডেটা পরিবর্তন করতে এবং পরিবর্তিত অনুরোধটি টার্গেটে পাঠাতে পারবেন। যেমন, অনুরোধের ডেটা XML হলে এবং টার্গেট JSON আশা করলে, আপনি ondata_request() পদ্ধতিতে এমন কোড যোগ করতে পারেন যা (ক) অনুরোধের হেডারের Content-Type পরিবর্তন করে application/json করে দেয় এবং আপনি যেভাবে চান সেইভাবে অনুরোধের ডেটা JSON-এ কনভার্ট করে (যেমন, আপনি NPM থেকে পাওয়া Node.js xml2json কনভার্টার ব্যবহার করতে পারেন)।

এটি কেমন দেখতে হতে পারে তা দেখা যাক:

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 কনফিগারেশন ফাইলে আপনি কোনও প্লাগ-ইন সিকোয়েন্স নির্দিষ্ট করলে, রিকোয়েস্ট হ্যান্ডলার উর্ধ্বক্রমিক ক্রমে এক্সিকিউট হয়, অন্যদিকে, রেসপন্স হ্যান্ডলার নিম্নক্রমিক ক্রমে এক্সিকিউট হয়।

এই এক্সিকিউশন সিকোয়েন্স বুঝতে সাহায্য করার জন্য নিম্নলিখিত উদাহরণটি তৈরি করা হয়েছে।

১. তিনটি সহজ প্লাগ-ইন তৈরি করুন

নিম্নলিখিত প্লাগ-ইন বিবেচনা করুন। এর ইভেন্ট হ্যান্ডলার কল করা হলে এটি শুধু কনসোল আউটপুট প্রিন্ট করে: কল করা হয়:

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 হিসেবে পরিবর্তন করুন)।

২. প্লাগ-ইনের কোড পর্যালোচনা করুন

এক্সপোর্ট করা প্লাগ-ইন ফাংশন <microgateway-root-dir>/plugins/plugin-1/index.js হল ইভেন্ট হ্যান্ডলার যা অনুরোধ ও উত্তর প্রসেস করার সময় নির্দিষ্ট সময়ে এক্সিকিউট হয়। যেমন, onrequest অনুরোধ হেডার প্রাপ্তির প্রথম বাইট এক্সিকিউট করে। অন্যদিকে, onend_response উত্তরের ডেটার শেষ বাইট পাওয়ার পরে এক্সিকিউট হয়।

ondata_response হ্যান্ডলারটি দেখুন -- এটি তখনই কল করা হয় যখন কোনও রেসপন্স ডেটার চাঙ্ক পাওয়া যায়। গুরুত্বপূর্ণ বিষয় হল, উত্তর সংক্রান্ত ডেটা যে একসাথে পাওয়া যাবে এমন কোনও কথা নেই। বরং, ডেটা অনির্দিষ্ট দৈর্ঘ্যের চ্যাঙ্ক হিসেবে পাওয়া যেতে পারে।

৩. প্লাগ-ইন সিকোয়েন্সে প্লাগ-ইন যোগ করুন

এই উদাহরণটি চালিয়ে নিয়ে, আমরা Edge Microgateway কনফিগারেশন ফাইলে (~./edgemicro/config.yaml) প্লাগ-ইন সিকোয়েন্সে প্লাগ-ইন যোগ করব, যেমনটি নিচে দেখানো হয়েছে। ক্রম গুরুত্বপূর্ণ। এটি সেই ক্রম নির্ধারণ করে যেটিতে প্লাগ-ইন হ্যান্ডলার এক্সিকিউট করে।

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

৪. ডিবাগ আউটপুট পরীক্ষা করা

এখন, এই প্লাগ-ইনগুলি কল করা হলে যে আউটপুট তৈরি হবে তা দেখে নেওয়া যাক। মনে রাখার মতো কয়েকটি গুরুত্বপূর্ণ বিষয়:

  • Edge Microgateway কনফিগারেশন ফাইলে প্লাগ-ইন সিকোয়েন্স (~./edgemicro/config.yaml) উল্লেখ করে যে কোন ক্রমে ইভেন্ট হ্যান্ডলারকে কল করা হবে।
  • রিকোয়েস্ট হ্যান্ডলারদের ছোট থেকে বড় ক্রমে কল করা হয় (যে ক্রমে সেগুলি প্লাগ-ইন সিকোয়েন্সে দেখা যায় -- ১, ২, ৩)।
  • রেসপন্স হ্যান্ডলারদের উত্ক্রম ক্রমে কল করা হয় -- ৩, ২, ১.
  • আগত ডেটার প্রতিটি চঙ্কের জন্য 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 আবার লেখা

এতে যোগ করা হয়েছে: v2.3.3

আপনার প্লাগ-ইন কোডে এইসব ভেরিয়েবল পরিবর্তন করে, আপনি কোনও প্লাগ-ইনে ডিফল্ট টার্গেট URL ডাইনামিক ওভাররাইড করতে পারবেন: req.targetHostname এবং req.targetPath.

এতে যোগ করা হয়েছে: v2.4.x

এছাড়াও, আপনি টার্গেট এন্ডপয়েন্ট পোর্ট ওভাররাইড করতে এবং HTTP ও HTTPS-এর মধ্যে থেকে একটি বেছে নিতে পারবেন। আপনার প্লাগ-ইন কোডে এইসব ভেরিয়েবল পরিবর্তন করুন: req.targetPort এবং req.targetSecure. HTTPS বেছে নিতে, req.targetSecure-কে true হিসেবে সেট করুন; HTTP-এর জন্য, এটিকে false হিসেবে সেট করুন। আপনি req.targetSecure-কে true হিসেবে সেট করলে, আরও তথ্যের জন্য এই আলোচনা থ্রেড দেখুন।

এখান থেকে সরানো হয়েছে: v3.3.3

Edge Microgateway-এর v.3.3.3 ভার্সন থেকে eurekaclient নামের স্যাম্পেল প্লাগ-ইন সরিয়ে দেওয়া হয়েছে। রিলিজ নোট দেখুন।

এই ফিচার সরিয়ে দেওয়া হলেও Edge মাইক্রোগেটওয়ের মূল কার্যকারিতা বা টার্গেট URL রিরাইট করার ক্ষেত্রে কোনও প্রভাব পড়ে না। আপনি প্লাগ-ইন লেভেলে ডায়নামিক এন্ডপয়েন্ট লুক-আপ কনফিগার করতে এবং req.targetHostname, req.targetPath, req.targetPort ও req.targetSecure-এর মতো টার্গেট ভেরিয়েবল ওভাররাইড করতে পারেন। প্লাগ-ইনে টার্গেট URL আবার লেখা দেখুন।


নমুনা প্লাগ-ইন

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);
    }

  };

}