Node.js HTTP Server:建立原生的 Web 伺服器
Node.js 最著名的特性之一,就是它不依賴 Apache 或 Nginx 就能自行架設高效能的 Web 伺服器。雖然現代開發多使用 Express 等框架,但深入理解原生的 http 模組,對於掌握 Web 請求的底層邏輯與串流 (Stream) 運作至關重要。
建立第一個 Web 伺服器
只需要幾行程式碼,你的電腦就能瞬間轉化為一台伺服器,準備接收全球的請求。
const http = require('http');
// createServer 的回呼函式會在每次有請求進來時執行
const server = http.createServer((req, res) => {
// 設定狀態碼與回應頭
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
// 寫入內容並正式結束回應
res.end('<h1>你好!這是來自 Node.js 原生伺服器的訊息。</h1>');
});
server.listen(3000, () => {
console.log('伺服器正運行在 http://localhost:3000/');
});
請求物件 (Request):客戶端傳了什麼?
req 物件是一個 Readable Stream。它承載了所有的連線資訊:
req.url:請求的路徑(如/api/users)。req.method:HTTP 方法(GET, POST, PUT, DELETE...)。req.headers:存取所有的請求頭資訊(如 User-Agent, Cookie)。
回應物件 (Response):我要回覆什麼?
res 物件是一個 Writable Stream。
res.writeHead():同時設定狀態碼與多個標頭(一旦呼叫就不能再改標頭)。res.setHeader():個別設定標頭。res.write():向客戶端傳送資料區塊(常用於大型串流傳輸)。res.end():這一步是強制性的,用來告知伺服器回應已結束,否則客戶端會一直處於等待掛起狀態。
實戰:處理 POST 數據 (Body Parsing)
由於 req 是個串流,我們必須手動收集數據塊並拼接起來:
http
.createServer((req, res) => {
if (req.method === 'POST') {
let body = '';
// 監聽數據流入
req.on('data', (chunk) => {
body += chunk.toString();
});
// 數據接收完畢
req.on('end', () => {
const data = JSON.parse(body);
console.log('收到 POST 資料:', data);
res.end('資料已收到');
});
}
})
.listen(3000);
基本路由 (Simple Routing) 邏輯
在原生環境下,我們需要根據 req.url 進行手動分流:
const server = http.createServer((req, res) => {
const path = req.url;
if (path === '/' || path === '/home') {
res.end('首頁內容');
} else if (path === '/api/status') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'Online' }));
} else {
res.writeHead(404);
res.end('404 Not Found');
}
});
為什麼要學 Express? 看到上面的路由與 Body 解析了嗎?在原生模式下做這些事非常繁瑣。這就是為什麼我們隨後會推薦使用 Express 框架,它能幫你自動化這些瑣碎的流程。
總結
http.createServer是 Node.js Web 開發的起點。- 記得
res.end()絕不能漏,它是關閉連線的訊號。 - 掌握原生 HTTP 模組後,你對 Node.js 的非阻塞 I/O 會有更深層次的體會。