เรียก API อื่น ใน handler ยังไงให้ถูกต้อง

เวลาเขียน backend ในภาษา Go เราต้องมีโอกาสไปเรียก API อื่น ผ่าน http แต่จะเขียนยังไงดีหล่ะ ?

ยกตัวอย่างง่าย ๆ เช่น เราทำเว็บที่ไว้เช็คว่าเว็บอื่นล่มรึเปล่า โดนการ get หน้าเว็บออกมา ถ้า status code เป็น 200 แปลว่าไม่ล่ม

เราอาจจะเขียน code ประมาณนี้

https://gist.github.com/acoshift/0733a578c4010bbe9aa6b7b8f08a3164

เราจะเจอกับปัญหา

  1. เว็บรับ connection แต่ไม่ตอบอะไรกลับมา และไม่ปิด connection ควรตอบกลับไปว่าเว็บล่ม
  2. user ปิดหน้า browser ควรยกเลิก request เพราะเราไม่ต้องการผลลัพท์แล้ว

จากปัญหาข้างบน เราสามารถแก้ได้โดย

  1. ตั้ง timeout ตอนส่ง request เช่นถ้าเว็บไม่ตอบกลับมาภายใน 5 วินาที ถือว่าล่ม
  2. ใช้ context จาก request ของ handler เพื่อยกเลิก request ที่ส่งไปเช็คว่าเว็บล่มหรือไม่

เราสามารถแก้ code ใหม่ได้เป็น

https://gist.github.com/acoshift/ba30cd12b75d7b8e26eae43db5a8bda3

สามารถลองเทสได้ง่าย ๆ โดยใช้ curl
$ curl http://localhost:8080/github.com

  1. ปรับ timeout ให้น้อย ๆ แล้วจะได้ Site "..." is down. ออกมา
  2. กด ctrl+c เพื่อยกเลิก request แล้วได้จะ user cancel request ออกมาใน log

สรุป

  • ใช้ context จาก request ที่มาจาก handler เพื่อยกเลิก request ที่ต่อไป API อื่นเมื่อ user cancel request เรา
  • ตั้ง timeout ด้วย อาจจะสร้าง http.Client ใหม่มาใช้เลยก็ได้
One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.