From 8069a7e85c7c1652848624ba1b8085c89d3b1db2 Mon Sep 17 00:00:00 2001 From: Nick Law Date: Thu, 10 Dec 2020 05:48:14 +1100 Subject: [PATCH] fix(apigateway): base path url cannot contain upper case characters (#11799) We're migrating an existing API Gateway application to CDK and have [hit this error](https://github.com/aws/aws-cdk/blob/2f0a598720f7ecf4dfea7dde97182940fcbe8d9a/packages/%40aws-cdk/aws-apigateway/lib/base-path-mapping.ts#L52), because our base paths include capitalised characters. This PR resolves that issue and I've included some basics tests for the `BasePathMapping` resource. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-apigateway/lib/base-path-mapping.ts | 2 +- .../test/base-path-mapping.test.ts | 107 ++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 packages/@aws-cdk/aws-apigateway/test/base-path-mapping.test.ts diff --git a/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts b/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts index 17fa52ee7005c..d87fe8536f099 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts @@ -48,7 +48,7 @@ export class BasePathMapping extends Resource { super(scope, id); if (props.basePath && !Token.isUnresolved(props.basePath)) { - if (!props.basePath.match(/^[a-z0-9$_.+!*'()-]+$/)) { + if (!props.basePath.match(/^[a-zA-Z0-9$_.+!*'()-]+$/)) { throw new Error(`A base path may only contain letters, numbers, and one of "$-_.+!*'()", received: ${props.basePath}`); } } diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.test.ts b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.test.ts new file mode 100644 index 0000000000000..49dc8e50759f8 --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.test.ts @@ -0,0 +1,107 @@ +import '@aws-cdk/assert/jest'; +import * as acm from '@aws-cdk/aws-certificatemanager'; +import * as cdk from '@aws-cdk/core'; +import * as apigw from '../lib'; + +describe('BasePathMapping', () => { + test('default setup', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigw.RestApi(stack, 'MyApi'); + api.root.addMethod('GET'); // api must have atleast one method. + const domain = new apigw.DomainName(stack, 'MyDomain', { + domainName: 'example.com', + certificate: acm.Certificate.fromCertificateArn(stack, 'cert', 'arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d'), + endpointType: apigw.EndpointType.REGIONAL, + }); + + // WHEN + new apigw.BasePathMapping(stack, 'MyBasePath', { + restApi: api, + domainName: domain, + }); + + // THEN + expect(stack).toHaveResource('AWS::ApiGateway::BasePathMapping', { + DomainName: { Ref: 'MyDomainE4943FBC' }, + RestApiId: { Ref: 'MyApi49610EDF' }, + }); + }); + + test('specify basePath property', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigw.RestApi(stack, 'MyApi'); + api.root.addMethod('GET'); // api must have atleast one method. + const domain = new apigw.DomainName(stack, 'MyDomain', { + domainName: 'example.com', + certificate: acm.Certificate.fromCertificateArn(stack, 'cert', 'arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d'), + endpointType: apigw.EndpointType.REGIONAL, + }); + + // WHEN + new apigw.BasePathMapping(stack, 'MyBasePath', { + restApi: api, + domainName: domain, + basePath: 'My_B45E-P4th', + }); + + // THEN + expect(stack).toHaveResourceLike('AWS::ApiGateway::BasePathMapping', { + BasePath: 'My_B45E-P4th', + }); + }); + + test('throw error for invalid basePath property', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigw.RestApi(stack, 'MyApi'); + api.root.addMethod('GET'); // api must have atleast one method. + const domain = new apigw.DomainName(stack, 'MyDomain', { + domainName: 'example.com', + certificate: acm.Certificate.fromCertificateArn(stack, 'cert', 'arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d'), + endpointType: apigw.EndpointType.REGIONAL, + }); + + // WHEN + const invalidBasePath = '/invalid-/base-path'; + + // THEN + expect(() => { + new apigw.BasePathMapping(stack, 'MyBasePath', { + restApi: api, + domainName: domain, + basePath: invalidBasePath, + }); + }).toThrowError(/base path may only contain/); + }); + + test('specify stage property', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigw.RestApi(stack, 'MyApi'); + api.root.addMethod('GET'); // api must have atleast one method. + const domain = new apigw.DomainName(stack, 'MyDomain', { + domainName: 'example.com', + certificate: acm.Certificate.fromCertificateArn(stack, 'cert', 'arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d'), + endpointType: apigw.EndpointType.REGIONAL, + }); + const stage = new apigw.Stage(stack, 'MyStage', { + deployment: new apigw.Deployment(stack, 'MyDeplouyment', { + api, + }), + }); + + // WHEN + new apigw.BasePathMapping(stack, 'MyBasePathMapping', { + restApi: api, + domainName: domain, + stage, + }); + + // THEN + expect(stack).toHaveResourceLike('AWS::ApiGateway::BasePathMapping', { + Stage: { Ref: 'MyStage572B0482' }, + }); + }); +});