Skip to content

Commit 7d2c60d

Browse files
authored
Merge pull request #23 from ShieldTech-Ltd/fix/vercel-proxy-rate-limit
fix: trust Vercel proxy for API rate limiting
2 parents 1d00107 + c4826af commit 7d2c60d

2 files changed

Lines changed: 7 additions & 0 deletions

File tree

server.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const path = require('path');
1111

1212
// Middleware
1313
app.disable('x-powered-by');
14+
app.set('trust proxy', 1);
1415
app.use(helmet({ contentSecurityPolicy: false, crossOriginEmbedderPolicy: false }));
1516
app.use(express.json({ limit: '32kb' }));
1617
app.use('/api/', rateLimit({ windowMs: 60_000, limit: 120, standardHeaders: 'draft-7', legacyHeaders: false }));
@@ -375,6 +376,7 @@ app.use((req, res) => res.status(404).json({ error: 'Not found' }));
375376
app.use((error, req, res, next) => {
376377
console.error(error.message);
377378
if (res.headersSent) return next(error);
379+
if (error.type === 'entity.parse.failed') return res.status(400).json({ error: 'Invalid JSON body' });
378380
return res.status(502).json({ error: 'Upstream service unavailable' });
379381
});
380382

test/api.test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ test('validates scanner and payslip input', async () => {
2222
await request(app).post('/api/v1/payslip/decode').send({ grossSalary: -1, pensionRate: 5 }).expect(400);
2323
});
2424

25+
test('returns 400 for malformed JSON', async () => {
26+
await request(app).post('/api/v1/scan')
27+
.set('Content-Type', 'application/json').send('{broken').expect(400, { error: 'Invalid JSON body' });
28+
});
29+
2530
test('caption analysis is explicitly not OCR', async () => {
2631
const response = await request(app).post('/api/v1/scan/ocr')
2732
.send({ rawCaption: 'Guaranteed 50x leverage returns' }).expect(200);

0 commit comments

Comments
 (0)