mirror of
https://github.com/jason5ng32/MyIP.git
synced 2026-11-04 08:55:47 +00:00
Improvements
This commit is contained in:
1 parent
ca4db706df
commit
57f03e66ec
10 files changed
+22
-22
No files matched your search
+3
-3
@@ -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
@@ -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
@@ -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
@@ -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 |
Reference in new issue
Block a user