From 8e2c562c2506cb48989ae857509e7a6dd8d89420 Mon Sep 17 00:00:00 2001 From: Benny Thomas Date: Wed, 11 Mar 2026 09:47:25 +0100 Subject: [PATCH] feat(api-gateway): support timeoutInMillis for http events Add support for configuring API Gateway integration timeout via timeoutInMillis on individual http events or as a default through provider.apiGateway.timeoutInMillis. Event-level config takes precedence over the provider default. Closes #651 Co-Authored-By: Claude Sonnet 4.6 --- lib/deploy/events/apiGateway/methods.js | 1 + lib/deploy/events/apiGateway/methods.test.js | 15 ++++ lib/deploy/events/apiGateway/validate.js | 7 ++ lib/deploy/events/apiGateway/validate.test.js | 68 +++++++++++++++++++ 4 files changed, 91 insertions(+) diff --git a/lib/deploy/events/apiGateway/methods.js b/lib/deploy/events/apiGateway/methods.js index bad6476a..acef49b1 100644 --- a/lib/deploy/events/apiGateway/methods.js +++ b/lib/deploy/events/apiGateway/methods.js @@ -191,6 +191,7 @@ module.exports = { stateMachineObj, http, ), + ...(http && http.timeoutInMillis && { TimeoutInMillis: http.timeoutInMillis }), }; let responses; diff --git a/lib/deploy/events/apiGateway/methods.test.js b/lib/deploy/events/apiGateway/methods.test.js index 8dc81999..cda73f52 100644 --- a/lib/deploy/events/apiGateway/methods.test.js +++ b/lib/deploy/events/apiGateway/methods.test.js @@ -133,6 +133,21 @@ describe('#methods()', () => { .to.equal('\'*\''); }); + it('should set TimeoutInMillis when timeoutInMillis is provided', + () => { + const integration = serverlessStepFunctions.getMethodIntegration('stateMachine', undefined, { + timeoutInMillis: 10000, + }).Properties.Integration; + expect(integration.TimeoutInMillis).to.equal(10000); + }); + + it('should not set TimeoutInMillis when timeoutInMillis is not provided', + () => { + const integration = serverlessStepFunctions + .getMethodIntegration('stateMachine').Properties.Integration; + expect(integration.TimeoutInMillis).to.equal(undefined); + }); + it('should change passthroughBehavior and action when action is set', () => { expect(serverlessStepFunctions.getMethodIntegration('stateMachine', 'custom', { diff --git a/lib/deploy/events/apiGateway/validate.js b/lib/deploy/events/apiGateway/validate.js index 543f93ae..c0e4dd6c 100644 --- a/lib/deploy/events/apiGateway/validate.js +++ b/lib/deploy/events/apiGateway/validate.js @@ -21,6 +21,13 @@ module.exports = { http.authorizer = this.getAuthorizer(http, stateMachineName); } + if (!http.timeoutInMillis) { + const providerTimeout = _.get(this.serverless.service.provider.apiGateway, 'timeoutInMillis'); + if (providerTimeout) { + http.timeoutInMillis = providerTimeout; + } + } + if (http.cors) { http.cors = this.getCors(http); diff --git a/lib/deploy/events/apiGateway/validate.test.js b/lib/deploy/events/apiGateway/validate.test.js index b7c5233c..e7e15a4c 100644 --- a/lib/deploy/events/apiGateway/validate.test.js +++ b/lib/deploy/events/apiGateway/validate.test.js @@ -822,4 +822,72 @@ describe('#httpValidate()', () => { expect(validated.events[0].http.cors.origin).to.equal('*'); expect(validated.events[0].http.cors.maxAge).to.equal(86400); }); + + it('should pass timeoutInMillis from the http event', () => { + serverlessStepFunctions.serverless.service.stepFunctions = { + stateMachines: { + first: { + events: [ + { + http: { + method: 'POST', + path: '/foo/bar', + timeoutInMillis: 10000, + }, + }, + ], + }, + }, + }; + + const validated = serverlessStepFunctions.httpValidate(); + expect(validated.events[0].http.timeoutInMillis).to.equal(10000); + }); + + it('should use provider.apiGateway.timeoutInMillis as default when not set on event', () => { + serverlessStepFunctions.serverless.service.provider.apiGateway = { + timeoutInMillis: 15000, + }; + serverlessStepFunctions.serverless.service.stepFunctions = { + stateMachines: { + first: { + events: [ + { + http: { + method: 'POST', + path: '/foo/bar', + }, + }, + ], + }, + }, + }; + + const validated = serverlessStepFunctions.httpValidate(); + expect(validated.events[0].http.timeoutInMillis).to.equal(15000); + }); + + it('should prefer event-level timeoutInMillis over provider default', () => { + serverlessStepFunctions.serverless.service.provider.apiGateway = { + timeoutInMillis: 15000, + }; + serverlessStepFunctions.serverless.service.stepFunctions = { + stateMachines: { + first: { + events: [ + { + http: { + method: 'POST', + path: '/foo/bar', + timeoutInMillis: 5000, + }, + }, + ], + }, + }, + }; + + const validated = serverlessStepFunctions.httpValidate(); + expect(validated.events[0].http.timeoutInMillis).to.equal(5000); + }); });