Skip to content

Commit

Permalink
feat(apigateway): Add LambdaIntegrationOptions to LambdaRestApi (#17065)
Browse files Browse the repository at this point in the history
This adds an `integrationOptions` field to the `LambdaRestApiProps` and ensures that `proxy` cannot be set differently from the base `proxy` flag (but discourages setting it at all). This will allow setting the `cacheKeyParameters`, `allowTestInvoke`, and `vpcLink` configuration fields without having to fall back to using a regular `RestApi`.

Some of this is inspired by #12004 and its review comments, which was closed earlier this year due to inactivity.

Resolves: #3269

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
kylelaker committed Jun 22, 2022
1 parent fb5ebdd commit b117469
Show file tree
Hide file tree
Showing 16 changed files with 2,538 additions and 4 deletions.
15 changes: 15 additions & 0 deletions packages/@aws-cdk/aws-apigateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,21 @@ item.addMethod('GET'); // GET /items/{item}
item.addMethod('DELETE', new apigateway.HttpIntegration('http://amazon.com'));
```

Additionally, `integrationOptions` can be supplied to explicitly define
options of the Lambda integration:

```ts
declare const backend: lambda.Function;

const api = new apigateway.LambdaRestApi(this, 'myapi', {
handler: backend,
integrationOptions: {
allowTestInvoke: false,
timeout: Duration.seconds(1),
}
})
```

## AWS StepFunctions backed APIs

You can use Amazon API Gateway with AWS Step Functions as the backend integration, specifically Synchronous Express Workflows.
Expand Down
13 changes: 10 additions & 3 deletions packages/@aws-cdk/aws-apigateway/lib/lambda-api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as lambda from '@aws-cdk/aws-lambda';
import { Construct } from 'constructs';
import { LambdaIntegration } from './integrations';
import { LambdaIntegration, LambdaIntegrationOptions } from './integrations';
import { Method } from './method';
import { ProxyResource, Resource } from './resource';
import { RestApi, RestApiProps } from './restapi';
Expand All @@ -14,6 +14,13 @@ export interface LambdaRestApiProps extends RestApiProps {
*/
readonly handler: lambda.IFunction;

/**
* Specific Lambda integration options.
*
* @default see defaults defined in {@link LambdaIntegrationOptions}.
*/
readonly integrationOptions?: LambdaIntegrationOptions;

/**
* If true, route all requests to the Lambda Function
*
Expand Down Expand Up @@ -43,12 +50,12 @@ export interface LambdaRestApiProps extends RestApiProps {
*/
export class LambdaRestApi extends RestApi {
constructor(scope: Construct, id: string, props: LambdaRestApiProps) {
if ((props.options && props.options.defaultIntegration) || props.defaultIntegration) {
if (props.options?.defaultIntegration || props.defaultIntegration) {
throw new Error('Cannot specify "defaultIntegration" since Lambda integration is automatically defined');
}

super(scope, id, {
defaultIntegration: new LambdaIntegration(props.handler),
defaultIntegration: new LambdaIntegration(props.handler, props.integrationOptions),
...props.options, // deprecated, but we still support
...props,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Fixture with packages imported, but nothing else
import { Construct } from 'constructs';
import { Stack } from '@aws-cdk/core';
import { Duration, Stack } from '@aws-cdk/core';
import apigateway = require('@aws-cdk/aws-apigateway');
import cognito = require('@aws-cdk/aws-cognito');
import lambda = require('@aws-cdk/aws-lambda');
Expand Down
35 changes: 35 additions & 0 deletions packages/@aws-cdk/aws-apigateway/test/integ.lambda-api-nonproxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Code, Function, Runtime } from '@aws-cdk/aws-lambda';
import { App, Stack } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { LambdaRestApi, PassthroughBehavior } from '../lib';

class LambdaApiIntegrationOptionsNonProxyIntegrationStack extends Stack {
constructor(scope: Construct) {
super(scope, 'LambdaApiIntegrationOptionsNonProxyIntegrationStack');

const fn = new Function(this, 'myfn', {
code: Code.fromInline('foo'),
runtime: Runtime.NODEJS_14_X,
handler: 'index.handler',
});

new LambdaRestApi(this, 'lambdarestapi', {
handler: fn,
integrationOptions: {
proxy: false,
passthroughBehavior: PassthroughBehavior.WHEN_NO_MATCH,
integrationResponses: [
{
statusCode: '200',
responseTemplates: {
'application/json': JSON.stringify({ message: 'Hello, word' }),
},
},
],
},
});
}
}

const app = new App();
new LambdaApiIntegrationOptionsNonProxyIntegrationStack(app);
26 changes: 26 additions & 0 deletions packages/@aws-cdk/aws-apigateway/test/integ.lambda-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Code, Function, Runtime } from '@aws-cdk/aws-lambda';
import { App, Duration, Stack } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { LambdaRestApi } from '../lib';

class LambdaApiIntegrationOptionsStack extends Stack {
constructor(scope: Construct) {
super(scope, 'LambdaApiIntegrationOptionsStack');

const fn = new Function(this, 'myfn', {
code: Code.fromInline('foo'),
runtime: Runtime.NODEJS_14_X,
handler: 'index.handler',
});

new LambdaRestApi(this, 'lambdarestapi', {
handler: fn,
integrationOptions: {
timeout: Duration.seconds(1),
},
});
}
}

const app = new App();
new LambdaApiIntegrationOptionsStack(app);

0 comments on commit b117469

Please sign in to comment.