สร้างเว็บเซิร์ฟเวอร์ HTTP ใน Node.js ด้วย Code ตัวอย่าง

⚡ สรุปอย่างชาญฉลาด

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

  • 🖥️ การสร้างเซิร์ฟเวอร์: http.createServer จะลงทะเบียนฟังก์ชันเรียกกลับ (callback) ที่จะทำงานหนึ่งครั้งต่อคำขอขาเข้าแต่ละคำขอ และรับอ็อบเจ็กต์คำขอและคำตอบ
  • 🔢 สถานะและส่วนหัว: ฟังก์ชัน writeHead จะส่งรหัสสถานะและ Content-Type ก่อนที่จะเขียนเนื้อหาใดๆ ลงใน body
  • 🔌 การผูกพอร์ต: คำสั่ง server.listen จะเชื่อมต่อแอปพลิเคชันเข้ากับพอร์ต โดยสามารถเลือกหมายเลขพอร์ตว่างใดก็ได้
  • 📥 คำขอขาออก: การดึงข้อมูลจากเว็บไซต์อื่นจำเป็นต้องใช้ไคลเอ็นต์ HTTP และปัจจุบัน Node.js มีฟังก์ชัน fetch ทั่วโลกให้ใช้งานแล้ว
  • ⚠️ ไคลเอ็นต์ที่เลิกใช้งานแล้ว: โมดูล request ถูกยกเลิกการใช้งานในเดือนกุมภาพันธ์ 2020 และไม่ควรนำไปใช้ในโค้ดใหม่
  • 🛠️ ความล้มเหลวในการเริ่มต้นธุรกิจ: ข้อผิดพลาด EADDRINUSE หมายความว่าพอร์ตที่เลือกถูกใช้งานโดยกระบวนการอื่นอยู่แล้ว

สร้างเว็บเซิร์ฟเวอร์ HTTP ใน Node.js

การขอ Node.js เฟรมเวิร์กนี้ส่วนใหญ่ใช้ในการสร้างแอปพลิเคชันที่ทำงานบนเซิร์ฟเวอร์ สามารถนำไปใช้สร้างเว็บเซิร์ฟเวอร์ที่ให้บริการเนื้อหาแก่ผู้ใช้ได้อย่างง่ายดาย

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

โหนดเป็นเว็บเซิร์ฟเวอร์โดยใช้ HTTP

เรามาดูตัวอย่างวิธีการสร้างและเรียกใช้งานแอปพลิเคชัน Node.js ตัวแรกกัน

แอปพลิเคชันนี้สร้างโมดูลเซิร์ฟเวอร์อย่างง่ายที่รับฟังการเชื่อมต่อบนพอร์ต 7000 เมื่อมีการส่งคำขอผ่านเบราว์เซอร์บนพอร์ตดังกล่าว เซิร์ฟเวอร์จะส่งคำตอบ สวัสดีชาวโลก การตอบสนองต่อลูกค้า

โหนดเป็นเว็บเซิร์ฟเวอร์โดยใช้ HTTP

Code คำอธิบาย

  1. การขอ require ฟังก์ชันอ่านค่า Javaต้นฉบับ เรียกใช้ไฟล์และส่งคืนอ็อบเจ็กต์ส่งออก ในที่นี้จะโหลดไฟล์ http โมดูลเพื่อให้ฟังก์ชันการทำงานของโมดูลนั้นพร้อมใช้งานในแอปพลิเคชัน
  2. แอปพลิเคชันเซิร์ฟเวอร์ถูกสร้างขึ้นจากฟังก์ชันง่ายๆ ฟังก์ชันนั้นจะทำงานทุกครั้งที่มีคำขอเข้ามายังเซิร์ฟเวอร์
  3. เมื่อได้รับคำขอ ระบบจะส่งการตอบกลับพร้อมสถานะดังนี้ 200นี่คือรหัสสถานะมาตรฐานในส่วนหัว HTTP สำหรับการตอบสนองที่สำเร็จ
  4. ส่วนเนื้อหาของการตอบกลับนั้นคือสตริง สวัสดีชาวโลก.
  5. server.listen โปรแกรมนี้จะทำให้แอปพลิเคชันรอรับคำขอจากไคลเอ็นต์บนพอร์ต 7000 สามารถใช้พอร์ตใดก็ได้ที่ว่างอยู่

หากคำสั่งทำงานสำเร็จ ผลลัพธ์ต่อไปนี้จะปรากฏในเบราว์เซอร์

