Files
image-service/app.js

80 lines
2.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require('dotenv').config();
const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
const {sendResponse, isSafePath, processImage} = require("./utils");
const PORT = process.env.PORT || 3000;
const IMAGE_BASE_DIR = process.env.IMAGE_BASE_DIR || '/app/images';
const server = http.createServer(async (req, res) => {
if (req.method !== 'GET') {
return sendResponse(res, 405, '仅支持GET请求');
}
try {
const parsedUrl = url.parse(req.url, true);
const requestPath = parsedUrl.pathname;
const query = parsedUrl.query;
// 过滤根路径请求(避免直接访问服务根目录)
if (requestPath === '/') {
return sendResponse(res, 200, '图片处理服务已启动!');
}
const requestedFilePath = requestPath.slice(1);
const fullImagePath = path.join(IMAGE_BASE_DIR, requestedFilePath);
// 安全检查:防止路径遍历
if (!isSafePath(fullImagePath, IMAGE_BASE_DIR)) {
return sendResponse(res, 403, '访问拒绝:非法路径(路径遍历攻击)');
}
if (!fs.existsSync(fullImagePath)) {
return sendResponse(res, 404, `图片不存在:${requestedFilePath}`);
}
// 如果没有压缩参数,直接返回原图
if (!query.q && !query.w && !query.width && !query.h && !query.height) {
const fileStream = fs.createReadStream(fullImagePath);
const ext = path.extname(fullImagePath).slice(1);
res.writeHead(200, {'Content-Type': `image/${ext}`});
// 流式传输文件(适合大文件)
fileStream.pipe(res);
fileStream.on('error', (err) => {
sendResponse(res, 500, `读取文件失败:${err.message}`);
});
return;
}
// 处理图片压缩和调整大小
const imageBuffer = await processImage(fullImagePath, query);
res.writeHead(200, {
'Content-Type': 'image/jpeg',
'Content-Length': imageBuffer.length,
'Cache-Control': 'public, max-age=86400' // 缓存1天
});
res.end(imageBuffer);
} catch (error) {
console.error('服务器异常:', error);
sendResponse(res, 500, `服务器内部错误:${error.message}`);
}
});
// ===================== 启动服务器 =====================
server.listen(PORT, '0.0.0.0', () => {
console.log(`服务地址http://0.0.0.0:${PORT}`);
});
// 捕获全局未处理异常
process.on('uncaughtException', (err) => {
console.error('全局未捕获异常:', err);
});
process.on('unhandledRejection', (reason) => {
console.error('全局未处理Promise拒绝', reason);
});