Appearance
第8章:请求与响应处理
8.1 GET请求参数获取
GET 请求的参数通常包含在 URL 的查询字符串中,我们可以使用 url 模块来解析这些参数。
示例:
javascript
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
// 解析 URL,第二个参数为 true 表示将查询字符串解析为对象
const { pathname, query } = url.parse(req.url, true);
if (pathname === '/api/users' && req.method === 'GET') {
// 获取查询参数
const { name, age } = query;
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
message: '获取用户列表成功',
data: {
name,
age,
timestamp: new Date().toISOString()
}
}));
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
}
});
const port = 3000;
server.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});测试:
访问 http://localhost:3000/api/users?name=张三&age=20,你应该会看到以下响应:
json
{
"message": "获取用户列表成功",
"data": {
"name": "张三",
"age": "20",
"timestamp": "2026-04-02T03:16:00.000Z"
}
}8.2 POST请求参数获取
POST 请求的参数通常包含在请求体中,我们需要监听 req 对象的 data 和 end 事件来获取请求体数据。
示例:
javascript
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
const { pathname } = url.parse(req.url);
if (pathname === '/api/users' && req.method === 'POST') {
let requestBody = '';
// 监听 data 事件,接收请求体数据
req.on('data', chunk => {
requestBody += chunk.toString();
});
// 监听 end 事件,处理请求体数据
req.on('end', () => {
try {
// 解析 JSON 格式的请求体
const userData = JSON.parse(requestBody);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
message: '创建用户成功',
data: {
id: Date.now(),
...userData,
createdAt: new Date().toISOString()
}
}));
} catch (error) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
message: '请求体格式错误',
error: error.message
}));
}
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
}
});
const port = 3000;
server.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});测试:
使用 Postman 或 curl 发送 POST 请求:
bash
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name": "张三", "age": 20, "email": "zhangsan@example.com"}'你应该会看到以下响应:
json
{
"message": "创建用户成功",
"data": {
"id": 1617300960000,
"name": "张三",
"age": 20,
"email": "zhangsan@example.com",
"createdAt": "2026-04-02T03:16:00.000Z"
}
}8.3 响应状态码、响应头设置
响应状态码
HTTP 响应状态码表示服务器对请求的处理结果,常用的状态码:
- 200 OK:请求成功
- 201 Created:资源创建成功
- 204 No Content:请求成功但无内容返回
- 400 Bad Request:请求参数错误
- 401 Unauthorized:未授权
- 403 Forbidden:禁止访问
- 404 Not Found:资源不存在
- 500 Internal Server Error:服务器内部错误
响应头设置
响应头包含了关于响应的元信息,如内容类型、缓存控制等。
示例:
javascript
const http = require('http');
const server = http.createServer((req, res) => {
// 设置响应状态码和响应头
res.writeHead(200, {
'Content-Type': 'application/json',
'X-Powered-By': 'Node.js',
'Cache-Control': 'no-cache',
'Access-Control-Allow-Origin': '*'
});
// 发送响应内容
res.end(JSON.stringify({
message: 'Hello, Node.js!',
timestamp: new Date().toISOString()
}));
});
const port = 3000;
server.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});8.4 响应JSON数据
在现代 Web 开发中,API 接口通常返回 JSON 格式的数据。我们需要设置 Content-Type 响应头为 application/json,并使用 JSON.stringify() 将 JavaScript 对象转换为 JSON 字符串。
示例:
javascript
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
const { pathname } = url.parse(req.url);
if (pathname === '/api/data' && req.method === 'GET') {
// 模拟数据
const data = {
id: 1,
name: 'Node.js 教程',
description: 'Node.js 新手入门教程',
tags: ['Node.js', 'JavaScript', '后端开发'],
createdAt: new Date().toISOString()
};
// 设置响应头
res.writeHead(200, {
'Content-Type': 'application/json'
});
// 发送 JSON 响应
res.end(JSON.stringify({
success: true,
message: '获取数据成功',
data: data
}));
} else {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
message: '接口不存在'
}));
}
});
const port = 3000;
server.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});测试:
访问 http://localhost:3000/api/data,你应该会看到以下响应:
json
{
"success": true,
"message": "获取数据成功",
"data": {
"id": 1,
"name": "Node.js 教程",
"description": "Node.js 新手入门教程",
"tags": ["Node.js", "JavaScript", "后端开发"],
"createdAt": "2026-04-02T03:16:00.000Z"
}
}8.5 跨域问题基础
跨域问题是指浏览器的同源策略限制,当前端应用和后端 API 不在同一域名下时,会出现跨域问题。
CORS 配置
CORS (Cross-Origin Resource Sharing) 是解决跨域问题的标准方法,通过设置响应头来允许跨域请求。
示例:
javascript
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
// 设置 CORS 响应头
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
// 处理 OPTIONS 请求
if (req.method === 'OPTIONS') {
res.writeHead(204);
res.end();
return;
}
const { pathname } = url.parse(req.url);
if (pathname === '/api/users' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: true,
message: '获取用户列表成功',
data: [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' }
]
}));
} else {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
message: '接口不存在'
}));
}
});
const port = 3000;
server.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});说明:
Access-Control-Allow-Origin: 允许的源,*表示允许所有源Access-Control-Allow-Methods: 允许的 HTTP 方法Access-Control-Allow-Headers: 允许的请求头OPTIONS请求:浏览器在发送跨域请求前会先发送 OPTIONS 请求进行预检
8.6 实操案例:编写GET/POST接口
案例:用户管理 API
步骤1:创建 server.js 文件
javascript
// server.js
const http = require('http');
const url = require('url');
// 模拟用户数据
let users = [
{ id: 1, name: '张三', age: 20, email: 'zhangsan@example.com' },
{ id: 2, name: '李四', age: 25, email: 'lisi@example.com' }
];
const server = http.createServer((req, res) => {
// 设置 CORS 响应头
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
// 处理 OPTIONS 请求
if (req.method === 'OPTIONS') {
res.writeHead(204);
res.end();
return;
}
const { pathname, query } = url.parse(req.url, true);
// GET /api/users - 获取用户列表
if (pathname === '/api/users' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: true,
message: '获取用户列表成功',
data: users
}));
}
// GET /api/users/:id - 获取单个用户
else if (pathname.match(/^\/api\/users\/\d+$/) && req.method === 'GET') {
const id = parseInt(pathname.split('/')[3]);
const user = users.find(u => u.id === id);
if (user) {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: true,
message: '获取用户成功',
data: user
}));
} else {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
message: '用户不存在'
}));
}
}
// POST /api/users - 创建用户
else if (pathname === '/api/users' && req.method === 'POST') {
let requestBody = '';
req.on('data', chunk => {
requestBody += chunk.toString();
});
req.on('end', () => {
try {
const userData = JSON.parse(requestBody);
const newUser = {
id: users.length + 1,
...userData,
createdAt: new Date().toISOString()
};
users.push(newUser);
res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: true,
message: '创建用户成功',
data: newUser
}));
} catch (error) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
message: '请求体格式错误',
error: error.message
}));
}
});
}
// PUT /api/users/:id - 更新用户
else if (pathname.match(/^\/api\/users\/\d+$/) && req.method === 'PUT') {
const id = parseInt(pathname.split('/')[3]);
const userIndex = users.findIndex(u => u.id === id);
if (userIndex === -1) {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
message: '用户不存在'
}));
return;
}
let requestBody = '';
req.on('data', chunk => {
requestBody += chunk.toString();
});
req.on('end', () => {
try {
const userData = JSON.parse(requestBody);
const updatedUser = {
...users[userIndex],
...userData,
updatedAt: new Date().toISOString()
};
users[userIndex] = updatedUser;
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: true,
message: '更新用户成功',
data: updatedUser
}));
} catch (error) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
message: '请求体格式错误',
error: error.message
}));
}
});
}
// DELETE /api/users/:id - 删除用户
else if (pathname.match(/^\/api\/users\/\d+$/) && req.method === 'DELETE') {
const id = parseInt(pathname.split('/')[3]);
const userIndex = users.findIndex(u => u.id === id);
if (userIndex === -1) {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
message: '用户不存在'
}));
return;
}
users.splice(userIndex, 1);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: true,
message: '删除用户成功'
}));
}
// 404
else {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
message: '接口不存在'
}));
}
});
const port = 3000;
server.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});步骤2:运行服务器
bash
node server.js步骤3:测试 API
使用 Postman 或 curl 测试以下接口:
获取用户列表:
bashcurl http://localhost:3000/api/users获取单个用户:
bashcurl http://localhost:3000/api/users/1创建用户:
bashcurl -X POST http://localhost:3000/api/users \ -H "Content-Type: application/json" \ -d '{"name": "王五", "age": 30, "email": "wangwu@example.com"}'更新用户:
bashcurl -X PUT http://localhost:3000/api/users/1 \ -H "Content-Type: application/json" \ -d '{"age": 21, "email": "zhangsan updated@example.com"}'删除用户:
bashcurl -X DELETE http://localhost:3000/api/users/2
小结
- GET 请求参数可以通过
url模块解析查询字符串获取 - POST 请求参数需要监听
data和end事件获取请求体 - 响应状态码表示服务器对请求的处理结果
- 响应头包含了关于响应的元信息
- API 接口通常返回 JSON 格式的数据
- 跨域问题可以通过 CORS 配置解决
- 实际项目中,通常使用 Express 等框架来简化请求和响应处理
现在,你已经了解了如何处理 HTTP 请求和响应,接下来让我们学习文件系统进阶。
