MichaelEdou
Fix OAuth on reverse proxy (HuggingFace): trust proxy, secure cookies, error display
907039a
// Force Eastern Time for all date operations (Gatineau, QC)
process.env.TZ = 'America/Toronto';
import express from 'express';
import { createServer } from 'http';
import { Server as SocketIOServer } from 'socket.io';
import cors from 'cors';
import helmet from 'helmet';
import cookieParser from 'cookie-parser';
import pino from 'pino';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
import { existsSync } from 'fs';
import { config } from './config/env.js';
import { db } from './db/index.js';
import { setupScanEvents } from './websocket/scanEvents.js';
import authRoutes from './routes/auth.js';
import emailRoutes from './routes/emails.js';
import transactionRoutes from './routes/transactions.js';
import settingsRoutes from './routes/settings.js';
import receiptRoutes from './routes/receipts.js';
import senderRoutes from './routes/senders.js';
import screenshotRoutes from './routes/screenshots.js';
import { errorHandler } from './middleware/errorHandler.js';
const logger = pino({
level: 'info',
transport: {
target: 'pino-pretty',
options: { colorize: true },
},
});
const app = express();
const httpServer = createServer(app);
const corsOrigin = config.APP_URL === '*' ? true : config.APP_URL;
const io = new SocketIOServer(httpServer, {
cors: {
origin: corsOrigin,
methods: ['GET', 'POST'],
credentials: true,
},
path: '/ws',
});
// Trust reverse proxy (HuggingFace, nginx, etc.)
app.set('trust proxy', true);
// Middleware
app.use(
helmet({
contentSecurityPolicy: false,
crossOriginEmbedderPolicy: false,
})
);
app.use(cors({ origin: corsOrigin, credentials: true }));
app.use(express.json({ limit: '10mb' }));
app.use(cookieParser());
// Health check
app.get('/api/health', (_req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Routes
app.use('/api/auth', authRoutes);
app.use('/api/scan', emailRoutes);
app.use('/api/transactions', transactionRoutes);
app.use('/api/settings', settingsRoutes);
app.use('/api/receipts', receiptRoutes);
app.use('/api/senders', senderRoutes);
app.use('/api/screenshots', screenshotRoutes);
// Serve frontend static files in production
const __dirname_server = dirname(fileURLToPath(import.meta.url));
const frontendDist = resolve(__dirname_server, '../../web/dist');
if (existsSync(frontendDist)) {
app.use(express.static(frontendDist));
// SPA fallback — serve index.html for non-API routes (Express 5 syntax)
app.get('{*path}', (_req, res) => {
res.sendFile(resolve(frontendDist, 'index.html'));
});
logger.info(`Serving frontend from ${frontendDist}`);
}
// Error handler
app.use(errorHandler);
// WebSocket setup
setupScanEvents(io);
// Export io for use in services
export { io };
const PORT = config.PORT;
httpServer.listen(PORT, () => {
logger.info(`ICC Interac Manager API running on http://localhost:${PORT}`);
});