Spaces:
Running
Running
File size: 4,594 Bytes
6279ff0 6acb2cb 6279ff0 1e6a865 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 1e6a865 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 1e6a865 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 6acb2cb 6279ff0 1e6a865 6acb2cb |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
// === 引入依赖 ===
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const requestIp = require('request-ip');
const crypto = require('crypto'); // 用于生成设备指纹的哈希值
const { URL } = require('url'); // 用于验证 URL 格式
const app = express();
// === 配置常量 ===
const PORT = process.env.PORT || 3000;
const HOST = '0.0.0.0';
console.log(`Starting server! PORT: ${PORT}`);
// === 中间件配置 ===
// CORS 配置
const corsOptions = {
origin: '*', // 允许所有来源的请求
methods: ['GET', 'POST', 'OPTIONS'],
allowedHeaders: ['Content-Type'],
};
app.use(cors(corsOptions));
// 使用 Body-Parser 解析 JSON 请求体
app.use(bodyParser.json());
// 使用 request-ip 中间件获取客户端 IP
app.use(requestIp.mw());
// === 内存存储及清理 ===
// URL 存储字典(以用户唯一标识符为键)
const urlMap = new Map();
// 超时时间配置(以毫秒为单位)
const EXPIRATION_TIME = 90 * 1000; // 90 秒
const CLEANUP_INTERVAL = 60 * 1000; // 每 60 秒清理一次
// 定时清理过期数据
setInterval(() => {
const now = Date.now();
const expiredTime = now - EXPIRATION_TIME;
for (const [userId, { timestamp }] of urlMap) {
if (timestamp < expiredTime) {
console.log(`Deleting expired data for user: ${userId}`);
urlMap.delete(userId); // 删除过期数据
}
}
}, CLEANUP_INTERVAL);
// 健康检查
app.get("/", (req, res) => {
res.status(200).send({ message: "Server is healthy and running." });
});
// === 辅助函数 ===
// 生成设备指纹
const generateDeviceFingerprint = (req) => {
const ip = req.clientIp || '';
const userAgent = req.headers['user-agent'] || '';
const acceptLanguage = req.headers['accept-language'] || '';
const connection = req.headers['connection'] || '';
const encoding = req.headers['accept-encoding'] || '';
const forwardedFor = req.headers['x-forwarded-for'] || '';
// 将关键信息合并生成唯一指纹
const rawFingerprint = `${ip}-${userAgent}-${acceptLanguage}-${connection}-${encoding}-${forwardedFor}`;
// 使用 SHA-256 哈希算法生成指纹
const fingerprint = crypto.createHash('sha256').update(rawFingerprint).digest('hex');
return fingerprint;
};
// === 路由 ===
// 存储 URL(POST 请求)
app.post('/storeURL', (req, res) => {
const url = req.body.url; // 从请求体中解析 URL
const ip = req.clientIp; // 获取客户端 IP
// 验证 URL 是否存在并合法
if (!url) {
return res.status(400).json({ error: 'URL is required.' });
}
try {
new URL(url); // 验证 URL 格式
} catch (err) {
return res.status(400).json({ error: 'Invalid URL format.' });
}
// 生成用户唯一标识符(包括 IP 和设备指纹)
const deviceFingerprint = generateDeviceFingerprint(req);
const userId = `${ip}-${deviceFingerprint}`; // 结合 IP 和设备指纹生成唯一标识符
// 存储到字典中
urlMap.set(userId, { url, timestamp: Date.now() });
console.log(`Stored URL for user: ${userId}`);
// 返回成功响应
res.json({ message: 'URL stored successfully.', userId });
});
// 获取 URL(GET 请求)
app.get('/getURL', (req, res) => {
const ip = req.clientIp; // 获取客户端 IP
// 生成用户唯一标识符(包括 IP 和设备指纹)
const deviceFingerprint = generateDeviceFingerprint(req);
const userId = `${ip}-${deviceFingerprint}`;
// 查询字典获取存储的 URL
if (urlMap.has(userId)) {
const storedData = urlMap.get(userId);
storedData.timestamp = Date.now(); // 更新数据时间戳
urlMap.set(userId, storedData); // 保存更新后的数据
console.log(`Retrieved URL for user: ${userId}`);
return res.json({ url: storedData.url });
} else {
console.error(`No URL found for user: ${userId}`);
return res.status(404).json({ error: 'URL not found for this user.' });
}
});
// === 启动服务器 ===
app.listen(PORT, HOST, (err) => {
if (err) {
console.error(`Error starting server: ${err}`);
return;
}
console.log(`Server running on http://${HOST}:${PORT}`);
});
// === 全局错误处理 ===
process.on('uncaughtException', (err) => {
console.error('Uncaught Exception:', err);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
}); |