เอาท์พุต

เอาต์พุตเว็บเซิร์ฟเวอร์ Node

จากผลลัพธ์:

  • กำลังเรียกดู localhost URL บนพอร์ต 7000 แสดงสตริง สวัสดีชาวโลก ในหน้าเว็บ
  • เนื่องจากโค้ดระบุพอร์ต 7000 ผลลัพธ์จึงจะปรากฏให้เห็นเฉพาะเมื่อเข้าถึงผ่านพอร์ตนั้นเท่านั้น

นี่คือโค้ดตัวอย่าง:

var http = require('http');

var server = http.createServer(function(request, response) {
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.end("Hello World\n");
});

server.listen(7000);

การจัดการคำขอ GET ใน Node.js

การส่งคำขอ GET เพื่อดึงข้อมูลจากเว็บไซต์อื่นนั้นทำได้ง่ายใน Node.js ซึ่งในอดีตต้องใช้ขั้นตอนที่ซับซ้อนกว่านี้ request โมดูลที่ติดตั้งจากบรรทัดคำสั่ง:

npm install request

คำสั่งนั้นจะขอให้ตัวจัดการแพ็กเกจของ Node ดาวน์โหลดโมดูลที่ต้องการและติดตั้ง เมื่อการติดตั้งสำเร็จ บรรทัดคำสั่งจะแสดงชื่อและเวอร์ชันของโมดูลที่ติดตั้งในรูปแบบ <name>@<version>.

ผลลัพธ์คำขอติดตั้ง npm

ในภาพด้านบนนั้น request โมดูลและหมายเลขเวอร์ชันได้รับการดาวน์โหลดและติดตั้งเรียบร้อยแล้ว

การส่งคำขอ GET ใน Node.js

Code คำอธิบาย

  1. การขอ request โมดูลที่ติดตั้งในขั้นตอนก่อนหน้านี้มีฟังก์ชันที่จำเป็นสำหรับการส่งคำขอ GET ไปยังเว็บไซต์ต่างๆ
  2. มีการส่งคำขอ GET ไปยังเว็บไซต์ และฟังก์ชันเรียกกลับจะทำงานเมื่อได้รับคำตอบ ฟังก์ชันเรียกกลับจะได้รับพารามิเตอร์สามตัว:
    1. ความผิดพลาด — บันทึกข้อผิดพลาดใดๆ ที่เกิดขึ้นระหว่างการส่งคำขอ
    2. คำตอบ — บรรจุส่วนหัว HTTP ที่ส่งกลับมาพร้อมกับการตอบกลับ
    3. ร่างกาย — ประกอบด้วยเนื้อหาทั้งหมดของคำตอบ
  3. เนื้อหาที่ได้รับใน body ค่าพารามิเตอร์จะถูกเขียนลงในคอนโซล

นี่คือโค้ดตัวอย่าง:

var request = require("request");

request("https://example.com", function(error, response, body) {
    // Always check the error parameter before using the body
    if (error) {
        console.error("Request failed:", error.message);
        return;
    }
    console.log(body);
});

⚠️ ประกาศแจ้งเตือนการเลิกใช้งาน: request โมดูลคือ เลิกใช้สิทธิ์โดยสมบูรณ์ในเดือนกุมภาพันธ์ 2020 และจะไม่ได้รับการอัปเดตเพิ่มเติมอีกต่อไป มันยังคงติดตั้งและทำงานได้ ดังนั้นตัวอย่างข้างต้นจึงยังคงใช้ได้กับโปรเจกต์ที่มีอยู่แล้ว แต่ npm install request ขณะนี้แสดงคำเตือนเกี่ยวกับการเลิกใช้งานแล้ว โค้ดใหม่ควรใช้ฟังก์ชันในตัว fetch ฟังก์ชันที่แสดงในส่วนถัดไป

วิธีการสร้างคำขอ HTTP ด้วย Native fetch ใน Node.js

Node ได้รวมเอาทั่วโลกไว้ด้วยแล้ว fetch ฟังก์ชันนี้มีมาตั้งแต่เวอร์ชัน 18 โดยตรงกับ API ที่เบราว์เซอร์มีอยู่แล้ว ไม่จำเป็นต้องติดตั้งแพ็กเกจ และฟังก์ชันจะส่งคืนค่า Promise ดังนั้นจึงใช้งานได้โดยตรงกับเบราว์เซอร์ async/await.

