7、http

Node.js 的 http 模块提供了创建HTTP 服务器和客户端的功能。

HTTP 服务器

创建方法

使用createServer 创建

const http = require('http');

// 创建服务对象
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World\n');
});
// 开启监听 3000 端口
server.listen(3000, '127.0.0.1', () => {
  console.log('服务器运行在 http://127.0.0.1:3000/');
});

使用 Server 类创建

const http = require('http');

const server = new http.Server((req, res) => {
  // 设置统一响应头
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  // 设置统一响应体
  res.end('Hello World\n');
});

server.listen(3001);

处理不同请求方法

const http = require('http');


// 2. 使用 Server 类
const server = new http.Server((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World\n');
});

server.listen(3001);

// 处理不同请求方法
const server = http.createServer((req, res) => {
  switch (req.method) {
    case 'GET':
      handleGet(req, res);
      break;
    case 'POST':
      handlePost(req, res);
      break;
    default:
      res.writeHead(405);
      res.end('Method Not Allowed');
  }
});

// get 方法处理函数
function handleGet(req, res) {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ message: 'GET request handled' }));
}

// post 方法处理函数
function handlePost(req, res) {
  let body = '';
  
  req.on('data', chunk => {
    body += chunk.toString();
  });
  
  req.on('end', () => {
    try {
      const data = JSON.parse(body);
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ received: data }));
    } catch (e) {
      res.writeHead(400);
      res.end('Invalid JSON');
    }
  });
}

服务端事件

// 1. 连接事件
server.on('connection', (socket) => {
  console.log('新连接建立');
  
  socket.on('data', (chunk) => {
    console.log('收到数据:', chunk.toString());
  });
  
  socket.on('end', () => {
    console.log('连接结束');
  });
  
  socket.on('error', (err) => {
    console.error('Socket 错误:', err);
  });
});

// 2. 请求事件
server.on('request', (req, res) => {
  console.log('收到请求:', req.method, req.url);
});

// 3. 错误事件
server.on('error', (err) => {
  console.error('服务器错误:', err);
});

// 4. 关闭事件
server.on('close', () => {
  console.log('服务器关闭');
});

// 5. 监听事件
server.on('listening', () => {
  console.log('服务器开始监听');
});

服务端常用方法

// 1. 启动服务器
server.listen(3000, '127.0.0.1', () => {
  console.log('服务器运行在 http://127.0.0.1:3000/');
});

// 2. 关闭服务器
server.close(() => {
  console.log('服务器已关闭');
});

// 3. 获取服务器地址信息
const address = server.address();
console.log('服务器地址:', address); // { address: '127.0.0.1', family: 'IPv4', port: 3000 }

// 4. 设置超时
server.setTimeout(60000); // 60 秒
server.on('timeout', (socket) => {
  console.log('连接超时');
});

// 5. 获取最大头信息大小
const maxHeaderSize = server.maxHeaderSize;
console.log('最大头信息大小:', maxHeaderSize);

// 6. 设置最大头信息大小
server.maxHeaderSize = 16384; // 16KB

回调函数

请求对象 (http.IncomingMessage)

即我们在创建 server 时回调函数的第一个参数

// 1. 请求属性
server.on('request', (req, res) => {
  console.log('请求方法:', req.method);
  console.log('请求 URL:', req.url);
  console.log('请求头:', req.headers);
  console.log('HTTP 版本:', req.httpVersion);
  console.log('HTTP 版本号:', req.httpVersionMajor, req.httpVersionMinor);
  console.log('原始 URL:', req.rawHeaders);
  console.log('原始尾随头信息:', req.rawTrailers);
  console.log('尾随头信息:', req.trailers);
  console.log('Socket:', req.socket);
  console.log('连接:', req.connection);
});

// 2. 请求事件
server.on('request', (req, res) => {
  // 数据事件
  req.on('data', (chunk) => {
    console.log('收到数据块:', chunk);
  });
  
  // 结束事件
  req.on('end', () => {
    console.log('请求数据接收完成');
  });
  
  // 错误事件
  req.on('error', (err) => {
    console.error('请求错误:', err);
  });
  
  // 关闭事件
  req.on('close', () => {
    console.log('请求关闭');
  });
  
  // 中止事件
  req.on('aborted', () => {
    console.log('请求中止');
  });
});

// 3. 请求方法
server.on('request', (req, res) => {
  // 销毁请求
  req.destroy();
  
  // 暂停请求
  req.pause();
  
  // 恢复请求
  req.resume();
});

响应对象 (http.ServerResponse)

即我们在创建 server 时回调函数的第二个参数

// 1. 响应属性
server.on('request', (req, res) => {
  console.log('响应头已发送:', res.headersSent);
  console.log('响应完成:', res.finished);
  console.log('响应发送中:', res.sending);
  console.log('响应状态码:', res.statusCode);
  console.log('响应状态消息:', res.statusMessage);
  console.log('Socket:', res.socket);
});

// 2. 响应方法
server.on('request', (req, res) => {
  // 设置响应头
  res.setHeader('Content-Type', 'text/plain');
  res.setHeader('X-Custom-Header', 'value');
  
  // 获取响应头
  const contentType = res.getHeader('Content-Type');
  console.log('Content-Type:', contentType);
  
  // 移除响应头
  res.removeHeader('X-Custom-Header');
  
  // 写入响应头
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  
  // 写入响应体
  res.write('Hello ');
  res.write('World\n');
  
  // 结束响应
  res.end();
  
  // 刷新响应头
  res.flushHeaders();
});

// 3. 响应事件
server.on('request', (req, res) => {
  // 完成事件
  res.on('finish', () => {
    console.log('响应完成');
  });
  
  // 关闭事件
  res.on('close', () => {
    console.log('响应关闭');
  });
});

HTTP 客户端

发送请求

GET

const getReq = http.get('http://example.com', (res) => {
  console.log('状态码:', res.statusCode);
  console.log('头信息:', res.headers);
  
  let data = '';
  
  res.on('data', chunk => {
    data += chunk;
  });
  
  res.on('end', () => {
    console.log('响应数据:', data);
  });
});

getReq.on('error', (err) => {
  console.error('请求错误:', err);
});

POST

const postData = JSON.stringify({ key: 'value' });

const options = {
  hostname: 'example.com',
  path: '/api/data',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(postData)
  }
};

const postReq = http.request(options, (res) => {
  console.log('状态码:', res.statusCode);
  
  let data = '';
  
  res.on('data', chunk => {
    data += chunk;
  });
  
  res.on('end', () => {
    console.log('响应数据:', data);
  });
});

postReq.on('error', (err) => {
  console.error('请求错误:', err);
});

postReq.write(postData);
postReq.end();

使用 Agent

const agent = new http.Agent({
  keepAlive: true,
  keepAliveMsecs: 1000,
  maxSockets: 10
});

const reqWithAgent = http.request({
  hostname: 'example.com',
  path: '/',
  agent: agent
}, (res) => {
  // 处理响应
});