diff --git a/.env b/.env index b651f5b..0be06ff 100644 --- a/.env +++ b/.env @@ -22,6 +22,8 @@ PROBE_FAILRATE=30 PROBE_INTERVAL_SECONDS=60 API_BASE_URL=https://selfservice.cqers.com/drones/api +API_DEBUG=true + # Optional: Override default settings # NODE_ENV=production # CORS_ORIGIN=http://localhost:3000 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..67ff557 --- /dev/null +++ b/.gitignore @@ -0,0 +1,59 @@ +# Dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Production build +dist/ +build/ + +# Environment variables +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Logs +logs/ +*.log + +# Debug files +api_debug.log +debug.log +requests.log +responses.log + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo + +# OS files +.DS_Store +Thumbs.db + +# Database +*.sqlite +*.db + +# Docker +.dockerignore + +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +env/ +venv/ +.venv/ +pip-log.txt + +# Temporary files +tmp/ +temp/ +*.tmp +*.temp diff --git a/server/utils/apiDebugLogger.js b/server/utils/apiDebugLogger.js new file mode 100644 index 0000000..81898eb --- /dev/null +++ b/server/utils/apiDebugLogger.js @@ -0,0 +1,132 @@ +const fs = require('fs'); +const path = require('path'); + +class ApiDebugLogger { + constructor() { + this.logFile = path.join(__dirname, '..', 'api_debug.log'); + this.enabled = process.env.NODE_ENV === 'development' || process.env.API_DEBUG === 'true'; + } + + log(method, url, statusCode, requestBody = {}, responseBody = {}, headers = {}) { + if (!this.enabled) return; + + const timestamp = new Date().toISOString(); + const sanitizedRequest = this.sanitizeData(requestBody); + const sanitizedResponse = this.sanitizeData(responseBody); + const sanitizedHeaders = this.sanitizeHeaders(headers); + + const logEntry = [ + `[${timestamp}]`, + method.toUpperCase(), + url, + `-`, + `STATUS:${statusCode}`, + `-`, + `REQ:${JSON.stringify(sanitizedRequest)}`, + `-`, + `RES:${JSON.stringify(sanitizedResponse)}`, + `-`, + `HEADERS:${JSON.stringify(sanitizedHeaders)}` + ].join(' '); + + try { + fs.appendFileSync(this.logFile, logEntry + '\n'); + } catch (error) { + console.error('Failed to write to API debug log:', error); + } + } + + sanitizeData(data) { + if (!data || typeof data !== 'object') return data; + + const sanitized = { ...data }; + + // Remove sensitive fields + const sensitiveFields = ['password', 'token', 'secret', 'key', 'auth', 'authorization']; + + sensitiveFields.forEach(field => { + if (sanitized[field]) { + sanitized[field] = '***REDACTED***'; + } + }); + + return sanitized; + } + + sanitizeHeaders(headers) { + if (!headers || typeof headers !== 'object') return {}; + + const sanitized = { ...headers }; + + // Remove sensitive headers + const sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-auth-token']; + + sensitiveHeaders.forEach(header => { + if (sanitized[header]) { + sanitized[header] = '***REDACTED***'; + } + }); + + return sanitized; + } + + logRequest(req) { + if (!this.enabled) return; + + const timestamp = new Date().toISOString(); + const logEntry = `[${timestamp}] INCOMING ${req.method} ${req.url} - BODY:${JSON.stringify(this.sanitizeData(req.body))} - HEADERS:${JSON.stringify(this.sanitizeHeaders(req.headers))}`; + + try { + fs.appendFileSync(this.logFile, logEntry + '\n'); + } catch (error) { + console.error('Failed to write request to API debug log:', error); + } + } + + logResponse(req, res, responseBody) { + if (!this.enabled) return; + + this.log( + req.method, + req.url, + res.statusCode, + req.body, + responseBody, + { + 'content-type': res.getHeader('content-type'), + 'user-agent': req.headers['user-agent'] + } + ); + } + + clear() { + try { + fs.writeFileSync(this.logFile, '# API Debug Log Cleared at ' + new Date().toISOString() + '\n'); + console.log('API debug log cleared'); + } catch (error) { + console.error('Failed to clear API debug log:', error); + } + } +} + +// Middleware function for Express +function apiDebugMiddleware(req, res, next) { + const logger = new ApiDebugLogger(); + + // Log incoming request + logger.logRequest(req); + + // Override res.json to capture response + const originalJson = res.json; + res.json = function(data) { + logger.logResponse(req, res, data); + return originalJson.call(this, data); + }; + + next(); +} + +module.exports = { + ApiDebugLogger, + apiDebugMiddleware +};