@@ -8,7 +8,7 @@ import { Policy, PolicyStatement, Role, ServicePrincipal } from '@aws-cdk/aws-ia
88import { Code , Function as LambdaFunction , Runtime } from '@aws-cdk/aws-lambda' ;
99import { LogGroup , RetentionDays } from '@aws-cdk/aws-logs' ;
1010import { Bucket , IBucket } from '@aws-cdk/aws-s3' ;
11- import { ArnFormat , Aws , Construct , Duration , Lazy , Stack } from '@aws-cdk/core' ;
11+ import { ArnFormat , Aws , Construct , Duration , Lazy , Resource , Stack } from '@aws-cdk/core' ;
1212import { CloudFrontToApiGatewayToLambda } from '@aws-solutions-constructs/aws-cloudfront-apigateway-lambda' ;
1313
1414import { addCfnSuppressRules } from '../../utils/utils' ;
@@ -92,7 +92,75 @@ export class BackEnd extends Construct {
9292
9393 addCfnSuppressRules ( imageHandlerLogGroup , [ { id : 'W84' , reason : 'CloudWatch log group is always encrypted by default.' } ] ) ;
9494
95- const cachePolicy = new CfnCachePolicy ( this , 'CachePolicy' , {
95+ const cachePolicy = new CustomBackEndCachePolicy ( this , 'CachePolicy' , props ) ;
96+
97+ const originRequestPolicy = new CustomBackEndOriginRequestPolicy ( this , 'OriginRequestPolicy' , props ) ;
98+
99+ const apiGatewayRestApi = RestApi . fromRestApiId ( this , 'ApiGatewayRestApi' , Lazy . string ( { produce : ( ) => imageHandlerCloudFrontApiGatewayLambda . apiGateway . restApiId } ) ) ;
100+
101+ const origin : IOrigin = new HttpOrigin ( `${ apiGatewayRestApi . restApiId } .execute-api.${ Aws . REGION } .amazonaws.com` , {
102+ originPath : '/image' ,
103+ originSslProtocols : [ OriginSslPolicy . TLS_V1_1 , OriginSslPolicy . TLS_V1_2 ]
104+ } ) ;
105+
106+ const cloudFrontDistributionProps : DistributionProps = {
107+ comment : 'Image Handler Distribution for Serverless Image Handler' ,
108+ defaultBehavior : {
109+ origin : origin ,
110+ allowedMethods : AllowedMethods . ALLOW_GET_HEAD ,
111+ viewerProtocolPolicy : ViewerProtocolPolicy . HTTPS_ONLY ,
112+ originRequestPolicy : originRequestPolicy ,
113+ cachePolicy : cachePolicy
114+ } ,
115+ priceClass : props . cloudFrontPriceClass as PriceClass ,
116+ enableLogging : true ,
117+ logBucket : props . logsBucket ,
118+ logFilePrefix : 'api-cloudfront/' ,
119+ errorResponses : [
120+ { httpStatus : 500 , ttl : Duration . minutes ( 10 ) } ,
121+ { httpStatus : 501 , ttl : Duration . minutes ( 10 ) } ,
122+ { httpStatus : 502 , ttl : Duration . minutes ( 10 ) } ,
123+ { httpStatus : 503 , ttl : Duration . minutes ( 10 ) } ,
124+ { httpStatus : 504 , ttl : Duration . minutes ( 10 ) }
125+ ]
126+ } ;
127+
128+ const logGroupProps = {
129+ retention : props . logRetentionPeriod as RetentionDays
130+ } ;
131+
132+ const apiGatewayProps : LambdaRestApiProps = {
133+ handler : imageHandlerLambdaFunction ,
134+ deployOptions : {
135+ stageName : 'image'
136+ } ,
137+ binaryMediaTypes : [ '*/*' ]
138+ } ;
139+
140+ const imageHandlerCloudFrontApiGatewayLambda = new CloudFrontToApiGatewayToLambda ( this , 'ImageHandlerCloudFrontApiGatewayLambda' , {
141+ existingLambdaObj : imageHandlerLambdaFunction ,
142+ insertHttpSecurityHeaders : false ,
143+ logGroupProps : logGroupProps ,
144+ cloudFrontDistributionProps : cloudFrontDistributionProps ,
145+ apiGatewayProps : apiGatewayProps
146+ } ) ;
147+
148+ imageHandlerCloudFrontApiGatewayLambda . apiGateway . node . tryRemoveChild ( 'Endpoint' ) ; // we don't need the RestApi endpoint in the outputs
149+
150+ this . domainName = imageHandlerCloudFrontApiGatewayLambda . cloudFrontWebDistribution . distributionDomainName ;
151+ }
152+ }
153+
154+
155+ class CustomBackEndCachePolicy extends Resource implements ICachePolicy {
156+ public readonly cachePolicyId : string ;
157+
158+ constructor ( scope : Construct , id : string , props : BackEndProps ) {
159+ super ( scope , id , {
160+ physicalName : `ServerlessImageHandler-${ props . uuid } ` ,
161+ } ) ;
162+
163+ const cachePolicy = new CfnCachePolicy ( this , 'Resource' , {
96164 cachePolicyConfig : {
97165 name : `ServerlessImageHandler-${ props . uuid } ` ,
98166 defaultTtl : Duration . days ( 1 ) . toSeconds ( ) ,
@@ -115,7 +183,7 @@ export class BackEnd extends Construct {
115183 }
116184 }
117185 ) ;
118-
186+
119187 // https://github.com/aws/aws-cdk/issues/8396#issuecomment-857690411
120188 cachePolicy . addOverride (
121189 'Properties.CachePolicyConfig.ParametersInCacheKeyAndForwardedToOrigin.HeadersConfig.Headers' ,
@@ -128,11 +196,19 @@ export class BackEnd extends Construct {
128196 }
129197 ) ;
130198
131- const cachePolicyAdapter = new class implements ICachePolicy {
132- public readonly cachePolicyId = cachePolicy . ref ;
133- } ( ) ;
199+ this . cachePolicyId = cachePolicy . ref ;
200+ }
201+ }
202+
203+ class CustomBackEndOriginRequestPolicy extends Resource implements IOriginRequestPolicy {
204+ public readonly originRequestPolicyId : string ;
205+
206+ constructor ( scope : Construct , id : string , props : BackEndProps ) {
207+ super ( scope , id , {
208+ physicalName : `ServerlessImageHandler-${ props . uuid } ` ,
209+ } ) ;
134210
135- const originRequestPolicy = new CfnOriginRequestPolicy ( this , 'OriginRequestPolicy ' , {
211+ const originRequestPolicy = new CfnOriginRequestPolicy ( this , 'Resource ' , {
136212 originRequestPolicyConfig : {
137213 name : `ServerlessImageHandler-${ props . uuid } ` ,
138214 headersConfig : {
@@ -160,61 +236,6 @@ export class BackEnd extends Construct {
160236 }
161237 ) ;
162238
163- const originRequestPolicyAdapter = new class implements IOriginRequestPolicy {
164- public readonly originRequestPolicyId = originRequestPolicy . ref ;
165- } ( ) ;
166-
167- const apiGatewayRestApi = RestApi . fromRestApiId ( this , 'ApiGatewayRestApi' , Lazy . string ( { produce : ( ) => imageHandlerCloudFrontApiGatewayLambda . apiGateway . restApiId } ) ) ;
168-
169- const origin : IOrigin = new HttpOrigin ( `${ apiGatewayRestApi . restApiId } .execute-api.${ Aws . REGION } .amazonaws.com` , {
170- originPath : '/image' ,
171- originSslProtocols : [ OriginSslPolicy . TLS_V1_1 , OriginSslPolicy . TLS_V1_2 ]
172- } ) ;
173-
174- const cloudFrontDistributionProps : DistributionProps = {
175- comment : 'Image Handler Distribution for Serverless Image Handler' ,
176- defaultBehavior : {
177- origin : origin ,
178- allowedMethods : AllowedMethods . ALLOW_GET_HEAD ,
179- viewerProtocolPolicy : ViewerProtocolPolicy . HTTPS_ONLY ,
180- originRequestPolicy : originRequestPolicyAdapter ,
181- cachePolicy : cachePolicyAdapter
182- } ,
183- priceClass : props . cloudFrontPriceClass as PriceClass ,
184- enableLogging : true ,
185- logBucket : props . logsBucket ,
186- logFilePrefix : 'api-cloudfront/' ,
187- errorResponses : [
188- { httpStatus : 500 , ttl : Duration . minutes ( 10 ) } ,
189- { httpStatus : 501 , ttl : Duration . minutes ( 10 ) } ,
190- { httpStatus : 502 , ttl : Duration . minutes ( 10 ) } ,
191- { httpStatus : 503 , ttl : Duration . minutes ( 10 ) } ,
192- { httpStatus : 504 , ttl : Duration . minutes ( 10 ) }
193- ]
194- } ;
195-
196- const logGroupProps = {
197- retention : props . logRetentionPeriod as RetentionDays
198- } ;
199-
200- const apiGatewayProps : LambdaRestApiProps = {
201- handler : imageHandlerLambdaFunction ,
202- deployOptions : {
203- stageName : 'image'
204- } ,
205- binaryMediaTypes : [ '*/*' ]
206- } ;
207-
208- const imageHandlerCloudFrontApiGatewayLambda = new CloudFrontToApiGatewayToLambda ( this , 'ImageHandlerCloudFrontApiGatewayLambda' , {
209- existingLambdaObj : imageHandlerLambdaFunction ,
210- insertHttpSecurityHeaders : false ,
211- logGroupProps : logGroupProps ,
212- cloudFrontDistributionProps : cloudFrontDistributionProps ,
213- apiGatewayProps : apiGatewayProps
214- } ) ;
215-
216- imageHandlerCloudFrontApiGatewayLambda . apiGateway . node . tryRemoveChild ( 'Endpoint' ) ; // we don't need the RestApi endpoint in the outputs
217-
218- this . domainName = imageHandlerCloudFrontApiGatewayLambda . cloudFrontWebDistribution . distributionDomainName ;
239+ this . originRequestPolicyId = originRequestPolicy . ref ;
219240 }
220241}
0 commit comments