// No require and no npm install needed on Node 18 or later

async function getData() {
    try {
        const response = await fetch("https://example.com");

        // fetch does NOT reject on 404 or 500 — check ok yourself
        if (!response.ok) {
            throw new Error("HTTP status " + response.status);
        }

        const body = await response.text();
        console.log(body);

    } catch (err) {
        // Network failures and the throw above both land here
        console.error("Request failed:", err.message);
    }
}

getData();

มีข้อแตกต่างสามประการที่ควรสังเกตจากรูปแบบการเรียกใช้ฟังก์ชันแบบ Callback ประการแรก fetch จะปฏิเสธเฉพาะกรณีที่เกิดความล้มเหลวในระดับเครือข่ายเท่านั้น ข้อผิดพลาด HTTP 404 หรือ 500 ยังคงแก้ไขได้สำเร็จ ซึ่งเป็นเหตุผลว่าทำไม response.ok ตรวจสอบว่ามีอยู่หรือไม่ และเหตุใดการละเว้นการตรวจสอบนี้จึงเป็นข้อผิดพลาดที่พบบ่อยที่สุดเมื่อทำการย้ายจากที่หนึ่งไปยังอีกที่หนึ่ง requestประการที่สอง เนื้อหาไม่ได้ถูกส่งมาพร้อมกับคำตอบ แต่ต้องอ่านอย่างชัดเจนพร้อมกับคำตอบนั้น response.text() สำหรับข้อความธรรมดาหรือ response.json() สำหรับ JSON และแต่ละรายการจะส่งคืน Promise ของตัวเอง ประการที่สาม เนื่องจากคำสั่งเรียกทั้งหมดใช้ Promise เป็นหลัก จึงมีเพียงรายการเดียว try/catch ครอบคลุมทั้งการอ่านคำขอและเนื้อหา โดยแทนที่พารามิเตอร์ callback ที่แสดงข้อผิดพลาดก่อนอย่างสมบูรณ์

สำหรับสคริปต์ที่ต้องทำงานบน Node 16 หรือเวอร์ชันก่อนหน้า ให้ติดตั้ง node-fetch or axios แต่เนื่องจากทั้งสองแบบมีอินเทอร์เฟซที่ใช้ Promise ที่คล้ายคลึงกัน และต้องการเพียงการเปลี่ยนแปลงบรรทัดการนำเข้าเท่านั้นเมื่อมีการอัปเกรดรันไทม์

request, fetch และ axios: ควรใช้ตัวไหนดี? ควรใช้ตัวไหนดี?

โดยทั่วไปแล้วจะมีไคลเอ็นต์ HTTP สามตัวที่ปรากฏอยู่ในเอกสารเกี่ยวกับ Node.js ส่วนใหญ่ และมีเพียงตัวเดียวเท่านั้นที่เป็นค่าเริ่มต้นที่เหมาะสมสำหรับงานใหม่ ไคลเอ็นต์ทั้งสามตัวนี้แตกต่างกันในสถานะการบำรุงรักษา ความจำเป็นในการพึ่งพา และวิธีการที่แต่ละตัวส่งสัญญาณสถานะข้อผิดพลาด ดังนั้นตารางด้านล่างจึงนำไคลเอ็นต์ทั้งสามตัวมาเปรียบเทียบกัน

แง่มุม ขอ ดึงข้อมูล (ในตัว) Axios
สถานะ เลิกใช้งานแล้วตั้งแต่ปี 2020 บำรุงรักษาในส่วนหลัก มีการดูแลรักษาอย่างสม่ำเสมอ
การติดตั้ง แพ็คเกจ npm ไม่มีใน Node 18+ แพ็คเกจ npm
สไตล์ เรียกกลับแบบเกิดข้อผิดพลาดก่อน คำมั่นสัญญา คำมั่นสัญญา
การแยกวิเคราะห์ JSON กำหนดเอง หรือตัวเลือก JSON คู่มือผ่าน response.json() อัตโนมัติ
ปฏิเสธที่รหัส 404 หรือ 500 ไม่ ไม่ มี (ใบกำกับภาษีเต็มรูปแบบ)

