Node.js 的 http
模块是构建 Web 服务器和客户端的基础核心模块,它提供了创建 HTTP 服务器和发起 HTTP 请求的能力。
1. 核心功能
- 创建 HTTP 服务器:监听端口,处理客户端请求(如浏览器访问)。
- 发起 HTTP 请求 :作为客户端向其他服务器发送请求(类似
fetch
或axios
的底层实现)。 - 处理 HTTP 协议 :支持 HTTP/1.1 和部分 HTTP/2 功能(需结合
http2
模块)。
2. 创建 HTTP 服务器
使用 http.createServer()
方法创建服务器,传入一个回调函数处理请求和响应。
javascript
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 请求示例
javascript
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');
javascript
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()
方法向其他服务器发送请求。
基本示例
javascript
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
)
javascript
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 服务器:
javascript
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
等模块实现更复杂功能。