diff --git a/docs/events/apigateway.md b/docs/events/apigateway.md index 4feb8d18c0..3b633d4f3c 100644 --- a/docs/events/apigateway.md +++ b/docs/events/apigateway.md @@ -55,6 +55,9 @@ Summary: - [AWS X-Ray Tracing](#aws-x-ray-tracing) - [Tags / Stack Tags](#tags--stack-tags) - [Logs](#logs) +- [Disable Default Endpoint](#disable-default-endpoint) +- [Providing a custom stage name](#providing-a-custom-stage-name) +- [Timeout](#timeout) _Are you looking for tutorials on using API Gateway? Check out the following resources:_ @@ -1867,3 +1870,33 @@ provider: apiGateway: stage: customStageName ``` + +## Timeout + +By default, the timeout for API Gateway integration is 29 seconds. +You can change this by setting the `timeoutInMillis` property in the `apiGateway` configuration +and overriding it in the `http` event for specific functions. + +**Note:** This is particularly useful if you have requested an increase to the API Gateway integration timeout soft limit +in AWS (which previously had a hard limit of 29 seconds). + +```yml +provider: + apiGateway: + timeoutInMillis: 10000 # Default timeout of 10 seconds for all endpoints + +functions: + fetch: + handler: handler.hello + events: + - http: + path: /posts/{id} + method: get + create: + handler: handler.bye + events: + - http: + path: /posts + method: post + timeoutInMillis: 40000 # Override: 40-second timeout for this endpoint +``` diff --git a/lib/plugins/aws/deploy/lib/extended-validate.js b/lib/plugins/aws/deploy/lib/extended-validate.js index 53e4e70118..c7ca93751c 100644 --- a/lib/plugins/aws/deploy/lib/extended-validate.js +++ b/lib/plugins/aws/deploy/lib/extended-validate.js @@ -41,16 +41,24 @@ module.exports = { const functionObject = this.serverless.service.getFunction(functionName); // Check if function timeout is greater than API Gateway timeout - if (functionObject.timeout > 30 && functionObject.events) { + if (functionObject.timeout && functionObject.events) { functionObject.events.forEach((event) => { if (Object.keys(event)[0] === 'http' && !event.http.async) { - log.warning( - [ - `Function ${functionName} has timeout of ${functionObject.timeout} `, - "seconds, however, it's attached to API Gateway so it's automatically ", - 'limited to 30 seconds.', - ].join('') - ); + const localApiTimeout = event.http && event.http.timeoutInMillis; + const globalApiTimeout = + this.serverless.service && + this.serverless.service.provider && + this.serverless.service.provider.apiGateway && + this.serverless.service.provider.apiGateway.timeoutInMillis; + const apiTimeout = localApiTimeout || globalApiTimeout || 29000 / 1000; // Default to 29 seconds + if (functionObject.timeout > apiTimeout) { + log.warning( + [ + `Function ${functionName} has a timeout of ${functionObject.timeout} seconds, `, + `but it is attached to an API Gateway with a timeout of ${apiTimeout} seconds. `, + ].join('') + ); + } } }); } diff --git a/lib/plugins/aws/package/compile/events/api-gateway/index.js b/lib/plugins/aws/package/compile/events/api-gateway/index.js index 2cf8fa2dd8..09e3fd8bfa 100644 --- a/lib/plugins/aws/package/compile/events/api-gateway/index.js +++ b/lib/plugins/aws/package/compile/events/api-gateway/index.js @@ -208,6 +208,7 @@ class AwsCompileApigEvents { private: { type: 'boolean' }, request: requestSchema, response: responseSchema, + timeoutInMillis: { type: 'integer', minimum: 50 }, }, required: ['path', 'method'], additionalProperties: false, diff --git a/lib/plugins/aws/package/compile/events/api-gateway/lib/method/integration.js b/lib/plugins/aws/package/compile/events/api-gateway/lib/method/integration.js index add99dbd30..972376f2fa 100644 --- a/lib/plugins/aws/package/compile/events/api-gateway/lib/method/integration.js +++ b/lib/plugins/aws/package/compile/events/api-gateway/lib/method/integration.js @@ -51,9 +51,16 @@ const DEFAULT_COMMON_TEMPLATE = ` module.exports = { getMethodIntegration(http, { lambdaLogicalId, lambdaAliasName }) { const type = http.integration || 'AWS_PROXY'; + const globalApiTimeout = + this.serverless.service && + this.serverless.service.provider && + this.serverless.service.provider.apiGateway && + this.serverless.service.provider.apiGateway.timeoutInMillis; + const integration = { IntegrationHttpMethod: 'POST', Type: type, + TimeoutInMillis: http.timeoutInMillis || globalApiTimeout || undefined, }; // Valid integrations are: diff --git a/lib/plugins/aws/provider.js b/lib/plugins/aws/provider.js index 44fcbd3fd3..f067e791cc 100644 --- a/lib/plugins/aws/provider.js +++ b/lib/plugins/aws/provider.js @@ -870,6 +870,7 @@ class AwsProvider { }, shouldStartNameWithService: { type: 'boolean' }, stage: { type: 'string' }, + timeoutInMillis: { type: 'integer', minimum: 50 }, usagePlan: { anyOf: [ apiGatewayUsagePlan,