Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(apigatewayv2): set throttling on stages #19776

Merged
merged 9 commits into from
Apr 8, 2022
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/lib/common/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ export interface StageOptions {
* @default - no custom domain and api mapping configuration
*/
readonly domainMapping?: DomainMappingOptions;

/**
* Throttle settings for the routes of this stage
*
* @default - no throttling configuration
*/
readonly throttle?: ThrottleSettings;
}

/**
Expand All @@ -70,3 +77,20 @@ export interface StageAttributes {
*/
readonly stageName: string;
}

/**
* Container for defining throttling parameters to API stages
*/
export interface ThrottleSettings {
/**
* The API request steady-state rate limit (average requests per second over an extended period of time)
* @default none
*/
readonly rateLimit?: number;

/**
* The maximum API request rate limit over a time ranging from one to a few seconds.
* @default none
*/
readonly burstLimit?: number;
}
4 changes: 4 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/lib/http/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ export class HttpStage extends HttpStageBase {
apiId: props.httpApi.apiId,
stageName: this.physicalName,
autoDeploy: props.autoDeploy,
defaultRouteSettings: !props.throttle ? undefined : {
throttlingBurstLimit: props.throttle?.burstLimit,
throttlingRateLimit: props.throttle?.rateLimit,
},
});

this.stageName = this.physicalName;
Expand Down
4 changes: 4 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ export class WebSocketStage extends StageBase implements IWebSocketStage {
apiId: props.webSocketApi.apiId,
stageName: this.physicalName,
autoDeploy: props.autoDeploy,
defaultRouteSettings: !props.throttle ? undefined : {
throttlingBurstLimit: props.throttle?.burstLimit,
throttlingRateLimit: props.throttle?.rateLimit,
},
});

if (props.domainMapping) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"Resources": {
"HttpApiF5A9A8A7": {
"Type": "AWS::ApiGatewayV2::Api",
"Properties": {
"Name": "HttpApi",
"ProtocolType": "HTTP"
}
},
"HttpStageWithPropertiesC0AABA83": {
"Type": "AWS::ApiGatewayV2::Stage",
"Properties": {
"ApiId": {
"Ref": "HttpApiF5A9A8A7"
},
"StageName": "$default",
"DefaultRouteSettings": {
"ThrottlingBurstLimit": 1000,
"ThrottlingRateLimit": 1000
}
}
}
}
}
17 changes: 17 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/test/http/integ.stage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env node
import * as cdk from '@aws-cdk/core';
import * as apigw from '../../lib';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-cdk-aws-apigatewayv2-http-stage');

const httpApi = new apigw.HttpApi(stack, 'HttpApi', { createDefaultStage: false });
new apigw.HttpStage(stack, 'HttpStageWithProperties', {
httpApi,
throttle: {
rateLimit: 1000,
burstLimit: 1000,
},
});

app.synth();
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"Resources": {
"HttpApiF5A9A8A7": {
"Type": "AWS::ApiGatewayV2::Api",
"Properties": {
"Name": "HttpApi",
"ProtocolType": "HTTP"
}
},
"HttpStageWithPropertiesC0AABA83": {
"Type": "AWS::ApiGatewayV2::Stage",
"Properties": {
"ApiId": {
"Ref": "HttpApiF5A9A8A7"
},
"StageName": "$default",
"DefaultRouteSettings": {
"ThrottlingBurstLimit": 1000,
"ThrottlingRateLimit": 1000
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":"17.0.0"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"version": "17.0.0",
"artifacts": {
"Tree": {
"type": "cdk:tree",
"properties": {
"file": "tree.json"
},
"metadata": {}
},
"aws-cdk-aws-apigatewayv2-http-stage": {
"type": "aws:cloudformation:stack",
"environment": "aws://unknown-account/unknown-region",
"properties": {
"templateFile": "aws-cdk-aws-apigatewayv2-http-stage.template.json",
"validateOnSynth": false
},
"metadata": {
"/aws-cdk-aws-apigatewayv2-http-stage/HttpApi/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "HttpApiF5A9A8A7"
}
],
"/aws-cdk-aws-apigatewayv2-http-stage/HttpStageWithProperties/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "HttpStageWithPropertiesC0AABA83"
}
]
},
"displayName": "aws-cdk-aws-apigatewayv2-http-stage"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"version": "tree-0.1",
"tree": {
"id": "App",
"path": "",
"children": {
"Tree": {
"id": "Tree",
"path": "Tree",
"constructInfo": {
"fqn": "@aws-cdk/core.Construct",
"version": "0.0.0"
}
},
"aws-cdk-aws-apigatewayv2-http-stage": {
"id": "aws-cdk-aws-apigatewayv2-http-stage",
"path": "aws-cdk-aws-apigatewayv2-http-stage",
"children": {
"HttpApi": {
"id": "HttpApi",
"path": "aws-cdk-aws-apigatewayv2-http-stage/HttpApi",
"children": {
"Resource": {
"id": "Resource",
"path": "aws-cdk-aws-apigatewayv2-http-stage/HttpApi/Resource",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Api",
"aws:cdk:cloudformation:props": {
"name": "HttpApi",
"protocolType": "HTTP"
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-apigatewayv2.CfnApi",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-apigatewayv2.HttpApi",
"version": "0.0.0"
}
},
"HttpStageWithProperties": {
"id": "HttpStageWithProperties",
"path": "aws-cdk-aws-apigatewayv2-http-stage/HttpStageWithProperties",
"children": {
"Resource": {
"id": "Resource",
"path": "aws-cdk-aws-apigatewayv2-http-stage/HttpStageWithProperties/Resource",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Stage",
"aws:cdk:cloudformation:props": {
"apiId": {
"Ref": "HttpApiF5A9A8A7"
},
"stageName": "$default",
"defaultRouteSettings": {
"throttlingBurstLimit": 1000,
"throttlingRateLimit": 1000
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-apigatewayv2.CfnStage",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-apigatewayv2.HttpStage",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/core.Stack",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/core.App",
"version": "0.0.0"
}
}
}
29 changes: 28 additions & 1 deletion packages/@aws-cdk/aws-apigatewayv2/test/http/stage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,31 @@ describe('HttpStage with domain mapping', () => {

expect(t).toThrow(/domainUrl is not available when no API mapping is associated with the Stage/);
});
});

test('correctly sets throttle settings', () => {
// GIVEN
const stack = new Stack();
const api = new HttpApi(stack, 'Api', {
createDefaultStage: false,
});

// WHEN
new HttpStage(stack, 'DefaultStage', {
httpApi: api,
throttle: {
burstLimit: 1000,
rateLimit: 1000,
},
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Stage', {
ApiId: stack.resolve(api.apiId),
StageName: '$default',
DefaultRouteSettings: {
ThrottlingBurstLimit: 1000,
ThrottlingRateLimit: 1000,
},
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"Resources": {
"WebSocketApi34BCF99B": {
"Type": "AWS::ApiGatewayV2::Api",
"Properties": {
"Name": "WebSocketApi",
"ProtocolType": "WEBSOCKET",
"RouteSelectionExpression": "$request.body.action"
}
},
"WebSocketStageC46B7E43": {
"Type": "AWS::ApiGatewayV2::Stage",
"Properties": {
"ApiId": {
"Ref": "WebSocketApi34BCF99B"
},
"StageName": "dev",
"DefaultRouteSettings": {
"ThrottlingBurstLimit": 1000,
"ThrottlingRateLimit": 1000
}
}
}
}
}
18 changes: 18 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/test/websocket/integ.stage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env node
import * as cdk from '@aws-cdk/core';
import * as apigw from '../../lib';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-cdk-aws-apigatewayv2-websocket-stage');

const webSocketApi = new apigw.WebSocketApi(stack, 'WebSocketApi');
new apigw.WebSocketStage(stack, 'WebSocketStage', {
webSocketApi,
stageName: 'dev',
throttle: {
rateLimit: 1000,
burstLimit: 1000,
},
});

app.synth();
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"Resources": {
"WebSocketApi34BCF99B": {
"Type": "AWS::ApiGatewayV2::Api",
"Properties": {
"Name": "WebSocketApi",
"ProtocolType": "WEBSOCKET",
"RouteSelectionExpression": "$request.body.action"
}
},
"WebSocketStageC46B7E43": {
"Type": "AWS::ApiGatewayV2::Stage",
"Properties": {
"ApiId": {
"Ref": "WebSocketApi34BCF99B"
},
"StageName": "dev",
"DefaultRouteSettings": {
"ThrottlingBurstLimit": 1000,
"ThrottlingRateLimit": 1000
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":"17.0.0"}
Loading