elearning/Backend/src/app.ts
JakkrapartXD e7ea035a9e add
2026-01-14 04:33:33 +00:00

98 lines
2.8 KiB
TypeScript

import express, { Application, Request, Response } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import swaggerUi from 'swagger-ui-express';
import { config } from './config';
import { logger } from './config/logger';
import { errorHandler } from './middleware/errorHandler';
import { RegisterRoutes } from './routes/routes';
export function createApp(): Application {
const app = express();
// Security middleware - Disable CSP for Swagger UI
app.use(helmet({
contentSecurityPolicy: false
}));
// CORS - Allow multiple origins
const allowedOrigins = config.cors.origin.split(',').map(o => o.trim());
app.use(cors({
origin: (origin, callback) => {
// Allow requests with no origin (like mobile apps, Postman, curl)
if (!origin) return callback(null, true);
// Check if origin is allowed
if (allowedOrigins.includes('*') || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true
}));
// Rate limiting
const limiter = rateLimit({
windowMs: config.rateLimit.windowMs,
max: config.rateLimit.maxRequests,
message: {
error: {
code: 'RATE_LIMIT_EXCEEDED',
message: 'Too many requests, please try again later'
}
}
});
app.use('/api/', limiter);
// Body parsing
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Request logging
app.use((req: Request, res: Response, next) => {
logger.info('Incoming request', {
method: req.method,
path: req.path,
ip: req.ip
});
next();
});
// Swagger documentation
try {
const swaggerDocument = require('../public/swagger.json');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
logger.info('Swagger documentation available at /api-docs');
} catch (error) {
logger.warn('Swagger documentation not available. Run "npm run tsoa:gen" to generate it.');
}
// Simple health check endpoint (not using TSOA)
app.get('/health', (req: Request, res: Response) => {
res.json({
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime()
});
});
// Register TSOA routes
RegisterRoutes(app);
// 404 handler
app.use((req: Request, res: Response) => {
res.status(404).json({
error: {
code: 'NOT_FOUND',
message: 'Route not found'
}
});
});
// Error handler (must be last)
app.use(errorHandler);
return app;
}