西安优秀的集团门户网站建设公司b2b网站
下面我将为你提供四个实战项目的完整实现代码,每个项目都展示了Express中间件的实际应用场景。
1. API网关实现
const express = require('express');
const rateLimit = require('express-rate-limit');
const helmet = require('helmet');
const morgan = require('morgan');const app = express();// 1. 安全中间件
app.use(helmet());// 2. 请求日志
app.use(morgan('combined'));// 3. API密钥验证
app.use((req, res, next) => {const apiKey = req.headers['x-api-key'];const validKeys = ['key123', 'key456'];if (!validKeys.includes(apiKey)) {return res.status(401).json({ error: 'Invalid API Key' });}next();
});// 4. 限流中间件
const apiLimiter = rateLimit({windowMs: 15 * 60 * 1000, // 15分钟max: 100, // 每个IP限制100个请求message: 'Too many requests from this IP, please try again later'
});
app.use(apiLimiter);// 5. 路由转发
const { createProxyMiddleware } = require('http-proxy-middleware');
app.use('/users', createProxyMiddleware({ target: 'http://user-service:3000', changeOrigin: true
}));
app.use('/products', createProxyMiddleware({ target: 'http://product-service:3000', changeOrigin: true
}));// 6. 错误处理
app.use((err, req, res, next) => {console.error(err.stack);res.status(500).json({ error: 'Internal Server Error' });
});app.listen(3000, () => {console.log('API Gateway running on port 3000');
});
2. 文件处理管道
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const sharp = require('sharp');const app = express();// 1. 文件存储配置
const storage = multer.diskStorage({destination: (req, file, cb) => {const uploadDir = 'uploads/';if (!fs.existsSync(uploadDir)) {fs.mkdirSync(uploadDir);}cb(null, uploadDir);},filename: (req, file, cb) => {cb(null, `${Date.now()}-${file.originalname}`);}
});const upload = multer({ storage });// 2. 文件类型验证中间件
function validateFile(req, res, next) {const allowedTypes = ['image/jpeg', 'image/png'];if (!allowedTypes.includes(req.file.mimetype)) {return res.status(400).json({ error: 'Invalid file type' });}next();
}// 3. 图片处理中间件
async function processImage(req, res, next) {try {const outputPath = `processed/${req.file.filename}`;await sharp(req.file.path).resize(800, 800, { fit: 'inside' }).toFormat('jpeg', { quality: 80 }).toFile(outputPath);req.file.processedPath = outputPath;next();} catch (err) {next(err);}
}// 4. 文件上传路由
app.post('/upload', upload.single('file'), // 1. 接收文件validateFile, // 2. 验证类型processImage, // 3. 处理图片(req, res) => { // 4. 返回结果res.json({ original: req.file.path,processed: req.file.processedPath });}
);// 错误处理
app.use((err, req, res, next) => {console.error(err);res.status(500).json({ error: 'File processing failed' });
});app.listen(3000, () => {console.log('File processor running on port 3000');
});
3. A/B测试框架
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();app.use(cookieParser());// 1. A/B测试分配中间件
app.use((req, res, next) => {// 如果已经有分组cookie,继续使用if (req.cookies.abTestGroup) {req.abTestGroup = req.cookies.abTestGroup;return next();}// 随机分配A组或B组const group = Math.random() < 0.5 ? 'A' : 'B';res.cookie('abTestGroup', group, { maxAge: 30 * 24 * 60 * 60 * 1000 }); // 30天req.abTestGroup = group;next();
});// 2. 不同版本的页面处理
function variantA(req, res) {res.send(`<h1 style="color: blue">Version A</h1><p>This is the original version of our page</p>`);
}function variantB(req, res) {res.send(`<h1 style="color: green">Version B</h1><p>This is the experimental version of our page</p>`);
}// 3. 路由处理
app.get('/home', (req, res) => {// 根据分组显示不同版本req.abTestGroup === 'A' ? variantA(req, res) : variantB(req, res);
});// 4. 结果跟踪
app.get('/track-conversion', (req, res) => {const { group } = req.query;console.log(`Conversion recorded for group ${group}`);res.sendStatus(200);
});// 5. 分析仪表板
app.get('/dashboard', (req, res) => {// 这里应该是从数据库获取实际数据const stats = {A: { views: 1000, conversions: 100 },B: { views: 950, conversions: 120 }};res.json(stats);
});app.listen(3000, () => {console.log('A/B Testing Framework running on port 3000');
});
4. 多租户系统
const express = require('express');
const app = express();// 模拟租户数据
const tenants = {'tenant1': { dbConfig: { host: 'tenant1.db.example.com',name: 'tenant1_db'},theme: 'blue'},'tenant2': { dbConfig: { host: 'tenant2.db.example.com',name: 'tenant2_db'},theme: 'green'}
};// 1. 租户识别中间件
app.use((req, res, next) => {// 从子域名识别租户 (tenant1.example.com)const hostParts = req.hostname.split('.');const tenantId = hostParts.length > 2 ? hostParts[0] : null;// 或者从请求头识别// const tenantId = req.headers['x-tenant-id'];if (!tenantId || !tenants[tenantId]) {return res.status(404).send('Tenant not found');}req.tenant = tenants[tenantId];req.tenant.id = tenantId;next();
});// 2. 租户数据库连接中间件
app.use((req, res, next) => {// 模拟数据库连接console.log(`Connecting to tenant database: ${req.tenant.dbConfig.host}`);// 实际应用中这里会建立数据库连接next();
});// 3. 租户特定路由
app.get('/dashboard', (req, res) => {res.send(`<h1 style="color: ${req.tenant.theme}">Dashboard for ${req.tenant.id}</h1><p>Connected to database: ${req.tenant.dbConfig.name}</p>`);
});// 4. 租户配置API
app.get('/api/config', (req, res) => {res.json({tenant: req.tenant.id,theme: req.tenant.theme,dbConfig: req.tenant.dbConfig});
});// 错误处理
app.use((err, req, res, next) => {console.error(`[${req.tenant?.id}]`, err);res.status(500).send('Tenant-specific error occurred');
});app.listen(3000, () => {console.log('Multi-tenant system running on port 3000');
});
项目部署与测试建议
-
API网关:
- 测试不同API密钥的访问
- 测试限流功能
- 使用Postman测试路由转发
-
文件处理管道:
- 测试不同文件类型的上传
- 检查处理后的图片质量
- 测试大文件上传性能
-
A/B测试框架:
- 清除cookie测试分组分配
- 模拟转换事件
- 分析不同版本的表现
-
多租户系统:
- 测试不同子域名的访问
- 模拟租户特定的错误
- 测试租户隔离性