diff --git a/packages/api/src/server.ts b/packages/api/src/server.ts index 9d427c47..05c90d3e 100644 --- a/packages/api/src/server.ts +++ b/packages/api/src/server.ts @@ -12,7 +12,8 @@ export const DEFAULT_PORT = 80; export const startServer = (config: Config, port: number) => { const app = express(); - app.use(express.json()); + // The default limit is 100kb, which is not enough for the signed API because some payloads can be quite large. + app.use(express.json({ limit: '10mb' })); app.post('/', async (req, res) => { logger.info('Received request "POST /".', req.body); @@ -46,6 +47,17 @@ export const startServer = (config: Config, port: number) => { }); } + // Inline error handling middleware + app.use((err: any, _req: express.Request, res: express.Response, _next: express.NextFunction) => { + logger.error('An unexpected error occurred.', { err }); + + res.status(err.status || 500).json({ + error: { + message: err.message || 'An unexpected error occurred.', + }, + }); + }); + app.listen(port, () => { logger.info(`Server listening at http://localhost:${port}.`); }); diff --git a/packages/e2e/src/user.test.ts b/packages/e2e/src/user.test.ts index 633a2c96..21426905 100644 --- a/packages/e2e/src/user.test.ts +++ b/packages/e2e/src/user.test.ts @@ -1,3 +1,4 @@ +import { go } from '@api3/promise-utils'; import axios from 'axios'; import { airnode, formatData } from './utils'; @@ -27,3 +28,26 @@ test('respects the delay', async () => { expect(realCount).toBeGreaterThan(0); expect(delayedCount).toBeGreaterThan(0); }, 20_000); + +test('ensures Signed API handles requests with huge payloads', async () => { + const signedData = { + signature: + '0x1ea0a64100431adf033ec730547cd3ffd253dd5991336b3d9b9e8dcfe68d82a61bcd9b8b677557a90a025c19ebde1d98608e2fa3462457bb6fe62675518f7f9c1c', + timestamp: '1701419743', + templateId: '0x031487ca600cd3a26a39206b5b4373f9231f75e4bd23edeb3d5bdc513c147e2a', + encodedValue: '0x000000000000000000000000000000000000000000000003d026ef5a02753000', + airnode: '0x198539e151Fc2CF7642BFfe95B2b7a3Dc08bE0b7', + }; + + const goPostData = await go(async () => + axios.post(`http://localhost:8090`, Array.from({ length: 100_000 }).fill(signedData)) + ); + + expect(goPostData.success).toBe(false); + const error = goPostData.error as any; + expect(error.message).toBe('Request failed with status code 413'); + expect(error.response.status).toBe(413); + expect(error.response.data).toStrictEqual({ + error: { message: 'request entity too large' }, + }); +});