Node-RED - ตอนที่ 1 - ทำ Mock Server ด้วย Node-RED

Node-RED - ทำ Mock Application Server ด้วย Node-RED

ปัญหาในการใช้งาน Application Server ที่ต้องทำงานด้วย

ปัญหาหนึ่งที่เจอในเวลาเขียน Program ก็คือเราต้องการใช้งาน Application Server ที่ต้องทำงานด้วย แต่เราไม่สามารถติดต่อมันได้ด้วยเหตุผลบางอย่างเช่น

  • Application Server นั้นเป็นของ Third party เขาไม่เปิดให้ใช้งานจนกว่าจะทำข้อตกลงทางกฎหมายหรือต้องตกลงบางอย่างให้เสร็จก่อน
  • Application Server นั้นยังพัฒนาไม่เสร็จ จะเสร็จก่อนกำหนดเวลา 1 สัปดาห์
  • การเรียกใช้งานนั้นต้องเสียเงิน ตัวอย่างเช่น เรียกใช้งาน SMS Provider ที่ใช้ส่ง OTP ให้ลูกค้า

ซึ่งด้วยปัญหาต่างๆเหล่านี้มักทำให้เราไม่สามารถเขียนโปรแกรมต่อได้ ทางเหล่าผู้พัฒนาก็เลยแก้ปัญหากันโดยกำหนด Spec ในการใช้งานตัว Application Server ขึ้นมา ตัวอย่างเช่น API ใช้งาน Board Trello , CAT FACE เพื่อบอกให้รู้ว่า Application Server มี Request Response อย่างไร เพื่อให้ทีมพัฒนาที่จะมาใช้ด้วยเนี่ยสามารถไปเขียนโปรแกรมก่อนได้

แต่ปัญหามันไม่ได้ถูกแก้เพราะต่อให้เราได้ spec ของ Application Server ที่เราต้องติดต่อด้วยมาแล้ว แต่เราก็ไม่สามารถยิงไปหามันจริงๆได้ ทำให้เราไม่สามารถ Test code ที่เราเขียนขึ้นมาได้ตาม Flow ตัวอย่างเช่น ถ้าคุณต้องเขียน App ซื้อของออนไลน์ Flow การทำงานตั้งแต่ต้นจนจบคือเลือกสินค้าและจ่ายเงิน ในส่วนการเลือกสินค้านั้นเป็นส่วนของเราที่เขียน แต่ส่วนที่เป็นส่วนจ่ายเงินนั้นเป็นส่วนที่คนอื่นเขียนและเราไม่สามารถใช้งานได้ พอไม่สามารถใช้งานได้เราก็ Test ทั้ง Flow ไม่ได้ วิธีแก้ปัญหาที่ไม่ค่อยดีอย่างหนึ่งที่ Developer จำนวนหนึ่งมักใช้คือทำการแก้ Code ตรงที่เรียกให้มันผ่านตลอดหรือมีผลตามที่อยากได้ ซึ่งมันก็ตอบโจทย์การ Test ให้ผ่านไปได้ แต่ปัญหาคือ Developer มักจะลืมกลับไปแก้ Code ตรงนั้นหลังจาก Test เสร็จ ซึ่งมันก็จะลืมไปจนขึ้น Production และเกิดปัญหานั่นเอง

ดังนั้นมันจะมีดีกว่าไหมถ้าเราสามารถติดต่อไป Application Server ที่เราสามารถกำหนด Response ที่ Application Server นั้นตอบกลับได้อย่างที่เราต้องการ โดยไม่ต้องใส่ Logic ให้เหมือนจริง ซึ่งก็ขอดีใจด้วยครับ ชาว Developer ได้สร้างสิ่งนี้ขึ้นมาให้เราแล้วมากมายมันเรียก Mock Server ซึ่งมีอยู่หลายเจ้า โดยเจ้าที่ผมจะเอามาสอนวิธีใช้คือ Node-RED

จริงๆ Node-RED สามารถทำได้มากกว่า Mock server นะครับ มันสามารถทำได้หลายอย่างมากมีหลายคนเอาไปทำเป็น Server ส่งข้อมูลระหว่าง IOT บางคนก็เอาไปทำเป็น Application Server ที่มีหน้าที่ประมวลผลเลยก็มี

Start Node-RED ด้วย Docker

เนื่องจากเข้าใจว่าคนที่มาอ่านบทความนี้คงจะเป็น Dev QA หรือผู้ที่น่าจะเคยใช้งาน Docker มาแล้วดังนั้นจึงขอใช้ Node-RED ในรูปแบบของ Docker เพราะมันสะดวกไม่ต้อง config อะไรให้ยุ่งยาก

1
2
3
4
5
6
7
8
9
10

# ตัวอย่างการเรียกใช้งาน
# path/to/persistent/data ให้เปลี่ยนเป็น path ที่คุณอยากจะ mount data กับ Node-RED
# โดยถ้าไม่ทำการ map ไว้อะไรที่เคยทำไว้จะหายไปทั้งหมด

# กรณีเป็น Linux ให้ run
sudo chown -R 1000:1000 path/to/persistent/data


docker run -d -p 1880:1880 -v path/to/persistent/data:/data --name mock-server nodered/node-red:latest

โดยเมื่อ Run command ด้านบนเสร็จให้ลองเปิด Browser แล้วใส่ url

1
2
3
4
5
http://[ip ของเครื่องที่ Run docker]:8080

