'use strict'; require('dotenv').config(); const express = require('express'); const helmet = require('helmet'); const rateLimit = require('express-rate-limit'); const eraseRoute = require('./routes/erase'); const gmailOAuth = require('./routes/gmail_oauth'); const egosearch = require('./routes/egosearch'); const app = express(); // trust proxy: loopback para que req.ip use X-Forwarded-For correctamente, // pero el keyGenerator de rate-limit usa X-Real-IP (imposible de spoofear por clientes) // porque Nginx lo establece desde $remote_addr (dirección TCP real). app.set('trust proxy', 'loopback'); app.disable('x-powered-by'); app.use(helmet()); app.use(express.json({ limit: '10kb' })); /* Extrae la IP real desde X-Real-IP (puesto por Nginx con $remote_addr). No puede ser manipulado por el cliente — Nginx sobreescribe este header. */ function realIp(req) { return req.headers['x-real-ip'] || req.ip || '0.0.0.0'; } // Rate limiting general — usa IP real (anti-bypass X-Forwarded-For) app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100, standardHeaders: true, legacyHeaders: false, keyGenerator: realIp, })); // Rate limiting específico para envío de emails (más estricto) const emailLimit = rateLimit({ windowMs: 60 * 60 * 1000, // 1 hora max: 10, message: { error: 'Demasiadas solicitudes de envío. Espera antes de reintentar.' }, keyGenerator: realIp, }); // ── Rate limits específicos ─────────────────────────────────────── const searchLimit = rateLimit({ windowMs: 60 * 1000, // 1 minuto max: 8, message: { error: 'Demasiadas búsquedas. Espera un momento.' }, keyGenerator: realIp, }); // ── Rutas ──────────────────────────────────────────────────────── app.post('/api/erase', emailLimit, eraseRoute); app.get('/api/egosearch', searchLimit, egosearch); app.get('/api/gmail/auth', emailLimit, gmailOAuth.authInit); app.get('/api/gmail/callback', gmailOAuth.authCallback); // Health check app.get('/api/health', (req, res) => res.json({ status: 'ok' })); // ── Arranque ───────────────────────────────────────────────────── const PORT = process.env.PORT || 8787; const server = app.listen(PORT, '127.0.0.1', () => { console.log(`RESETEA backend corriendo en 127.0.0.1:${PORT}`); if (!process.env.GOOGLE_CLIENT_ID) { console.warn('⚠ GOOGLE_CLIENT_ID no configurado — OAuth Gmail deshabilitado'); } if (!process.env.SALT) { console.warn('⚠ SALT no configurado en .env — el hash de referencia usa salt por defecto'); } }); // Mitigación Slowloris: timeout en headers y body incompletos server.headersTimeout = 10_000; // 10 s para recibir los headers completos server.requestTimeout = 15_000; // 15 s para recibir el body completo server.keepAliveTimeout = 5_000; // cierra keep-alive inactivos tras 5 s