1.5 Node.js 的 HTTP
Node.js 的 http
模块是构建 Web 服务器和客户端的基础核心模块,它提供了创建 HTTP 服务器和发起 HTTP 请求的能力。
1. 核心功能
- 创建 HTTP 服务器:监听端口,处理客户端请求(如浏览器访问)。
- 发起 HTTP 请求:作为客户端向其他服务器发送请求(类似
fetch
或axios
的底层实现)。 - 处理 HTTP 协议:支持 HTTP/1.1 和部分 HTTP/2 功能(需结合
http2
模块)。
2. 创建 HTTP 服务器
使用 http.createServer()
方法创建服务器,传入一个回调函数处理请求和响应。
const http = require('http');// 创建服务器
const server = http.createServer((req, res) => {// req: 请求对象(包含客户端信息)// res: 响应对象(用于向客户端返回数据)// 设置响应头res.writeHead(200, { 'Content-Type': 'text/plain' });// 发送响应内容res.end('Hello, World!\n');
});// 监听端口
server.listen(3000, () => {console.log('Server running at http://localhost:3000/');
});
req
对象:包含请求方法(GET
/POST
)、URL、头部、Body 等信息。res
对象:用于设置状态码、头部、发送响应内容(end()
结束响应)。
3. 请求对象 (req
) 的常用属性和方法
属性/方法 | 说明 |
---|---|
req.method | 请求方法(如 'GET' , 'POST' )。 |
req.url | 请求的 URL 路径(不包含域名和查询参数)。 |
req.headers | 请求头对象(如 { 'user-agent': 'Chrome' } )。 |
req.on('data') | 监听数据块(用于处理 POST 请求的 Body)。 |
req.on('end') | 数据接收完毕时触发。 |
req.url | 解析 URL 可使用 url 模块(如 require('url').parse(req.url) )。 |
处理 POST 请求示例
const http = require('http');const server = http.createServer((req, res) => {if (req.method === 'POST') {let body = '';req.on('data', chunk => {body += chunk.toString(); // 拼接数据块});req.on('end', () => {console.log('Received:', body);res.end('Data received');});} else {res.end('Send a POST request');}
});server.listen(3000);
4. 响应对象 (res
) 的常用方法
方法 | 说明 |
---|---|
res.writeHead() | 设置状态码和响应头(如 200 和 Content-Type )。 |
res.write() | 发送部分响应内容(可多次调用)。 |
res.end() | 结束响应(可附带最后的数据)。 |
res.statusCode | 直接设置状态码(如 res.statusCode = 404 )。 |
(1) URL 解析
使用 url
模块解析请求 URL:
const url = require('url');
const parsedUrl = url.parse(req.url);
console.log('Path:', parsedUrl.pathname);
console.log('Query:', parsedUrl.query); // 如 ?name=foo&age=20
(2) 路由处理
手动实现简单路由:
const server = http.createServer((req, res) => {const { pathname } = url.parse(req.url);if (pathname === '/') {res.end('Home Page');} else if (pathname === '/about') {res.end('About Page');} else {res.statusCode = 404;res.end('Not Found');}
});
(3) HTTP 状态码
常用状态码:
200
:成功404
:未找到500
:服务器错误
设置状态码:
res.statusCode = 404;
res.end('Not Found');
const http = require('http');
const url = require('url');
const querystring = require('querystring');// 模拟数据库数据
const users = [{ id: 1, name: 'Alice' },{ id: 2, name: 'Bob' },{ id: 3, name: 'Charlie' }
];const server = http.createServer((req, res) => {// 解析 URL 和查询参数const parsedUrl = url.parse(req.url, true);const path = parsedUrl.pathname.replace(/^\/+|\/+$/g, ''); // 去除首尾斜杠const query = parsedUrl.query;// 设置 CORS 头,允许跨域请求res.setHeader('Access-Control-Allow-Origin', '*');res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');res.setHeader('Access-Control-Allow-Headers', 'Content-Type');// 处理 OPTIONS 请求(预检请求)if (req.method === 'OPTIONS') {res.writeHead(200);res.end();return;}// 路由处理if (path === 'users') {switch (req.method) {case 'GET':// 获取用户列表或单个用户if (query.id) {const user = users.find(u => u.id === parseInt(query.id));if (user) {res.writeHead(200, { 'Content-Type': 'application/json' });res.end(JSON.stringify(user));} else {res.writeHead(404, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ error: 'User not found' }));}} else {res.writeHead(200, { 'Content-Type': 'application/json' });res.end(JSON.stringify(users));}break;case 'POST':// 创建新用户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 (error) {res.writeHead(400, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ error: 'Invalid request body' }));}});break;case 'PUT':// 更新用户if (!query.id) {res.writeHead(400, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ error: 'Missing user ID' }));return;}let updateBody = '';req.on('data', (chunk) => {updateBody += chunk;});req.on('end', () => {try {const updatedData = JSON.parse(updateBody);const index = users.findIndex(u => u.id === parseInt(query.id));if (index !== -1) {users[index] = { ...users[index], ...updatedData };res.writeHead(200, { 'Content-Type': 'application/json' });res.end(JSON.stringify(users[index]));} else {res.writeHead(404, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ error: 'User not found' }));}} catch (error) {res.writeHead(400, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ error: 'Invalid request body' }));}});break;case 'DELETE':// 删除用户if (!query.id) {res.writeHead(400, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ error: 'Missing user ID' }));return;}const index = users.findIndex(u => u.id === parseInt(query.id));if (index !== -1) {const deletedUser = users.splice(index, 1)[0];res.writeHead(200, { 'Content-Type': 'application/json' });res.end(JSON.stringify(deletedUser));} else {res.writeHead(404, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ error: 'User not found' }));}break;default:res.writeHead(405, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ error: 'Method not allowed' }));}} else {// 未知路由res.writeHead(404, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ error: 'Route not found' }));}
});// 启动服务器
server.listen(3000, () => {console.log('API 服务器已启动,监听端口 3000');
});
5. 发起 HTTP 请求(客户端)
使用 http.request()
方法向其他服务器发送请求。
基本示例
const http = require('http');const options = {hostname: 'example.com',port: 80,path: '/',method: 'GET'
};const req = http.request(options, (res) => {console.log(`Status Code: ${res.statusCode}`);let data = '';res.on('data', (chunk) => {data += chunk;});res.on('end', () => {console.log('Response:', data);});
});req.on('error', (e) => {console.error('Request failed:', e);
});req.end(); // 必须调用 end() 发送请求
简化版(使用 http.get
)
const http = require('http');http.get('http://example.com', (res) => {let data = '';res.on('data', (chunk) => {data += chunk;});res.on('end', () => {console.log('Response:', data);});
});
6. 与 https
模块的区别
http
:明文传输(不加密)。https
:基于 TLS/SSL 加密(需配置证书)。
创建 HTTPS 服务器:
const https = require('https');
const fs = require('fs');const options = {key: fs.readFileSync('server.key'),cert: fs.readFileSync('server.crt')
};https.createServer(options, (req, res) => {res.end('Secure Server');
}).listen(443);
.注意事项
- 性能问题:
http
模块是底层 API,高并发场景建议使用Express
或Fastify
。 - 错误处理:必须监听
error
事件(如网络错误)。 - Body 解析:POST 请求的 Body 需要手动拼接(生产环境可用
body-parser
或类似中间件)。
总结
- 服务器端:
http.createServer()
+req/res
处理请求。 - 客户端:
http.request()
或http.get()
发起请求。 - 扩展性:结合
url
、querystring
等模块实现更复杂功能。