Skip to content

第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 对象的 dataend 事件来获取请求体数据。

示例

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 测试以下接口:

  1. 获取用户列表

    bash
    curl http://localhost:3000/api/users
  2. 获取单个用户

    bash
    curl http://localhost:3000/api/users/1
  3. 创建用户

    bash
    curl -X POST http://localhost:3000/api/users \
      -H "Content-Type: application/json" \
      -d '{"name": "王五", "age": 30, "email": "wangwu@example.com"}'
  4. 更新用户

    bash
    curl -X PUT http://localhost:3000/api/users/1 \
      -H "Content-Type: application/json" \
      -d '{"age": 21, "email": "zhangsan updated@example.com"}'
  5. 删除用户

    bash
    curl -X DELETE http://localhost:3000/api/users/2

小结

  • GET 请求参数可以通过 url 模块解析查询字符串获取
  • POST 请求参数需要监听 dataend 事件获取请求体
  • 响应状态码表示服务器对请求的处理结果
  • 响应头包含了关于响应的元信息
  • API 接口通常返回 JSON 格式的数据
  • 跨域问题可以通过 CORS 配置解决
  • 实际项目中,通常使用 Express 等框架来简化请求和响应处理

现在,你已经了解了如何处理 HTTP 请求和响应,接下来让我们学习文件系统进阶。

© 2026 编程马·菜鸟教程 版权所有