Skip to content

Commit 73c443a

Browse files
authoredOct 19, 2022
fix(apigateway): validation for path parts does not allow creation of resources with colon (#22531)
This PR adjusts the validation rules for path parts in resources created using the APIGateway library to allow the use of colons in pathParts, as requested in #22477. This enables the creation of resources with paths such as `events:batch` (from the reproduction steps in the related issue). An existing resource unit test (`'url for a resource'`) has been updated to ensure that a colon in a pathPart does not throw an error and properly reflects in the output of `RestApi.urlForPath`. The integration test `integ.restapi` has also been updated, wherein the `appliances` resource now has a path of `appliances:all` instead of `appliances`. If this is the wrong place to test the fix, I will gladly create a new resource to test on, or a new test altogether. Closes #22477. ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [x] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [x] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 9ab6d79 commit 73c443a

File tree

7 files changed

+75
-31
lines changed

7 files changed

+75
-31
lines changed
 

‎packages/@aws-cdk/aws-apigateway/lib/resource.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,8 @@ function validateResourcePathPart(part: string) {
558558
}
559559
}
560560

561-
if (!/^[a-zA-Z0-9\.\_\-]+$/.test(part)) {
562-
throw new Error(`Resource's path part only allow [a-zA-Z0-9._-], an optional trailing '+'
561+
if (!/^[a-zA-Z0-9:\.\_\-]+$/.test(part)) {
562+
throw new Error(`Resource's path part only allow [a-zA-Z0-9:._-], an optional trailing '+'
563563
and curly braces at the beginning and the end: ${part}`);
564564
}
565565
}

‎packages/@aws-cdk/aws-apigateway/test/integ.restapi.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class Test extends cdk.Stack {
3939
toys.addMethod('POST');
4040
toys.addMethod('PUT');
4141

42-
const appliances = v1.addResource('appliances');
42+
const appliances = v1.addResource('appliances:all');
4343
appliances.addMethod('GET');
4444

4545
const books = v1.addResource('books');

‎packages/@aws-cdk/aws-apigateway/test/resource.test.ts

+17
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ describe('resource', () => {
199199
// WHEN
200200
const aResource = api.root.addResource('a');
201201
const cResource = aResource.addResource('b').addResource('c');
202+
const colonResource = cResource.addResource('d:e');
202203

203204
// THEN
204205
expect(stack.resolve(api.urlForPath(aResource.path))).toEqual({
@@ -233,6 +234,22 @@ describe('resource', () => {
233234
],
234235
],
235236
});
237+
expect(stack.resolve(api.urlForPath(colonResource.path))).toEqual({
238+
'Fn::Join': [
239+
'',
240+
[
241+
'https://',
242+
{ Ref: 'apiC8550315' },
243+
'.execute-api.',
244+
{ Ref: 'AWS::Region' },
245+
'.',
246+
{ Ref: 'AWS::URLSuffix' },
247+
'/',
248+
{ Ref: 'apiDeploymentStageprod896C8101' },
249+
'/a/b/c/d:e',
250+
],
251+
],
252+
});
236253

237254
});
238255

‎packages/@aws-cdk/aws-apigateway/test/restapi.integ.snapshot/manifest.json

+33-6
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"validateOnSynth": false,
2424
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
2525
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
26-
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/ad4787bdd5f9c4b16cdee4831d5642e564049c42cac331b6d4b51b9ab2ae322e.json",
26+
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/527feb6f65d1f41404abb6acfb6504a918e1d7489665b74acb9fa0ca23f34049.json",
2727
"requiresBootstrapStackVersion": 6,
2828
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
2929
"additionalDependencies": [
@@ -60,7 +60,7 @@
6060
"/test-apigateway-restapi/my-api/Deployment/Resource": [
6161
{
6262
"type": "aws:cdk:logicalId",
63-
"data": "myapiDeployment92F2CB4963d40685c54c6f8da21d80a83f16d3d5"
63+
"data": "myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca"
6464
}
6565
],
6666
"/test-apigateway-restapi/my-api/DeploymentStage.beta/Resource": [
@@ -117,16 +117,16 @@
117117
"data": "myapiv1toysPUT59AFBBC2"
118118
}
119119
],
120-
"/test-apigateway-restapi/my-api/Default/v1/appliances/Resource": [
120+
"/test-apigateway-restapi/my-api/Default/v1/appliances:all/Resource": [
121121
{
122122
"type": "aws:cdk:logicalId",
123-
"data": "myapiv1appliances507FEFF4"
123+
"data": "myapiv1appliancesallCF8C6A16"
124124
}
125125
],
126-
"/test-apigateway-restapi/my-api/Default/v1/appliances/GET/Resource": [
126+
"/test-apigateway-restapi/my-api/Default/v1/appliances:all/GET/Resource": [
127127
{
128128
"type": "aws:cdk:logicalId",
129-
"data": "myapiv1appliancesGET8FE872EC"
129+
"data": "myapiv1appliancesallGETC4DF552D"
130130
}
131131
],
132132
"/test-apigateway-restapi/my-api/Default/v1/books/Resource": [
@@ -230,6 +230,33 @@
230230
"type": "aws:cdk:logicalId",
231231
"data": "CheckBootstrapVersion"
232232
}
233+
],
234+
"myapiDeployment92F2CB4963d40685c54c6f8da21d80a83f16d3d5": [
235+
{
236+
"type": "aws:cdk:logicalId",
237+
"data": "myapiDeployment92F2CB4963d40685c54c6f8da21d80a83f16d3d5",
238+
"trace": [
239+
"!!DESTRUCTIVE_CHANGES: WILL_DESTROY"
240+
]
241+
}
242+
],
243+
"myapiv1appliances507FEFF4": [
244+
{
245+
"type": "aws:cdk:logicalId",
246+
"data": "myapiv1appliances507FEFF4",
247+
"trace": [
248+
"!!DESTRUCTIVE_CHANGES: WILL_DESTROY"
249+
]
250+
}
251+
],
252+
"myapiv1appliancesGET8FE872EC": [
253+
{
254+
"type": "aws:cdk:logicalId",
255+
"data": "myapiv1appliancesGET8FE872EC",
256+
"trace": [
257+
"!!DESTRUCTIVE_CHANGES: WILL_DESTROY"
258+
]
259+
}
233260
]
234261
},
235262
"displayName": "test-apigateway-restapi"

‎packages/@aws-cdk/aws-apigateway/test/restapi.integ.snapshot/test-apigateway-restapi.assets.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"version": "21.0.0",
33
"files": {
4-
"ad4787bdd5f9c4b16cdee4831d5642e564049c42cac331b6d4b51b9ab2ae322e": {
4+
"527feb6f65d1f41404abb6acfb6504a918e1d7489665b74acb9fa0ca23f34049": {
55
"source": {
66
"path": "test-apigateway-restapi.template.json",
77
"packaging": "file"
88
},
99
"destinations": {
1010
"current_account-current_region": {
1111
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12-
"objectKey": "ad4787bdd5f9c4b16cdee4831d5642e564049c42cac331b6d4b51b9ab2ae322e.json",
12+
"objectKey": "527feb6f65d1f41404abb6acfb6504a918e1d7489665b74acb9fa0ca23f34049.json",
1313
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
1414
}
1515
}

‎packages/@aws-cdk/aws-apigateway/test/restapi.integ.snapshot/test-apigateway-restapi.template.json

+9-9
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"UpdateReplacePolicy": "Retain",
5656
"DeletionPolicy": "Retain"
5757
},
58-
"myapiDeployment92F2CB4963d40685c54c6f8da21d80a83f16d3d5": {
58+
"myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca": {
5959
"Type": "AWS::ApiGateway::Deployment",
6060
"Properties": {
6161
"RestApiId": {
@@ -64,8 +64,8 @@
6464
"Description": "Automatically created by the RestApi construct"
6565
},
6666
"DependsOn": [
67-
"myapiv1appliancesGET8FE872EC",
68-
"myapiv1appliances507FEFF4",
67+
"myapiv1appliancesallGETC4DF552D",
68+
"myapiv1appliancesallCF8C6A16",
6969
"myapiv1booksGETC6B996D0",
7070
"myapiv1booksPOST53E2832E",
7171
"myapiv1books1D4BE6C1",
@@ -87,7 +87,7 @@
8787
"CacheClusterEnabled": true,
8888
"CacheClusterSize": "0.5",
8989
"DeploymentId": {
90-
"Ref": "myapiDeployment92F2CB4963d40685c54c6f8da21d80a83f16d3d5"
90+
"Ref": "myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca"
9191
},
9292
"Description": "beta stage",
9393
"MethodSettings": [
@@ -288,24 +288,24 @@
288288
}
289289
}
290290
},
291-
"myapiv1appliances507FEFF4": {
291+
"myapiv1appliancesallCF8C6A16": {
292292
"Type": "AWS::ApiGateway::Resource",
293293
"Properties": {
294294
"ParentId": {
295295
"Ref": "myapiv113487378"
296296
},
297-
"PathPart": "appliances",
297+
"PathPart": "appliances:all",
298298
"RestApiId": {
299299
"Ref": "myapi4C7BF186"
300300
}
301301
}
302302
},
303-
"myapiv1appliancesGET8FE872EC": {
303+
"myapiv1appliancesallGETC4DF552D": {
304304
"Type": "AWS::ApiGateway::Method",
305305
"Properties": {
306306
"HttpMethod": "GET",
307307
"ResourceId": {
308-
"Ref": "myapiv1appliances507FEFF4"
308+
"Ref": "myapiv1appliancesallCF8C6A16"
309309
},
310310
"RestApiId": {
311311
"Ref": "myapi4C7BF186"
@@ -680,7 +680,7 @@
680680
}
681681
},
682682
"DependsOn": [
683-
"myapiv1appliancesGET8FE872EC",
683+
"myapiv1appliancesallGETC4DF552D",
684684
"myapiv1booksGETC6B996D0",
685685
"myapiv1booksPOST53E2832E",
686686
"myapiv1toysGET7348114D",

‎packages/@aws-cdk/aws-apigateway/test/restapi.integ.snapshot/tree.json

+11-11
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"path": "Tree",
1010
"constructInfo": {
1111
"fqn": "constructs.Construct",
12-
"version": "10.1.108"
12+
"version": "10.1.129"
1313
}
1414
},
1515
"test-apigateway-restapi": {
@@ -145,7 +145,7 @@
145145
"cacheClusterEnabled": true,
146146
"cacheClusterSize": "0.5",
147147
"deploymentId": {
148-
"Ref": "myapiDeployment92F2CB4963d40685c54c6f8da21d80a83f16d3d5"
148+
"Ref": "myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca"
149149
},
150150
"description": "beta stage",
151151
"methodSettings": [
@@ -466,20 +466,20 @@
466466
"version": "0.0.0"
467467
}
468468
},
469-
"appliances": {
470-
"id": "appliances",
471-
"path": "test-apigateway-restapi/my-api/Default/v1/appliances",
469+
"appliances:all": {
470+
"id": "appliances:all",
471+
"path": "test-apigateway-restapi/my-api/Default/v1/appliances:all",
472472
"children": {
473473
"Resource": {
474474
"id": "Resource",
475-
"path": "test-apigateway-restapi/my-api/Default/v1/appliances/Resource",
475+
"path": "test-apigateway-restapi/my-api/Default/v1/appliances:all/Resource",
476476
"attributes": {
477477
"aws:cdk:cloudformation:type": "AWS::ApiGateway::Resource",
478478
"aws:cdk:cloudformation:props": {
479479
"parentId": {
480480
"Ref": "myapiv113487378"
481481
},
482-
"pathPart": "appliances",
482+
"pathPart": "appliances:all",
483483
"restApiId": {
484484
"Ref": "myapi4C7BF186"
485485
}
@@ -492,17 +492,17 @@
492492
},
493493
"GET": {
494494
"id": "GET",
495-
"path": "test-apigateway-restapi/my-api/Default/v1/appliances/GET",
495+
"path": "test-apigateway-restapi/my-api/Default/v1/appliances:all/GET",
496496
"children": {
497497
"Resource": {
498498
"id": "Resource",
499-
"path": "test-apigateway-restapi/my-api/Default/v1/appliances/GET/Resource",
499+
"path": "test-apigateway-restapi/my-api/Default/v1/appliances:all/GET/Resource",
500500
"attributes": {
501501
"aws:cdk:cloudformation:type": "AWS::ApiGateway::Method",
502502
"aws:cdk:cloudformation:props": {
503503
"httpMethod": "GET",
504504
"resourceId": {
505-
"Ref": "myapiv1appliances507FEFF4"
505+
"Ref": "myapiv1appliancesallCF8C6A16"
506506
},
507507
"restApiId": {
508508
"Ref": "myapi4C7BF186"
@@ -1176,7 +1176,7 @@
11761176
"path": "apigateway-restapi/DefaultTest/Default",
11771177
"constructInfo": {
11781178
"fqn": "constructs.Construct",
1179-
"version": "10.1.108"
1179+
"version": "10.1.129"
11801180
}
11811181
},
11821182
"DeployAssert": {

0 commit comments

Comments
 (0)
Please sign in to comment.