Skip to content

Commit 2a49fd1

Browse files
authored
fix(apigateway): cannot use requestValidatorOptions multiple times (under feature flag) (#25324)
When using `addMethod` with `requestValidatorOptions` it is not possible to do this multiple times on the same RestApi. The same node id is used for all `RequestValidators` added using this method. This PR adds a new feature flag which when enabled will generate a unique id for the RequestValidators added in this way. fixes #7613 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 74c35dc commit 2a49fd1

File tree

4 files changed

+115
-3
lines changed

4 files changed

+115
-3
lines changed

packages/aws-cdk-lib/aws-apigateway/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,41 @@ resource.addMethod('GET', integration, {
608608
Specifying `requestValidatorOptions` automatically creates the RequestValidator construct with the given options.
609609
However, if you have your RequestValidator already initialized or imported, use the `requestValidator` option instead.
610610

611+
If you want to use `requestValidatorOptions` in multiple `addMethod()` calls
612+
then you need to set the `@aws-cdk/aws-apigateway:requestValidatorUniqueId`
613+
feature flag. When this feature flag is set, each `RequestValidator` will have a unique generated id.
614+
615+
> **Note** if you enable this feature flag when you have already used
616+
> `addMethod()` with `requestValidatorOptions` the Logical Id of the resource
617+
> will change causing the resource to be replaced.
618+
619+
```ts
620+
declare const integration: apigateway.LambdaIntegration;
621+
declare const resource: apigateway.Resource;
622+
declare const responseModel: apigateway.Model;
623+
declare const errorResponseModel: apigateway.Model;
624+
625+
resource.node.setContext('@aws-cdk/aws-apigateway:requestValidatorUniqueId', true);
626+
627+
resource.addMethod('GET', integration, {
628+
// we can set request validator options like below
629+
requestValidatorOptions: {
630+
requestValidatorName: 'test-validator',
631+
validateRequestBody: true,
632+
validateRequestParameters: false
633+
},
634+
});
635+
636+
resource.addMethod('POST', integration, {
637+
// we can set request validator options like below
638+
requestValidatorOptions: {
639+
requestValidatorName: 'test-validator2',
640+
validateRequestBody: true,
641+
validateRequestParameters: false
642+
},
643+
});
644+
```
645+
611646
## Default Integration and Method Options
612647

613648
The `defaultIntegration` and `defaultMethodOptions` properties can be used to

packages/aws-cdk-lib/aws-apigateway/lib/method.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import * as cloudwatch from '../../aws-cloudwatch';
2-
import { ArnFormat, Lazy, Resource, Stack } from '../../core';
31
import { Construct } from 'constructs';
42
import { ApiGatewayMetrics } from './apigateway-canned-metrics.generated';
53
import { CfnMethod, CfnMethodProps } from './apigateway.generated';
@@ -13,6 +11,9 @@ import { IResource } from './resource';
1311
import { IRestApi, RestApi, RestApiBase } from './restapi';
1412
import { IStage } from './stage';
1513
import { validateHttpMethod } from './util';
14+
import * as cloudwatch from '../../aws-cloudwatch';
15+
import { ArnFormat, FeatureFlags, Lazy, Names, Resource, Stack } from '../../core';
16+
import { APIGATEWAY_REQUEST_VALIDATOR_UNIQUE_ID } from '../../cx-api';
1617

1718
export interface MethodOptions {
1819
/**
@@ -360,7 +361,11 @@ export class Method extends Resource {
360361
}
361362

362363
if (options.requestValidatorOptions) {
363-
const validator = (this.api as RestApi).addRequestValidator('validator', options.requestValidatorOptions);
364+
const useUniqueId = FeatureFlags.of(this).isEnabled(APIGATEWAY_REQUEST_VALIDATOR_UNIQUE_ID);
365+
const id = useUniqueId
366+
? `${Names.uniqueResourceName(new Construct(this, 'Validator'), {})}`
367+
: 'validator';
368+
const validator = (this.api as RestApi).addRequestValidator(id, options.requestValidatorOptions);
364369
return validator.requestValidatorId;
365370
}
366371

packages/aws-cdk-lib/aws-apigateway/test/resource.test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Match, Template } from '../../assertions';
22
import { Stack } from '../../core';
3+
import { APIGATEWAY_REQUEST_VALIDATOR_UNIQUE_ID } from '../../cx-api';
34
import * as apigw from '../lib';
45

56
/* eslint-disable quote-props */
@@ -424,4 +425,58 @@ describe('resource', () => {
424425
});
425426
});
426427

428+
test('can add multiple valiators through addMethod', () => {
429+
// GIVEN
430+
const stack = new Stack();
431+
stack.node.setContext(APIGATEWAY_REQUEST_VALIDATOR_UNIQUE_ID, true);
432+
const api = new apigw.RestApi(stack, 'api');
433+
434+
// WHEN
435+
const resource = api.root.addResource('path');
436+
const resource2 = api.root.addResource('anotherPath');
437+
438+
resource.addMethod('GET', undefined, {
439+
requestValidatorOptions: {
440+
requestValidatorName: 'validator1',
441+
},
442+
});
443+
444+
resource2.addMethod('GET', undefined, {
445+
requestValidatorOptions: {
446+
requestValidatorName: 'validator3',
447+
},
448+
});
449+
450+
resource.addMethod('POST', undefined, {
451+
requestValidatorOptions: {
452+
requestValidatorName: 'validator2',
453+
},
454+
});
455+
456+
// THEN
457+
Template.fromStack(stack).resourceCountIs('AWS::ApiGateway::RequestValidator', 3);
458+
Template.fromStack(stack).templateMatches(Match.objectLike({
459+
Resources: {
460+
apiapipathGETValidator833E9D62E0C84E70: {
461+
Type: 'AWS::ApiGateway::RequestValidator',
462+
Properties: {
463+
Name: 'validator1',
464+
},
465+
},
466+
apiapipathPOSTValidatorA9DA2EF22AA0453F: {
467+
Type: 'AWS::ApiGateway::RequestValidator',
468+
Properties: {
469+
Name: 'validator2',
470+
},
471+
},
472+
apiapianotherPathGETValidator0A5B8E231A9FC6EA: {
473+
Type: 'AWS::ApiGateway::RequestValidator',
474+
Properties: {
475+
Name: 'validator3',
476+
},
477+
},
478+
},
479+
}));
480+
});
481+
427482
});

