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终端
- 对敏感数据进行加密处理