# ตัวอย่างคือ เครื่องที่ Run docker มี IP : 192.168.56.101 url ที่ได้จะเป็น

http://192.168.56.101:1880/

ซึ่งเมื่อเปิดแล้วจะได้ภาพแบบด้านล่าง ถ้าทำไม่ผิด

Mock Server

หากทาง Spec ที่ตกลงกันนั้นมี Request กับ Response ดังต่อไปนี้

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

ENDPOINT : /api/data
HTTP METHOD : POST

# HTTP REQUEST
{
"ref" : "string"
}

# HTTP RESPONSE

{
"transactionId" : "string", // unique string
"ref" : "string" // ref from request
}

โดยเรายิง request ที่มี ref ไปทาง server จะ return response กลับไปให้เป็น transactionId ที่สร้างขึ้นมาโดยต้อง unique และต้องเอา ref ส่งคืนกลับไปให้ใน response ด้วย

ด้วยความต้องการด้านบนเราสามารถใช้ Node-red ทำการ Mock server ได้โดยทำตามขั้นตอนดังต่อไปนี้

สร้างขารับ Http request ด้วย http in

  1. เลือก Component ชื่อ http in แล้วลากลงไปใน Flow
  2. ทำการกำหนด Method เป็น POST
  3. ทำการใส่ค่า URL เป็น /api/data
  4. กดปุ่ม Done

สร้างขาตอบกลับ Http response ด้วย

  1. เลือก Component ชื่อ http_response แล้วลากลงไปใน Flow
  2. ทำการลากเส้นจาก http in ไปหา http_response
  3. กด Deploy ด้านขวาบน

ลองทดสอบ Mock Server

  1. ทำการเปิด PostMan จากนั้นตั้งค่า Method เป็น POST

  2. ทำการใส่ url เป็น http://[ip เครื่องที่ run docker]:1880/api/data (ของผมเป็น VM เครื่อง 192.168.56.101)

  3. จากนั้นเลือก Body เลือกชนิดเป็น raw และเปลี่ยน type ของ raw เป็น Json จากนั้นกำหนด body เป็น

    1
    2
    3
    {
    "ref" : "TX1803"
    }

    จากนั้นกด Send

  4. ดู Response ที่กลับมา

    จาก Response จะเห็นว่า response นั้นเหมือนกับ request เลย เพื่อพิสูจน์ว่าเป็นจริงไหมให้ลองแก้ request เป็นข้อมูลแบบอื่นดู เช่น

    1
    2
    3
    4
    {
    "ref" : "TX1803",
    "testInput" : "TEST NEW INPUT"
    }

    จากนั้นยิงใหม่จะเห็นว่าข้อมูล Response ก็เปลี่ยนไปตาม Request

ทำการแก้ไข Response ที่จะตอบกลับ

  1. ทำลาก component : function ลงไปใน flow

  2. ทำการเพิ่ม

    1
    msg.payload.transactionId = "1234567890123";
  3. กด Done

  4. จากนั้นลากเส้นเชื่อมระหว่าง http in <–> function <–> http response

  1. กด Deploy

  2. จากนั้นเปิด Postman และยิง Request เหมือนในข้อก่อนหน้านี้และดูผลลัพธ์ที่ได้

ซึ่งจะเห็นว่ามีฟิลล์ชื่อ transactionId กลับมาใน response ด้วยซึ่งเป็นค่าเดียวกันกับที่เรา ตั้งค่าไปในขั้นตอนที่ 2 ซึ่งจะเห็นว่าเราสามารถตั้งค่าให้ Response ที่จะตอบกลับไปเป็นอะไรก็ได้ผ่านการ set ค่าที่ field msg.payload โดยถ้าเราเปลี่ยนข้อมูลตรง function เป็น

1
2
3
4
msg.payload = {
"field1" : "12345689",
"name" : "nico"
};

จากนั้น Deploy และใช้ Postman ยิงไปใหม่จะได้ข้อมูลดังภาพ

จะเห็นว่า Response ที่ตอบกลับมานั้นจะมีค่าเหมือนกับที่ set ค่าให้กับ msg.payload

  1. ทำการตั้งค่า function เป็นอย่างด้านล่างและกด Deploy

    1
    2
    3
    // ส่วนนี้จะทำการเอาค่า unix timestamp มาเป็น transactionId ซึ่งถ้าไม่ยิงมาพร้อมกันจริงๆเลขจะไม่ซ้ำกัน
    var transactionId = String(Date.now());
    msg.payload.transactionId = transactionId;

  2. ลองยิงด้วย Postman จะเห็นว่าได้ข้อมูลตาม spec api ที่ต้องการ

Export Flow และ Import Flow

Export Flow

เราสามารถ Export flow ที่เราพึ่งเขียนไปออกมาเก็บไว้ที่เครื่องตัวเองหรือจะส่งต่อให้ Dev คนอื่นๆที่ทำงานร่วมกับเราก็ได้โดยทำตามภาพ โดยไฟล์ที่ได้จะเป็นไฟล์ .json

Import Flow

เราสามารถ Import flow ได้โดยกดเลือก Import ตามภาพ

สรุป

ในตอนนี้เราสามารถทำการ Mock Http Response ให้สามารถตอบกลับตาม spec ที่เราต้องการได้แล้ว ในส่วนของ Component http in , http response ต่างๆนั้นสามารถทำอะไรได้อีกหลายๆอย่าง โดยสามารถไปอ่านเพิ่มได้ที่ https://cookbook.nodered.org/http/#http-endpoints