phase-8g: rate limiting and update readme doc
This commit is contained in:
+22
-1
@@ -1,5 +1,6 @@
|
||||
import Fastify from 'fastify';
|
||||
import Fastify, { type FastifyRequest, type FastifyReply } from 'fastify';
|
||||
import cors from '@fastify/cors';
|
||||
import rateLimit from '@fastify/rate-limit';
|
||||
import { ScreenerController } from './controllers/screener.controller';
|
||||
import { FinanceController } from './controllers/finance.controller';
|
||||
import { CallsController } from './controllers/calls.controller';
|
||||
@@ -31,6 +32,26 @@ export async function buildApp({ logger = true }: BuildAppOptions = {}) {
|
||||
origin: process.env.CLIENT_ORIGIN ?? 'http://localhost:5173',
|
||||
});
|
||||
|
||||
// ── Rate limiting — applied globally, tightest on expensive routes ───────
|
||||
await app.register(rateLimit, {
|
||||
global: false, // opt-in per route via config.rateLimit
|
||||
max: 60,
|
||||
timeWindow: '1 minute',
|
||||
});
|
||||
|
||||
// ── API key auth — only enforced when API_KEY env var is set ─────────────
|
||||
const API_KEY = process.env.API_KEY;
|
||||
if (API_KEY) {
|
||||
app.addHook('onRequest', async (req: FastifyRequest, reply: FastifyReply) => {
|
||||
// Skip auth for health check and OPTIONS preflight
|
||||
if (req.url === '/health' || req.method === 'OPTIONS') return;
|
||||
const header = req.headers['authorization'] ?? '';
|
||||
if (header !== `Bearer ${API_KEY}`) {
|
||||
return reply.code(401).send({ error: 'Unauthorized' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const yahoo = new YahooFinanceClient();
|
||||
const benchmark = new BenchmarkProvider(yahoo, { logger: noopLogger });
|
||||
const engine = new ScreenerEngine(yahoo, benchmark, { logger: noopLogger });
|
||||
|
||||
Reference in New Issue
Block a user