พัฒนาปลั๊กอินที่กำหนดเอง

คุณกำลังดูเอกสารประกอบของ Apigee Edge
ไปที่เอกสารประกอบของ Apigee X
ข้อมูล

Edge Microgateway เวอร์ชัน 3.2.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. เพิ่มปลั๊กอิน response-override ลงในองค์ประกอบ plugins:sequence ดังที่แสดงด้านล่าง
          ...
          
          plugins:
            dir: ../plugins
            sequence:
              - oauth
              - response-override
              
          ...
    
  9. รีสตาร์ท Edge Microgateway
  10. เรียก API ผ่าน Edge Microgateway (การเรียก 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() มีอาร์กิวเมนต์ 3 ตัว ได้แก่ config, logger และ stats เราได้อธิบายอาร์กิวเมนต์เหล่านี้ไว้ในอาร์กิวเมนต์ของฟังก์ชัน init() ปลั๊กอิน
  • init() จะแสดงผลออบเจ็กต์ที่มีตัวแฮนเดิลฟังก์ชันที่มีชื่อซึ่งมีการเรียกใช้เมื่อเกิดเหตุการณ์บางอย่างขึ้นตลอดอายุของคําขอ

ฟังก์ชันเครื่องจัดการเหตุการณ์

ปลั๊กอินต้องใช้ฟังก์ชันเครื่องจัดการเหตุการณ์เหล่านี้บางส่วนหรือทั้งหมด การใช้งานฟังก์ชันเหล่านี้ขึ้นอยู่กับคุณ คุณจะใช้ฟังก์ชันที่กำหนดหรือไม่ก็ได้ และปลั๊กอินทั่วไปจะใช้ฟังก์ชันเหล่านี้อย่างน้อย 1 ชุด

เครื่องจัดการกิจกรรมโฟลว์การส่งคำขอ

ระบบจะเรียกใช้ฟังก์ชันเหล่านี้เมื่อมีเหตุการณ์คำขอใน Edge Microgateway

  • onrequest
  • ondata_request
  • onend_request
  • onclose_request
  • onerror_request

onrequest function

เรียกใช้เมื่อเริ่มต้นคำขอของไคลเอ็นต์ ฟังก์ชันนี้จะเริ่มทำงานเมื่อ Edge Microgateway ได้รับไบต์แรกของคำขอ ฟังก์ชันนี้จะช่วยให้คุณเข้าถึงส่วนหัวของคำขอ, URL, พารามิเตอร์การค้นหา และเมธอด HTTP ได้ หากเรียกใช้ครั้งถัดไปด้วยอาร์กิวเมนต์แรกที่เชื่อถือได้ (เช่น อินสแตนซ์ของข้อผิดพลาด) ระบบจะหยุดการประมวลผลคำขอ และระบบจะไม่เริ่มคำขอเป้าหมาย

ตัวอย่าง

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

ondata_request function

มีการเรียกใช้เมื่อได้รับกลุ่มข้อมูลจากไคลเอ็นต์ บัตรผ่านจะขอข้อมูลไปยังปลั๊กอินถัดไปในลำดับปลั๊กอิน ระบบจะส่งค่าที่แสดงผลจากปลั๊กอินล่าสุดในลำดับไปยังเป้าหมาย กรณีการใช้งานทั่วไปที่แสดงด้านล่างคือการแปลงข้อมูลคำขอก่อนที่จะส่งไปยังเป้าหมาย

ตัวอย่าง

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

onend_request function

เรียกใช้เมื่อได้รับข้อมูลคำขอทั้งหมดจากไคลเอ็นต์แล้ว

ตัวอย่าง

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() ด้วยอาร์กิวเมนต์ที่ 2 ที่มีข้อมูลเพื่อส่งไปยังเป้าหมายหรือไคลเอ็นต์ อาร์กิวเมนต์นี้อาจเป็นค่าว่างหากปลั๊กอินกำลังบัฟเฟอร์และมีข้อมูลไม่เพียงพอที่จะเปลี่ยนรูปแบบในขณะนี้
  • โปรดทราบว่าจะมีการใช้ปลั๊กอินเพียงอินสแตนซ์เดียวเพื่อให้บริการคำขอและการตอบกลับทั้งหมด หากปลั๊กอินต้องการคงสถานะต่อคำขอไว้ระหว่างการเรียก ปลั๊กอินจะบันทึกสถานะนั้นในพร็อพเพอร์ตี้ที่เพิ่มลงในออบเจ็กต์ request ที่ให้ไว้ (req) ซึ่งมีอายุการใช้งานเป็นระยะเวลาของการเรียก API
  • ตรวจสอบให้ระวังข้อผิดพลาดทั้งหมดและเรียก next() ที่มีข้อผิดพลาด หากเรียกใช้ next() ไม่สำเร็จ จะทำให้การเรียก API ค้าง
  • โปรดระวังไม่ให้หน่วยความจำรั่วไหล เนื่องจากอาจส่งผลต่อประสิทธิภาพโดยรวมของ Edge Microgateway และก่อให้เกิดข้อขัดข้องหากหน่วยความจำเต็ม
  • โปรดใช้โมเดล Node.js อย่างระมัดระวังโดยอย่าทำงานที่ต้องอาศัยการประมวลผลในเทรดหลัก เนื่องจากอาจส่งผลเสียต่อประสิทธิภาพของ Edge Microgateway ได้

เกี่ยวกับฟังก์ชัน init() ของปลั๊กอิน

ส่วนนี้จะอธิบายถึงอาร์กิวเมนต์ที่ส่งผ่านไปยังฟังก์ชัน init(): config, logger และ stats

การกำหนดค่า

ข้อมูลการกำหนดค่าที่ได้จากการรวมไฟล์การกำหนดค่า Edge Microgateway กับข้อมูลที่ดาวน์โหลดจาก Apigee Edge จะอยู่ในออบเจ็กต์ชื่อ config

หากต้องการเพิ่มพารามิเตอร์การกำหนดค่าที่ชื่อ 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

คุณจะเข้าถึงการกำหนดค่าไมโครเกตเวย์ที่ผสานรวมและข้อมูล 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 หรืออินสแตนซ์ข้อผิดพลาด

  • 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
  }
  
  • requests - จำนวนคำขอทั้งหมด
  • responses - จำนวนคำตอบทั้งหมด
  • connections - จำนวนการเชื่อมต่อเป้าหมายที่ใช้งานอยู่

