Improvements

This commit is contained in:
jason5ng32 committed 2026-04-18 19:45:11 +08:00
1 parent ca4db706df
commit 57f03e66ec
10 files changed
+22 -22

No files matched your search

+3 -3
View File
@@ -1,4 +1,4 @@
# 第一阶段:构建
# Build stage
FROM node:24-alpine AS build-stage
WORKDIR /app
COPY package*.json ./
@@ -6,7 +6,7 @@ RUN npm install
COPY . .
RUN npm run build
# 第二阶段:运行
# Production stage
FROM node:24-alpine AS production-stage
WORKDIR /app
COPY --from=build-stage /app/node_modules ./node_modules
@@ -19,5 +19,5 @@ COPY --from=build-stage /app/common ./common
EXPOSE 18966
# 启动应用
# Start application
CMD ["npm", "start"]
+13 -13
View File
@@ -49,7 +49,7 @@ const speedLimitSet = parseInt(process.env.SECURITY_DELAY_AFTER || 0, 10);
app.set('trust proxy', 1);
// 获取客户端 IP 的辅助函数。
// Helper function to get client IP
function getClientIp(req) {
const cfIp = req.headers['cf-connecting-ip']; // Cloudflare IP
const forwardedIps = req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'].split(',')[0] : null;
@@ -57,23 +57,23 @@ function getClientIp(req) {
return cfIp || forwardedIps || cfIpV6 || req.ip;
}
// 将时间戳格式化为限流日志使用的上海时区时间。
// Format timestamp for rate limit log using Shanghai time zone
function formatDate(timestamp) {
return new Date(timestamp).toLocaleString('en-US', { timeZone: 'Asia/Shanghai' });
}
// 将触发限流的 IP 写入日志,并累计同一个 IP 被限制的次数。
// Write IP that triggered the limit to the log and count the number of times the same IP was limited
function logLimitedIP(ip) {
const logPath = path.join(__dirname, blackListIPLogFilePath);
// 如果 logs 目录不存在,则创建
// If logs directory does not exist, create it
const logDir = path.dirname(logPath);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
console.log('Created log directory:', logDir);
}
// 读取日志文件,更新 IP 计数,如果文件不存在则创建新的日志文件
// Read log file, update IP count, create new log file if it does not exist
fs.readFile(logPath, 'utf8', (err, data) => {
if (err && err.code !== 'ENOENT') {
console.error('Error reading the log file:', err);
@@ -117,7 +117,7 @@ const rateLimiter = rateLimit({
windowMs: 20 * 60 * 1000,
max: rateLimitSet,
message: 'Too Many Requests',
// 处理超过限流阈值的请求,并按需记录触发限流的 IP。
// Handle requests that exceed the rate limit threshold, and record the IP that triggered the limit as needed
handler: (req, res, next) => {
const ip = getClientIp(req);
if (req.rateLimit.current === req.rateLimit.limit + 1 && blackListIPLogFilePath) {
@@ -130,17 +130,17 @@ const rateLimiter = rateLimit({
const speedLimiter = slowDown({
windowMs: 60 * 60 * 1000,
delayAfter: speedLimitSet,
// 根据命中次数逐步增加响应延迟。
// Increase response delay gradually based on the number of hits
delayMs: (hits) => hits * 400,
})
// 如果 rateLimitSet 为 0,则不启用限流
// If rateLimitSet is 0, do not enable rate limiting
if (rateLimitSet !== 0) {
app.use('/api', rateLimiter);
console.log('Rate limiter is enabled, limit:', rateLimitSet, 'requests per 60 minutes');
}
// 如果 deleyAfter 为 0,则不启用延迟
// If delayAfter is 0, do not enable delay
if (speedLimitSet !== 0) {
app.use('/api', speedLimiter);
console.log('Speed limiter is enabled, slowing down after:', speedLimitSet, 'requests');
@@ -170,17 +170,17 @@ app.get('/api/maxmind', requireValidIP(), maxmindHandler);
app.get('/api/getuserinfo', getUserinfo);
app.put('/api/updateuserachievement', updateUserAchievement);
// 使用查询参数处理所有配置请求
// Handle all configuration requests using query parameters
app.get('/api/configs', validateConfigs);
// 设置静态文件服务
// Set static file server
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
app.use(express.static(path.join(__dirname, './dist')));
// 启动服务器
// Start server
app.listen(backEndPort, () => {
// 输出监听地址,便于本地运行和进程管理器日志排查。
// Output listening address, for local running and process manager log troubleshooting
console.log(`Backend server running on http://localhost:${backEndPort}`);
});
+3 -3
View File
@@ -4,8 +4,8 @@ services:
myip:
container_name: myip
image: jason5ng32/myip:latest # my-app: x.x.x
stdin_open: true # docker run -i 交互模式
tty: true # docker run -t 终端模式
restart: always # 重启策略 / on-failure:5 重启次数5次 / always 一直重启 / unless-stopped 除非停止 / no 从不重启
stdin_open: true # docker run -i interactive mode
tty: true # docker run -t terminal mode
restart: always # restart policy / on-failure:5 restart 5 times / always restart forever / unless-stopped unless stopped / no never restart
ports:
- "18966:18966"
+3 -3
View File
@@ -14,16 +14,16 @@ const frontEndPort = parseInt(process.env.FRONTEND_PORT || 18966, 10);
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// API 请求代理到后端服务
// API Proxy to backend server
frontendApp.use('/api', createProxyMiddleware({
target: `http://localhost:${backEndPort}/api`,
changeOrigin: true
}));
// 设置静态文件目录
// Set static file directory
frontendApp.use(express.static(path.join(__dirname, './dist')));
// 启动静态文件服务
// Start static file server
frontendApp.listen(frontEndPort, () => {
console.log(`Static file server running on port http://localhost:${frontEndPort}`);
});
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB