Skip to content

feat(apigateway): add mode property for SpecRestApi #34198

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

Merged
merged 18 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from 9 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
25 changes: 24 additions & 1 deletion packages/aws-cdk-lib/aws-apigateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ running on AWS Lambda, or any web application.
- [Cognito User Pools authorizer](#cognito-user-pools-authorizer)
- [Mutual TLS (mTLS)](#mutual-tls-mtls)
- [Deployments](#deployments)
- [Deploying to an existing stage](#deploying-to-an-existing-stage)
- [Using RestApi](#using-restapi)
- [Using SpecRestApi](#using-specrestapi)
- [Controlled triggering of deployments](#controlled-triggering-of-deployments)
- [Deep dive: Invalidation of deployments](#deep-dive-invalidation-of-deployments)
- [Custom Domains](#custom-domains)
- [Custom Domains with multi-level api mapping](#custom-domains-with-multi-level-api-mapping)
Expand Down Expand Up @@ -1600,6 +1604,25 @@ booksResource.addMethod('GET', integration);

It is possible to use the `addResource()` API to define additional API Gateway Resources.

You can control how API Gateway handles resource updates using the `mode` property. Valid values are:

* `overwrite` - The new API definition replaces the existing one. The existing API identifier remains unchanged.
* `merge` - The new API definition is merged with the existing API.

If you don't specify this property, a default value is chosen:
* For REST APIs created before March 29, 2021, the default is `overwrite`
* For REST APIs created after March 29, 2021, the new API definition takes precedence, but any container types such as endpoint configurations and binary media types are merged with the existing API.

Use the default mode to define top-level RestApi properties in addition to using OpenAPI.
Generally, it's preferred to use API Gateway's OpenAPI extensions to model these properties.

```ts
const api = new apigateway.SpecRestApi(this, 'books-api', {
apiDefinition: apigateway.ApiDefinition.fromAsset('path-to-file.json'),
mode: apigateway.RestApiMode.MERGE
});
```
Copy link
Contributor

@go-to-k go-to-k Apr 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry. I noticed that the description should be below the following statement:

**Note:** When starting off with an OpenAPI definition using `SpecRestApi`, it is not possible to configure some
properties that can be configured directly in the OpenAPI specification file. This is to prevent people duplication
of these properties and potential confusion.

And it might be good to change the following sentence to be more natural... (Because the description is related to the above statements, or will be in conflict.)

You can control how API Gateway handles resource updates using the `mode` property. Valid values are:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed. Added However, .


**Note:** Deployment will fail if a Resource of the same name is already defined in the Open API specification.

**Note:** Any default properties configured, such as `defaultIntegration`, `defaultMethodOptions`, etc. will only be
Expand Down Expand Up @@ -1667,4 +1690,4 @@ Move to using `aws-apigatewayv2` to get the latest APIs and updates.

----

This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.
This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.
42 changes: 41 additions & 1 deletion packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export interface RestApiBaseProps {
/**
* The removal policy applied to the AWS CloudWatch role when this resource
* is removed from the application.
* Requires `cloudWatchRole` to be enabled.
* Requires `cloudWatchRole` to be enabled.
*
* @default - RemovalPolicy.RETAIN
*/
Expand Down Expand Up @@ -275,6 +275,7 @@ export interface RestApiProps extends RestApiOptions {
* @default - Metering is disabled.
*/
readonly apiKeySourceType?: ApiKeySourceType;

}

/**
Expand All @@ -298,6 +299,28 @@ export interface SpecRestApiProps extends RestApiBaseProps {
* @default - Compression is disabled.
*/
readonly minCompressionSize?: Size;

/**
* This property applies only when you use OpenAPI to define your REST API.
* The Mode determines how API Gateway handles resource updates.
*
* Valid values are `overwrite` or `merge`.
*
* For `overwrite`, the new API definition replaces the existing one.
* The existing API identifier remains unchanged.
*
* For `merge`, the new API definition is merged with the existing API.
*
* If you don't specify this property, a default value is chosen:
* - For REST APIs created before March 29, 2021, the default is `overwrite`
* - For REST APIs created after March 29, 2021, the new API definition takes precedence, but any container types such as endpoint configurations and binary media types are merged with the existing API.
*
* Use the default mode to define top-level RestApi properties in addition to using OpenAPI.
* Generally, it's preferred to use API Gateway's OpenAPI extensions to model these properties.
*
* @default - `merge` for REST APIs created after March 29, 2021, otherwise `overwrite`
*/
readonly mode?: RestApiMode;
}

/**
Expand Down Expand Up @@ -754,6 +777,7 @@ export class SpecRestApi extends RestApiBase {
endpointConfiguration: this._configureEndpoints(props),
parameters: props.parameters,
disableExecuteApiEndpoint: props.disableExecuteApiEndpoint,
mode: props.mode,
});

props.apiDefinition.bindAfterCreate(this, this);
Expand Down Expand Up @@ -1058,6 +1082,22 @@ export enum EndpointType {
PRIVATE = 'PRIVATE',
}

/**
* Specifies how API Gateway handles resource updates when importing an OpenAPI definition.
* This property applies only when you use OpenAPI to define your REST API.
*/
export enum RestApiMode {
/**
* The new API definition replaces the existing one.
*/
OVERWRITE = 'overwrite',

/**
* The new API definition is merged with the existing API.
*/
MERGE = 'merge',
}

class RootResource extends ResourceBase {
public readonly parentResource?: IResource;
public readonly api: RestApiBase;
Expand Down
23 changes: 22 additions & 1 deletion packages/aws-cdk-lib/aws-apigateway/test/restapi.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { testDeprecated } from '@aws-cdk/cdk-build-tools';
import { cx_api } from '../..';
import { Template } from '../../assertions';
import { Template, Match } from '../../assertions';
import { UserPool } from '../../aws-cognito';
import { GatewayVpcEndpoint } from '../../aws-ec2';
import * as ec2 from '../../aws-ec2';
Expand Down Expand Up @@ -915,6 +915,7 @@ describe('restapi', () => {
});
}).toThrow(/'cloudWatchRole' must be enabled for 'cloudWatchRoleRemovalPolicy' to be applied./);
});

});

describe('Import', () => {
Expand Down Expand Up @@ -1416,6 +1417,26 @@ describe('SpecRestApi', () => {
});
});

test.each([
[apigw.RestApiMode.OVERWRITE, 'overwrite'],
[apigw.RestApiMode.MERGE, 'merge'],
[undefined, Match.absent()],
])('mode property is set (%s)', (mode, expectedMode) => {
// WHEN
const api = new apigw.SpecRestApi(stack, 'api', {
apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }),
mode,
});

api.root.addMethod('GET');

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::RestApi', {
Name: 'api',
Mode: expectedMode ?? Match.absent(),
});
});

describe('addToResourcePolicy', () => {
test('add a statement to the resource policy for RestApi', () => {
// GIVEN
Expand Down
Loading