เกี่ยวกับฟังก์ชัน next()

เมธอดปลั๊กอินทั้งหมดต้องเรียกใช้ next() เพื่อประมวลผลเมธอดถัดไปในชุดต่อ (ไม่เช่นนั้น กระบวนการปลั๊กอินจะค้าง) ในวงจรของคำขอ วิธีแรกที่จะเรียกใช้คือ onrequest() เมธอดถัดไปที่จะเรียกใช้คือเมธอด ondata_request() แต่ ondata_request จะเรียกใช้ก็ต่อเมื่อคำขอมีข้อมูล เช่น ในกรณีของคำขอ POST เท่านั้น วิธีการถัดไปคือ onend_request() ซึ่งจะเรียกใช้เมื่อการประมวลผลคำขอเสร็จสมบูรณ์ ระบบจะเรียกใช้ฟังก์ชัน onerror_* ในกรณีที่เกิดข้อผิดพลาดเท่านั้น และให้คุณจัดการข้อผิดพลาดด้วยโค้ดที่กำหนดเองได้หากต้องการ

สมมติว่ามีการส่งข้อมูลไปแล้วในคำขอและมีการเรียก ondata_request() โปรดสังเกตว่าฟังก์ชันเรียกใช้ next() ที่มีพารามิเตอร์ 2 รายการ ดังนี้

next(null, data);

ตามแบบแผน ระบบจะใช้พารามิเตอร์แรกเพื่อสื่อสารข้อมูลข้อผิดพลาด ซึ่งคุณสามารถจัดการในฟังก์ชันถัดไปในเชนได้ หากตั้งค่าเป็น null ซึ่งเป็นอาร์กิวเมนต์ที่ไม่ถูกต้อง เราจะบอกว่าไม่มีข้อผิดพลาด และการดำเนินการตามคำขอควรดำเนินการตามปกติ หากอาร์กิวเมนต์นี้เชื่อถือได้ (เช่น ออบเจ็กต์ข้อผิดพลาด) การประมวลผลคำขอจะหยุดและส่งคำขอไปยังเป้าหมาย

