var express = require('express'); var cors = require('cors'); var http = require('http'); var os = require('os'); var app = express(); var PORT = process.env.PORT || 3000; // 启用 CORS app.use(cors()); app.use(express.json()); /** * 获取真实客户端 IP(跨平台兼容) */ function getClientIP(req) { var headers = req.headers; // 优先级:X-Forwarded-For > X-Real-IP > 直连 IP var forwarded = headers['x-forwarded-for']; if (forwarded) { var ips = forwarded.split(','); return ips[0].trim(); } var realIP = headers['x-real-ip']; if (realIP) { return realIP.trim(); } var remoteAddr = req.socket.remoteAddress || req.connection.remoteAddress || req.ip; // IPv6 转 IPv4(兼容 Windows/Linux) if (remoteAddr && remoteAddr.indexOf('::ffff:') === 0) { return remoteAddr.substring(7); } return remoteAddr || 'unknown'; } /** * 只返回 IP(最高效) */ app.get('/api/get-ip', function(req, res) { var ip = getClientIP(req); res.json({ ip: ip, timestamp: new Date().getTime(), server: os.platform() }); }); /** * 返回 IP + 地理位置(带缓存) */ var ipCache = {}; var CACHE_TTL = 10 * 60 * 1000; // 10 分钟 app.get('/api/get-ip-info', function(req, res) { var ip = getClientIP(req); var now = new Date().getTime(); // 检查缓存 var cached = ipCache[ip]; if (cached && (now - cached.timestamp) < CACHE_TTL) { var result = JSON.parse(JSON.stringify(cached.data)); // 深拷贝 result.fromCache = true; return res.json(result); } // 使用原生 http 模块请求(无需额外依赖) var options = { hostname: 'ip-api.com', port: 80, path: '/json/' + encodeURIComponent(ip) + '?lang=zh-CN', method: 'GET', timeout: 5000 }; var request = http.request(options, function(response) { var chunks = []; response.on('data', function(chunk) { chunks.push(chunk); }); response.on('end', function() { var body = Buffer.concat(chunks).toString(); try { var data = JSON.parse(body); var result = { ip: ip, country: data.country || '', region: data.regionName || '', city: data.city || '', isp: data.isp || '', timezone: data.timezone || '', query_time: now, fromCache: false }; // 写入缓存 ipCache[ip] = { data: result, timestamp: now }; // 清理过期缓存(防止内存泄漏) cleanupCache(); res.json(result); } catch (e) { res.json({ ip: ip, error: 'Parse failed', fromCache: false }); } }); }); request.on('error', function(e) { res.json({ ip: ip, error: e.message, fromCache: false }); }); request.on('timeout', function() { request.destroy(); res.json({ ip: ip, error: 'Request timeout', fromCache: false }); }); request.end(); }); /** * 清理过期缓存 */ function cleanupCache() { var now = new Date().getTime(); var keys = Object.keys(ipCache); for (var i = 0; i < keys.length; i++) { var key = keys[i]; if ((now - ipCache[key].timestamp) > CACHE_TTL * 2) { delete ipCache[key]; } } } /** * 健康检查 */ app.get('/health', function(req, res) { res.json({ status: 'ok', uptime: process.uptime(), platform: os.platform(), memory: process.memoryUsage() }); }); // 启动服务器 var server = app.listen(PORT, function() { console.log('🚀 Server running on port ' + PORT); console.log(' Platform: ' + os.platform()); console.log(' Test: http://localhost:' + PORT + '/api/get-ip'); }); // 优雅关闭(兼容 Windows/Linux) process.on('SIGTERM', function() { console.log('SIGTERM received, shutting down...'); server.close(function() { process.exit(0); }); }); process.on('SIGINT', function() { console.log('SIGINT received, shutting down...'); server.close(function() { process.exit(0); }); });