http 模块是 Node.js 的核心模块之一,它提供了创建 HTTP 服务器和客户端的功能。通过 http 模块,你可以轻松构建 Web 应用、REST API 或静态文件服务器。本章将详细介绍如何使用 http 模块创建服务器、处理请求与响应、实现路由以及构建一个简单的 REST API。
http 是内置模块,无需安装,直接引入即可:
const http = require('http');
使用 http.createServer() 方法创建一个服务器实例,它接受一个回调函数,每当有请求到达时就会调用该函数。回调函数接收两个参数:req(请求对象)和 res(响应对象)。
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
});
server.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000/');
});
运行该脚本,访问 http://localhost:3000,你将看到 "Hello World"。
res.end() 必须被调用,否则客户端会一直等待响应。可以先用 res.write() 写入响应体,最后用 res.end() 结束响应。
req 是 http.IncomingMessage 的实例,包含请求的所有信息:
req.method - 请求方法(GET、POST、PUT 等)req.url - 请求的 URL(包含路径和查询字符串)req.headers - 请求头对象req.httpVersion - HTTP 版本const server = http.createServer((req, res) => {
console.log('请求方法:', req.method);
console.log('请求URL:', req.url);
console.log('请求头:', req.headers);
res.end('Check your console');
});
对于 POST、PUT 等包含请求体的请求,需要通过监听 data 和 end 事件来获取数据:
const server = http.createServer((req, res) => {
if (req.method === 'POST') {
let body = '';
req.on('data', chunk => {
body += chunk.toString(); // 默认是 Buffer,转成字符串
});
req.on('end', () => {
console.log('请求体:', body);
res.end('Data received');
});
} else {
res.end('Send a POST request');
}
});
res 是 http.ServerResponse 的实例,用于构建响应:
res.writeHead(statusCode, headers) - 设置状态码和响应头(可多次调用,但只有第一次有效)res.setHeader(name, value) - 单独设置响应头res.write(chunk) - 写入响应体(可以多次调用)res.end([data]) - 结束响应,可选地发送最后的数据示例:返回 JSON 数据
const server = http.createServer((req, res) => {
const data = { name: 'Node.js', type: 'runtime' };
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(data));
});
根据请求方法和 URL 进行分发,实现简单的路由:
const server = http.createServer((req, res) => {
const { method, url } = req;
if (method === 'GET' && url === '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>Home Page</h1>');
} else if (method === 'GET' && url === '/about') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>About Page</h1>');
} else if (method === 'POST' && url === '/api/users') {
res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'User created' }));
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
}
});
使用 Node.js 内置的 url 模块或 URL 类来解析 URL:
const url = require('url');
const server = http.createServer((req, res) => {
// 使用 url.parse (旧版)
const parsedUrl = url.parse(req.url, true); // true 表示将查询字符串解析为对象
console.log('路径名:', parsedUrl.pathname);
console.log('查询参数:', parsedUrl.query); // 例如 { id: '123', name: 'node' }
// 使用 URL 类 (现代方式)
const myURL = new URL(req.url, `http://${req.headers.host}`);
console.log('路径名:', myURL.pathname);
console.log('查询参数:', Object.fromEntries(myURL.searchParams));
res.end('Check console');
});
结合 fs 模块读取文件并返回:
const fs = require('fs');
const path = require('path');
const server = http.createServer((req, res) => {
if (req.method === 'GET' && req.url === '/') {
const filePath = path.join(__dirname, 'public', 'index.html');
fs.readFile(filePath, (err, content) => {
if (err) {
res.writeHead(500);
res.end('Server Error');
} else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content);
}
});
} else {
// 处理其他请求...
}
});
更好的做法是使用流式传输以提高性能:
const stream = fs.createReadStream(filePath);
res.writeHead(200, { 'Content-Type': 'text/html' });
stream.pipe(res); // 自动处理结束和错误
在服务器中,应始终处理可能发生的错误:
const server = http.createServer((req, res) => {
// ... 业务逻辑
});
server.on('error', (err) => {
console.error('服务器错误:', err);
});
https 模块与 http 类似,但需要提供 SSL 证书:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Hello HTTPS\n');
}).listen(443);
以下是一个模拟用户资源的 REST API:
const http = require('http');
const url = require('url');
let users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const method = req.method;
const pathname = parsedUrl.pathname;
// 设置 CORS 头(可选)
res.setHeader('Access-Control-Allow-Origin', '*');
// 路由:GET /users
if (method === 'GET' && pathname === '/users') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(users));
}
// 路由:GET /users/:id
else if (method === 'GET' && pathname.startsWith('/users/')) {
const id = parseInt(pathname.split('/')[2]);
const user = users.find(u => u.id === id);
if (user) {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(user));
} else {
res.writeHead(404);
res.end(JSON.stringify({ error: 'User not found' }));
}
}
// 路由:POST /users
else if (method === 'POST' && pathname === '/users') {
let body = '';
req.on('data', chunk => body += chunk);
req.on('end', () => {
try {
const newUser = JSON.parse(body);
newUser.id = users.length + 1;
users.push(newUser);
res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(newUser));
} catch (err) {
res.writeHead(400);
res.end(JSON.stringify({ error: 'Invalid JSON' }));
}
});
}
// 404
else {
res.writeHead(404);
res.end(JSON.stringify({ error: 'Route not found' }));
}
});
server.listen(3000, () => {
console.log('REST API 服务器运行在 http://localhost:3000');
});
res.end() 结束响应,否则请求会挂起。Content-Type 并使用 JSON.stringify()。data 和 end 事件。http 模块仍然很重要。本章介绍了如何使用 Node.js 的 http 模块创建 HTTP 服务器,包括处理请求、响应、路由、获取参数和构建简单的 REST API。虽然实际开发中可能会使用 Express 等框架,但深入理解底层实现有助于更好地调试和优化应用。下一章我们将介绍 Node.js 的另一个核心模块 url,用于更精细的 URL 处理。