พารามิเตอร์ที่สองจะส่งข้อมูลคำขอไปยังฟังก์ชันถัดไปในเชน หากคุณไม่ประมวลผลเพิ่มเติม ระบบจะส่งข้อมูลคำขอโดยไม่เปลี่ยนแปลงไปยังเป้าหมายของ API อย่างไรก็ตาม คุณมีโอกาสแก้ไขข้อมูลคำขอภายในเมธอดนี้และส่งต่อคำขอที่แก้ไขไปยังเป้าหมายได้ เช่น หากข้อมูลคำขอคือ XML และเป้าหมายต้องการ JSON คุณก็เพิ่มโค้ดลงในเมธอด ondata_request() ที่ (ก) เปลี่ยน Content-Type ของส่วนหัวของคำขอเป็น 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. สร้างปลั๊กอินง่ายๆ 3 รายการ

ลองพิจารณาปลั๊กอินต่อไปนี้ สิ่งที่ต้องทำคือเอาต์พุตของคอนโซลการพิมพ์เมื่อมีการเรียกใช้เครื่องจัดการเหตุการณ์

ปลั๊กอิน/ปลั๊กอิน-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);
    }
  };
}

ตอนนี้ลองสร้างปลั๊กอินอีก 2 รายการคือ 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 1 ครั้งสำหรับข้อมูลแต่ละกลุ่มที่เข้ามา ในตัวอย่างนี้ (เอาต์พุตที่แสดงด้านล่าง) จะได้รับข้อมูล 2 ส่วน

ตัวอย่างเอาต์พุตของการแก้ไขข้อบกพร่องที่สร้างเมื่อใช้ปลั๊กอินทั้ง 3 ตัวนี้และมีการส่งคำขอผ่าน 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 จะถูกส่งไปยังอินสแตนซ์เดียวกันของปลั๊กอิน ดังนั้นสถานะของคำขอที่ 2 จากไคลเอ็นต์อื่นจะเขียนทับคำขอแรก ที่ที่ปลอดภัยแห่งเดียวในการบันทึกสถานะปลั๊กอินคือการจัดเก็บสถานะในพร็อพเพอร์ตี้ในออบเจ็กต์คำขอหรือออบเจ็กต์การตอบกลับ (ซึ่งมีอายุการใช้งานจำกัดตามระยะเวลาของคำขอ)

การเขียน 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 เป็น "จริง" โปรดดูข้อมูลเพิ่มเติมที่ชุดข้อความการสนทนานี้

มีการเพิ่มปลั๊กอินตัวอย่างชื่อ 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

คำขอสะสม

ปลั๊กอินนี้จะรวบรวมชิ้นส่วนข้อมูลจากไคลเอ็นต์ลงในพร็อพเพอร์ตี้อาร์เรย์ที่แนบกับออบเจ็กต์คำขอ เมื่อได้รับข้อมูลคำขอทั้งหมดแล้ว อาร์เรย์จะเชื่อมต่อลงใน "บัฟเฟอร์" ซึ่งจะส่งไปยังปลั๊กอินถัดไปในลำดับ โดยปลั๊กอินนี้ควรเป็นปลั๊กอินแรกในลำดับเพื่อให้ปลั๊กอินต่อๆ มาได้รับข้อมูลคำขอสะสม

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

    }

  };

}

คำตอบสะสม

ปลั๊กอินนี้จะรวบรวมชิ้นส่วนข้อมูลจากเป้าหมายลงในพร็อพเพอร์ตี้อาร์เรย์ที่แนบกับออบเจ็กต์การตอบกลับ เมื่อได้รับข้อมูลตอบกลับทั้งหมดแล้ว อาร์เรย์จะต่อเข้ากับบัฟเฟอร์ซึ่งจะส่งไปยังปลั๊กอินถัดไปในลำดับ เนื่องจากปลั๊กอินนี้ทำงานบนคำตอบ ซึ่งประมวลผลกลับลำดับย้อนกลับ คุณจึงควรจัดตำแหน่งปลั๊กอินนี้เป็นปลั๊กอินสุดท้ายในลำดับ

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

  };

}

ปลั๊กอินส่วนหัวเป็นตัวพิมพ์ใหญ่

การแจกจ่าย 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();
    }

  };

}


เปลี่ยนตัวพิมพ์ใหญ่

ซึ่งเป็นปลั๊กอินการเปลี่ยนรูปแบบทั่วไปที่แก้ไขได้เพื่อเปลี่ยนรูปแบบตามต้องการ ตัวอย่างนี้เป็นการเปลี่ยนข้อมูลการตอบกลับและคำขอเป็นตัวพิมพ์ใหญ่

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

  };

}