Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { lit } from '../../core/lib/private/literal-string';
export interface FunctionUrlOriginProps extends cloudfront.OriginProps {
/**
* Specifies how long, in seconds, CloudFront waits for a response from the origin.
* The valid range is from 1 to 180 seconds, inclusive.
* The minimum is 1 second. The maximum is governed by the origin response timeout quota, which is
* adjustable, so the effective maximum depends on the target account.
*
* Note that values over 60 seconds are possible only after a limit increase request for the origin response timeout quota
* has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time.
Expand All @@ -23,10 +24,11 @@ export interface FunctionUrlOriginProps extends cloudfront.OriginProps {

/**
* Specifies how long, in seconds, CloudFront persists its connection to the origin.
* The valid range is from 1 to 180 seconds, inclusive.
* The minimum is 1 second. The maximum is governed by the keep-alive timeout per origin quota,
* which is adjustable, so the effective maximum depends on the target account.
*
* Note that values over 60 seconds are possible only after a limit increase request for the origin response timeout quota
* has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time.
* The default quota allows up to 300 seconds; higher values require an approved limit increase
* in the target account, and otherwise produce an error at deploy time.
*
* @default Duration.seconds(5)
*/
Expand Down Expand Up @@ -77,8 +79,8 @@ export class FunctionUrlOrigin extends cloudfront.OriginBase {
const domainName = cdk.Fn.select(2, cdk.Fn.split('/', lambdaFunctionUrl.url));
super(domainName, props);

validateSecondsInRangeOrUndefined('readTimeout', 1, 180, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, 180, props.keepaliveTimeout);
validateSecondsInRangeOrUndefined('readTimeout', 1, undefined, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, undefined, props.keepaliveTimeout);
this.validateResponseCompletionTimeoutWithReadTimeout(props.responseCompletionTimeout, props.readTimeout);
}

Expand Down Expand Up @@ -109,8 +111,8 @@ class FunctionUrlOriginWithOAC extends cloudfront.OriginBase {

this.props = props;

validateSecondsInRangeOrUndefined('readTimeout', 1, 180, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, 180, props.keepaliveTimeout);
validateSecondsInRangeOrUndefined('readTimeout', 1, undefined, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, undefined, props.keepaliveTimeout);
}

protected renderCustomOriginConfig(): cloudfront.CfnDistribution.CustomOriginConfigProperty | undefined {
Expand Down
14 changes: 8 additions & 6 deletions packages/aws-cdk-lib/aws-cloudfront-origins/lib/http-origin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export interface HttpOriginProps extends cloudfront.OriginProps {

/**
* Specifies how long, in seconds, CloudFront waits for a response from the origin, also known as the origin response timeout.
* The valid range is from 1 to 180 seconds, inclusive.
* The minimum is 1 second. The maximum is governed by the origin response timeout quota, which is
* adjustable, so the effective maximum depends on the target account.
*
* Note that values over 60 seconds are possible only after a limit increase request for the origin response timeout quota
* has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time.
Expand All @@ -49,10 +50,11 @@ export interface HttpOriginProps extends cloudfront.OriginProps {

/**
* Specifies how long, in seconds, CloudFront persists its connection to the origin.
* The valid range is from 1 to 180 seconds, inclusive.
* The minimum is 1 second. The maximum is governed by the keep-alive timeout per origin quota,
* which is adjustable, so the effective maximum depends on the target account.
*
* Note that values over 60 seconds are possible only after a limit increase request for the origin response timeout quota
* has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time.
* The default quota allows up to 300 seconds; higher values require an approved limit increase
* in the target account, and otherwise produce an error at deploy time.
*
* @default Duration.seconds(5)
*/
Expand All @@ -75,8 +77,8 @@ export class HttpOrigin extends cloudfront.OriginBase {
constructor(domainName: string, private readonly props: HttpOriginProps = {}) {
super(domainName, props);

validateSecondsInRangeOrUndefined('readTimeout', 1, 180, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, 180, props.keepaliveTimeout);
validateSecondsInRangeOrUndefined('readTimeout', 1, undefined, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, undefined, props.keepaliveTimeout);
this.validateResponseCompletionTimeoutWithReadTimeout(props.responseCompletionTimeout, props.readTimeout);

this.validatePortNumber('httpPort', props.httpPort);
Expand Down
11 changes: 8 additions & 3 deletions packages/aws-cdk-lib/aws-cloudfront-origins/lib/private/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { lit } from '../../../core/lib/private/literal-string';

/**
* Throws an error if a duration is defined and not an integer number of seconds within a range.
*
* Pass `undefined` for `max` to validate the lower bound only. This is for values whose upper
* bound is an adjustable service quota, so the effective maximum depends on the target account
* and can only be enforced by the service at deploy time.
*/
export function validateSecondsInRangeOrUndefined(name: string, min: number, max: number, duration?: cdk.Duration) {
export function validateSecondsInRangeOrUndefined(name: string, min: number, max: number | undefined, duration?: cdk.Duration) {
if (duration === undefined) { return; }
const value = duration.toSeconds();
if (!Number.isInteger(value) || value < min || value > max) {
throw new cdk.UnscopedValidationError(lit`InvalidDurationRange`, `${name}: Must be an int between ${min} and ${max} seconds (inclusive); received ${value}.`);
if (!Number.isInteger(value) || value < min || (max !== undefined && value > max)) {
const range = max !== undefined ? `between ${min} and ${max} seconds (inclusive)` : `${min} seconds or greater`;
throw new cdk.UnscopedValidationError(lit`InvalidDurationRange`, `${name}: Must be an int ${range}; received ${value}.`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import * as cdk from '../../core';
export interface RestApiOriginProps extends cloudfront.OriginProps {
/**
* Specifies how long, in seconds, CloudFront waits for a response from the origin, also known as the origin response timeout.
* The valid range is from 1 to 180 seconds, inclusive.
* The minimum is 1 second. The maximum is governed by the origin response timeout quota, which is
* adjustable, so the effective maximum depends on the target account.
*
* Note that values over 60 seconds are possible only after a limit increase request for the origin response timeout quota
* has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time.
Expand All @@ -20,10 +21,11 @@ export interface RestApiOriginProps extends cloudfront.OriginProps {

/**
* Specifies how long, in seconds, CloudFront persists its connection to the origin.
* The valid range is from 1 to 180 seconds, inclusive.
* The minimum is 1 second. The maximum is governed by the keep-alive timeout per origin quota,
* which is adjustable, so the effective maximum depends on the target account.
*
* Note that values over 60 seconds are possible only after a limit increase request for the origin response timeout quota
* has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time.
* The default quota allows up to 300 seconds; higher values require an approved limit increase
* in the target account, and otherwise produce an error at deploy time.
*
* @default Duration.seconds(5)
*/
Expand All @@ -43,8 +45,8 @@ export class RestApiOrigin extends cloudfront.OriginBase {
...props,
});

validateSecondsInRangeOrUndefined('readTimeout', 1, 180, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, 180, props.keepaliveTimeout);
validateSecondsInRangeOrUndefined('readTimeout', 1, undefined, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, undefined, props.keepaliveTimeout);
this.validateResponseCompletionTimeoutWithReadTimeout(props.responseCompletionTimeout, props.readTimeout);
}

Expand Down
14 changes: 8 additions & 6 deletions packages/aws-cdk-lib/aws-cloudfront-origins/lib/vpc-origin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export interface VpcOriginProps extends cloudfront.OriginProps {

/**
* Specifies how long, in seconds, CloudFront waits for a response from the origin, also known as the origin response timeout.
* The valid range is from 1 to 180 seconds, inclusive.
* The minimum is 1 second. The maximum is governed by the origin response timeout quota, which is
* adjustable, so the effective maximum depends on the target account.
*
* Note that values over 60 seconds are possible only after a limit increase request for the origin response timeout quota
* has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time.
Expand All @@ -29,10 +30,11 @@ export interface VpcOriginProps extends cloudfront.OriginProps {

/**
* Specifies how long, in seconds, CloudFront persists its connection to the origin.
* The valid range is from 1 to 180 seconds, inclusive.
* The minimum is 1 second. The maximum is governed by the keep-alive timeout per origin quota,
* which is adjustable, so the effective maximum depends on the target account.
*
* Note that values over 60 seconds are possible only after a limit increase request for the origin response timeout quota
* has been approved in the target account; otherwise, values over 60 seconds will produce an error at deploy time.
* The default quota allows up to 300 seconds; higher values require an approved limit increase
* in the target account, and otherwise produce an error at deploy time.
*
* @default Duration.seconds(5)
*/
Expand Down Expand Up @@ -83,8 +85,8 @@ export abstract class VpcOrigin extends cloudfront.OriginBase {
protected constructor(domainName: string, protected readonly props: VpcOriginProps) {
super(domainName, props);

validateSecondsInRangeOrUndefined('readTimeout', 1, 180, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, 180, props.keepaliveTimeout);
validateSecondsInRangeOrUndefined('readTimeout', 1, undefined, props.readTimeout);
validateSecondsInRangeOrUndefined('keepaliveTimeout', 1, undefined, props.keepaliveTimeout);
}

protected renderVpcOriginConfig(): cloudfront.CfnDistribution.VpcOriginConfigProperty | undefined {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,29 @@ test('renders an example with all available props', () => {

test.each([
Duration.seconds(0),
])('validates readTimeout is at least 1 second', (readTimeout) => {
expect(() => {
new HttpOrigin('www.example.com', {
readTimeout,
});
}).toThrow(`readTimeout: Must be an int 1 seconds or greater; received ${readTimeout.toSeconds()}.`);
});

test.each([
Duration.seconds(181),
Duration.minutes(5),
])('validates readTimeout is an integer between 1 and 180 seconds - out of bounds', (readTimeout) => {
])('allows readTimeout above the default quota, which the service validates at deploy time', (readTimeout) => {
expect(() => {
new HttpOrigin('www.example.com', {
readTimeout,
});
}).toThrow(`readTimeout: Must be an int between 1 and 180 seconds (inclusive); received ${readTimeout.toSeconds()}.`);
}).not.toThrow();
});

test.each([
Duration.seconds(0.5),
Duration.seconds(60.5),
])('validates readTimeout is an integer between 1 and 180 seconds - not an int', (readTimeout) => {
])('validates readTimeout is a whole number of seconds', (readTimeout) => {
expect(() => {
new HttpOrigin('www.example.com', {
readTimeout,
Expand All @@ -94,20 +103,29 @@ test.each([

test.each([
Duration.seconds(0),
])('validates keepaliveTimeout is at least 1 second', (keepaliveTimeout) => {
expect(() => {
new HttpOrigin('www.example.com', {
keepaliveTimeout,
});
}).toThrow(`keepaliveTimeout: Must be an int 1 seconds or greater; received ${keepaliveTimeout.toSeconds()}.`);
});

test.each([
Duration.seconds(181),
Duration.minutes(5),
])('validates keepaliveTimeout is an integer between 1 and 180 seconds - out of bounds', (keepaliveTimeout) => {
])('allows keepaliveTimeout within the default quota, which the service validates at deploy time', (keepaliveTimeout) => {
expect(() => {
new HttpOrigin('www.example.com', {
keepaliveTimeout,
});
}).toThrow(`keepaliveTimeout: Must be an int between 1 and 180 seconds (inclusive); received ${keepaliveTimeout.toSeconds()}.`);
}).not.toThrow();
});

test.each([
Duration.seconds(0.5),
Duration.seconds(60.5),
])('validates keepaliveTimeout is an integer between 1 and 180 seconds - not an int', (keepaliveTimeout) => {
])('validates keepaliveTimeout is a whole number of seconds', (keepaliveTimeout) => {
expect(() => {
new HttpOrigin('www.example.com', {
keepaliveTimeout,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,32 +206,56 @@ test('VPC origin from an imported VpcOrigin resource', () => {

test.each([
Duration.seconds(0),
])('VPC origin throws when readTimeout is %s - below the minimum', (readTimeout) => {
// GIVEN
const vpc = new ec2.Vpc(stack, 'Vpc');
const loadBalancer = new elbv2.ApplicationLoadBalancer(stack, 'ALB', { vpc });

// WHEN
expect(() => {
VpcOrigin.withApplicationLoadBalancer(loadBalancer, { readTimeout });
}).toThrow(`readTimeout: Must be an int 1 seconds or greater; received ${readTimeout.toSeconds()}`);
});

test.each([
Duration.seconds(181),
Duration.minutes(5),
])('VPC origin throws when readTimeout is %s - out of bounds', (readTimeout) => {
])('VPC origin allows readTimeout of %s above the default quota', (readTimeout) => {
// GIVEN
const vpc = new ec2.Vpc(stack, 'Vpc');
const loadBalancer = new elbv2.ApplicationLoadBalancer(stack, 'ALB', { vpc });

// WHEN
expect(() => {
VpcOrigin.withApplicationLoadBalancer(loadBalancer, { readTimeout });
}).toThrow(`readTimeout: Must be an int between 1 and 180 seconds (inclusive); received ${readTimeout.toSeconds()}`);
}).not.toThrow();
});

test.each([
Duration.seconds(0),
])('VPC origin throws when keepaliveTimeout is %s - below the minimum', (keepaliveTimeout) => {
// GIVEN
const vpc = new ec2.Vpc(stack, 'Vpc');
const loadBalancer = new elbv2.ApplicationLoadBalancer(stack, 'ALB', { vpc });

// WHEN
expect(() => {
VpcOrigin.withApplicationLoadBalancer(loadBalancer, { keepaliveTimeout });
}).toThrow(`keepaliveTimeout: Must be an int 1 seconds or greater; received ${keepaliveTimeout.toSeconds()}`);
});

test.each([
Duration.seconds(181),
Duration.minutes(5),
])('VPC origin throws when keepaliveTimeout is %s - out of bounds', (keepaliveTimeout) => {
])('VPC origin allows keepaliveTimeout of %s within the default quota', (keepaliveTimeout) => {
// GIVEN
const vpc = new ec2.Vpc(stack, 'Vpc');
const loadBalancer = new elbv2.ApplicationLoadBalancer(stack, 'ALB', { vpc });

// WHEN
expect(() => {
VpcOrigin.withApplicationLoadBalancer(loadBalancer, { keepaliveTimeout });
}).toThrow(`keepaliveTimeout: Must be an int between 1 and 180 seconds (inclusive); received ${keepaliveTimeout.toSeconds()}`);
}).not.toThrow();
});

test('VPC origin throws when no domainName is specified', () => {
Expand Down
Loading