packages/aws-cdk-lib/cx-api/lib/features.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export const EC2_LAUNCH_TEMPLATE_DEFAULT_USER_DATA = '@aws-cdk/aws-ec2:launchTem
8585
export const SECRETS_MANAGER_TARGET_ATTACHMENT_RESOURCE_POLICY = '@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments';
8686
export const REDSHIFT_COLUMN_ID = '@aws-cdk/aws-redshift:columnId';
8787
export const ENABLE_EMR_SERVICE_POLICY_V2 = '@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2';
88+
export const APIGATEWAY_REQUEST_VALIDATOR_UNIQUE_ID = '@aws-cdk/aws-apigateway:requestValidatorUniqueId';
8889

8990
export const FLAGS: Record<string, FlagInfo> = {
9091
//////////////////////////////////////////////////////////////////////
@@ -733,6 +734,7 @@ export const FLAGS: Record<string, FlagInfo> = {
733734
recommendedValue: true,
734735
},
735736

737+
//////////////////////////////////////////////////////////////////////
736738
[ENABLE_EMR_SERVICE_POLICY_V2]: {
737739
type: FlagType.BugFix,
738740
summary: 'Enable AmazonEMRServicePolicy_v2 managed policies',
@@ -749,6 +751,21 @@ export const FLAGS: Record<string, FlagInfo> = {
749751
introducedIn: { v2: '2.72.0' },
750752
recommendedValue: true,
751753
},
754+
755+
//////////////////////////////////////////////////////////////////////
756+
[APIGATEWAY_REQUEST_VALIDATOR_UNIQUE_ID]: {
757+
type: FlagType.BugFix,
758+
summary: 'Generate a unique id for each RequestValidator added to a method',
759+
detailsMd: `
760+
This flag allows multiple RequestValidators to be added to a RestApi when
761+
providing the \`RequestValidatorOptions\` in the \`addMethod()\` method.
762+
763+
If the flag is not set then only a single RequestValidator can be added in this way.
764+
Any additional RequestValidators have to be created directly with \`new RequestValidator\`.
765+
`,
766+
introducedIn: { v2: 'V2·NEXT' },
767+
recommendedValue: true,
768+
},
752769
};
753770

754771
const CURRENT_MV = 'v2';

0 commit comments

Comments
 (0)