ใช้ fetch สำหรับโปรเจ็กต์ใหม่บนเวอร์ชัน Node ปัจจุบัน เนื่องจากไม่เพิ่มการพึ่งพาใดๆ และตรงกับ API ของเบราว์เซอร์ที่นักพัฒนาคุ้นเคยอยู่แล้ว เลือกใช้ axios เมื่อการจัดการ JSON อัตโนมัติ การดักจับคำขอ หรือการปฏิเสธเมื่อเกิดข้อผิดพลาด จะช่วยประหยัดโค้ดจริงได้ เก็บไว้ request ใช้ได้เฉพาะภายในแอปพลิเคชันรุ่นเก่าที่พึ่งพาฟีเจอร์นี้อยู่แล้ว และวางแผนที่จะเปลี่ยนมาใช้ฟีเจอร์อื่นแทน

ข้อผิดพลาดทั่วไปของเซิร์ฟเวอร์ Node.js และวิธีแก้ไข

ความล้มเหลวส่วนใหญ่ในการเริ่มต้นเซิร์ฟเวอร์ Node.js ครั้งแรก มักเกิดจากพอร์ต เส้นทาง หรือการตอบสนองที่ขาดหายไป มากกว่าจากโค้ดของเซิร์ฟเวอร์เอง

  • การใช้เครื่องดื่ม: มีกระบวนการอื่นกำลังใช้งานพอร์ตอยู่แล้ว เรียกใช้งาน netstat -ano | findstr :7000 on Windowsหรือ lsof -i :7000 on macOS และสำหรับ Linux ให้หยุดกระบวนการนั้นหรือเลือกพอร์ตอื่น
  • EACCES บนพอร์ตต่ำ: พอร์ตที่ต่ำกว่า 1024 จำเป็นต้องใช้สิทธิ์ระดับสูง ควรใช้พอร์ตที่สูงกว่า 1024 ในระหว่างการพัฒนา เช่น 3000 หรือ 7000
  • เบราว์เซอร์ค้างและไม่โหลดเลย: เจ้าหน้าที่ไม่เคยโทรมา response.end()การเชื่อมต่อจะยังคงเปิดอยู่จนกว่าจะหมดเวลา ดังนั้นทุกเส้นทางที่ผ่านตัวจัดการจะต้องสิ้นสุดการตอบสนอง
  • ไม่พบโมดูล 'http': ชื่อไฟล์สะกดผิด หรือสคริปต์กำลังทำงานในเบราว์เซอร์แทนที่จะเป็น Node.js โมดูลหลักไม่จำเป็นต้องติดตั้ง
  • ไม่ปรากฏการเปลี่ยนแปลง: Node.js โหลดไฟล์เพียงครั้งเดียวตอนเริ่มต้น ควรเริ่มกระบวนการใหม่หลังจากแก้ไขแต่ละครั้ง หรือเรียกใช้งานผ่านโปรแกรมเฝ้าดู เช่น ... node --watch server.js.

คำถามที่พบบ่อย

โมดูล http นั้นเพียงพอสำหรับเอนด์พอยต์เดียว Express เพิ่มการกำหนดเส้นทาง มิดเดิลแวร์ และการแยกวิเคราะห์เนื้อหา ซึ่งจะคุ้มค่ากับการเป็นส่วนประกอบเสริมเมื่อแอปพลิเคชันให้บริการหลายเส้นทาง

จำเป็นต้องมี https ให้ใช้โมดูลแทน และส่งคีย์และใบรับรองไปยัง createServer ในสภาพแวดล้อมการใช้งานจริง โดยปกติแล้วพร็อกซีแบบย้อนกลับ เช่น Nginx จะยุติการเชื่อมต่อ TLS และส่งต่อ HTTP ธรรมดาไปยัง Node

ใช่. AI เครื่องมือเหล่านี้แปลง callback ที่รับข้อผิดพลาดก่อนเป็น async await ได้อย่างน่าเชื่อถือ ตรวจสอบให้แน่ใจว่าโค้ดที่สร้างขึ้นมีการเพิ่มการทดสอบ response.ok เนื่องจาก fetch จะแก้ไขปัญหาเมื่อเกิดข้อผิดพลาด 404 และการตรวจสอบนี้มักถูกละเว้น

ผู้ช่วย AI จะอ่านรหัสข้อผิดพลาดและระบุสาเหตุได้โดยตรง โดยแยกแยะความขัดแย้งของพอร์ตออกจากปัญหาด้านสิทธิ์หรือข้อผิดพลาดทางไวยากรณ์ ซึ่งช่วยลดการคาดเดาในโปรเจ็กต์ Node.js แรกได้อย่างมาก

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

สรุปโพสต์นี้ด้วย: