跳到主要内容

HTTP服务器搭建

HTTP服务器概述

Node.js提供了http模块,允许我们轻松创建HTTP服务器。这是Node.js最常用的功能之一,也是构建Web应用的基础。通过http模块,我们可以接收HTTP请求、处理请求、并发送HTTP响应。

创建一个简单的HTTP服务器

下面是创建一个最简单的HTTP服务器的代码示例:

const http = require('http');

// 创建服务器
const server = http.createServer((req, res) => {
// 设置响应头
res.writeHead(200, { 'Content-Type': 'text/plain' });

// 发送响应内容
res.end('Hello, World!\n');
});

// 监听端口
const PORT = 3000;
server.listen(PORT, () => {
console.log(`服务器运行在 http://localhost:${PORT}/`);
});

将上面的代码保存为server.js,然后在终端中运行:

node server.js

打开浏览器,访问http://localhost:3000/,你将看到"Hello, World!"的响应。

HTTP请求和响应对象

在创建HTTP服务器时,我们通过回调函数接收两个参数:req(请求对象)和res(响应对象)。

请求对象(req)

请求对象包含客户端发送的请求信息,主要属性和方法包括:

  • url:请求的URL路径
  • method:HTTP请求方法(GET, POST等)
  • headers:HTTP请求头
  • on('data', callback):监听请求体数据
  • on('end', callback):监听请求体数据接收完成

响应对象(res)

响应对象用于向客户端发送响应,主要方法包括:

  • writeHead(statusCode, headers):设置HTTP响应头
  • write(data):发送HTTP响应体数据
  • end(data):结束响应,可选地发送最后一块数据
  • setHeader(name, value):设置单个响应头

处理不同的URL路径

我们可以根据请求的URL路径来提供不同的响应内容:

const http = require('http');

const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });

// 根据URL路径提供不同的响应
if (req.url === '/') {
res.end('欢迎访问首页!\n');
} else if (req.url === '/about') {
res.end('关于我们页面\n');
} else if (req.url === '/contact') {
res.end('联系我们页面\n');
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 页面未找到\n');
}
});

const PORT = 3000;
server.listen(PORT, () => {
console.log(`服务器运行在 http://localhost:${PORT}/`);
});

处理不同的HTTP请求方法

我们可以根据HTTP请求方法来执行不同的操作:

const http = require('http');

const server = http.createServer((req, res) => {
const { url, method } = req;

if (url === '/api/data') {
if (method === 'GET') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: '这是GET请求返回的数据' }));
} else if (method === 'POST') {
let body = '';

// 接收请求体数据
req.on('data', chunk => {
body += chunk.toString();
});

// 请求体数据接收完成
req.on('end', () => {
console.log('接收到的POST数据:', body);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'POST请求已处理' }));
});
} else {
res.writeHead(405, { 'Content-Type': 'text/plain' });
res.end('方法不允许');
}
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 页面未找到');
}
});

const PORT = 3000;
server.listen(PORT, () => {
console.log(`服务器运行在 http://localhost:${PORT}/`);
});

提供静态文件服务

我们可以使用Node.js的fs模块和path模块来提供静态文件服务:

const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer((req, res) => {
// 确定请求的文件路径
let filePath = '.' + req.url;
if (filePath === './') {
filePath = './index.html'; // 默认首页
}

// 获取文件扩展名
const extname = String(path.extname(filePath)).toLowerCase();

// 设置MIME类型
const mimeTypes = {
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.wav': 'audio/wav',
'.mp4': 'video/mp4',
'.woff': 'application/font-woff',
'.ttf': 'application/font-ttf',
'.eot': 'application/vnd.ms-fontobject',
'.otf': 'application/font-otf',
'.wasm': 'application/wasm'
};

const contentType = mimeTypes[extname] || 'application/octet-stream';

// 读取并提供文件
fs.readFile(filePath, (error, content) => {
if (error) {
if (error.code === 'ENOENT') {
// 文件不存在
fs.readFile('./404.html', (err, content) => {
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end(content, 'utf-8');
});
} else {
// 服务器错误
res.writeHead(500);
res.end(`服务器错误: ${error.code}`);
res.end();
}
} else {
// 成功读取文件
res.writeHead(200, { 'Content-Type': contentType });
res.end(content, 'utf-8');
}
});
});

const PORT = 3000;
server.listen(PORT, () => {
console.log(`静态文件服务器运行在 http://localhost:${PORT}/`);
});

使用Express.js框架

虽然Node.js的http模块可以创建HTTP服务器,但在实际项目中,我们通常使用Express.js等框架来简化开发。Express.js是一个轻量级的Web应用框架,提供了更简洁的API和更多的功能。

以下是使用Express.js创建HTTP服务器的简单示例:

// 首先需要安装Express:npm install express
const express = require('express');
const app = express();
const PORT = 3000;

// 中间件,用于解析JSON请求体
app.use(express.json());

// 路由
app.get('/', (req, res) => {
res.send('Hello, World!');
});

app.get('/about', (req, res) => {
res.send('关于我们页面');
});

app.post('/api/data', (req, res) => {
console.log('接收到的POST数据:', req.body);
res.json({ message: 'POST请求已处理' });
});

// 静态文件服务
app.use(express.static('public'));

// 404 处理
app.use((req, res) => {
res.status(404).send('404 页面未找到');
});

// 启动服务器
app.listen(PORT, () => {
console.log(`Express服务器运行在 http://localhost:${PORT}/`);
});

服务器事件处理

HTTP服务器是一个EventEmitter对象,它可以触发多种事件,我们可以监听这些事件来处理特定情况:

const http = require('http');

const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World!\n');
});

// 监听连接事件
server.on('connection', (socket) => {
console.log('新的连接已建立');
});

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

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

const PORT = 3000;
server.listen(PORT, () => {
console.log(`服务器运行在 http://localhost:${PORT}/`);
});

// 5秒后关闭服务器(仅用于演示)
// setTimeout(() => {
// server.close();
// }, 5000);

使用HTTPS

如果需要创建HTTPS服务器,我们可以使用Node.js的https模块。创建HTTPS服务器需要SSL证书和私钥:

const https = require('https');
const fs = require('fs');

// 读取SSL证书和私钥
const options = {
key: fs.readFileSync('privatekey.pem'),
cert: fs.readFileSync('certificate.pem')
};

// 创建HTTPS服务器
const server = https.createServer(options, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('这是一个HTTPS服务器\n');
});

const PORT = 443;
server.listen(PORT, () => {
console.log(`HTTPS服务器运行在 https://localhost:${PORT}/`);
});

注意:在生产环境中,你应该使用由受信任的证书颁发机构(CA)签发的SSL证书。对于开发环境,你可以使用自签名证书,或者使用工具如mkcert来生成本地开发证书。

性能优化技巧

  • 使用连接池管理数据库连接
  • 启用gzip压缩
  • 使用缓存机制
  • 优化静态资源(压缩、CDN等)
  • 使用集群模式充分利用多核CPU

集群模式示例

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
console.log(`主进程 ${process.pid} 正在运行`);

// 创建工作进程
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}

cluster.on('exit', (worker, code, signal) => {
console.log(`工作进程 ${worker.process.pid} 已退出`);
});
} else {
// 工作进程创建HTTP服务器
http.createServer((req, res) => {
res.writeHead(200);
res.end('Hello, World!\n');
}).listen(3000);

console.log(`工作进程 ${process.pid} 已启动`);
}

最佳实践

  • 始终处理错误,包括请求处理过程中的错误和服务器错误
  • 使用适当的HTTP状态码
  • 设置正确的响应头
  • 对于生产环境,考虑使用进程管理器如PM2来管理Node.js进程
  • 实现日志记录,便于调试和监控
  • 考虑使用反向代理如Nginx来处理静态资源、负载均衡和SSL终端
  • 对敏感数据进行加密处理