import { Construct } from 'constructs'; import { ApiDefinition } from './api-definition'; import { ApiKey, ApiKeyOptions, IApiKey } from './api-key'; import { ApiGatewayMetrics } from './apigateway-canned-metrics.generated'; import { CfnAccount, CfnRestApi } from './apigateway.generated'; import { CorsOptions } from './cors'; import { Deployment } from './deployment'; import { DomainName, DomainNameOptions } from './domain-name'; import { GatewayResponse, GatewayResponseOptions } from './gateway-response'; import { Integration } from './integration'; import { Method, MethodOptions } from './method'; import { Model, ModelOptions } from './model'; import { RequestValidator, RequestValidatorOptions } from './requestvalidator'; import { IResource, ResourceBase, ResourceOptions } from './resource'; import { Stage, StageOptions } from './stage'; import { UsagePlan, UsagePlanProps } from './usage-plan'; import * as cloudwatch from '../../aws-cloudwatch'; import { IVpcEndpoint } from '../../aws-ec2'; import * as iam from '../../aws-iam'; import { ArnFormat, CfnOutput, IResource as IResourceBase, Resource, Stack, Token, FeatureFlags, RemovalPolicy, Size } from '../../core'; import { APIGATEWAY_DISABLE_CLOUDWATCH_ROLE } from '../../cx-api'; const RESTAPI_SYMBOL = Symbol.for('@aws-cdk/aws-apigateway.RestApiBase'); export interface IRestApi extends IResourceBase { /** * The ID of this API Gateway RestApi. * @attribute */ readonly restApiId: string; /** * The name of this API Gateway RestApi. * @attribute */ readonly restApiName: string; /** * The resource ID of the root resource. * @attribute */ readonly restApiRootResourceId: string; /** * API Gateway deployment that represents the latest changes of the API. * This resource will be automatically updated every time the REST API model changes. * `undefined` when no deployment is configured. */ readonly latestDeployment?: Deployment; /** * API Gateway stage that points to the latest deployment (if defined). */ deploymentStage: Stage; /** * Represents the root resource ("/") of this API. Use it to define the API model: * * api.root.addMethod('ANY', redirectToHomePage); // "ANY /" * api.root.addResource('friends').addMethod('GET', getFriendsHandler); // "GET /friends" * */ readonly root: IResource; /** * Gets the "execute-api" ARN * @returns The "execute-api" ARN. * @default "*" returns the execute API ARN for all methods/resources in * this API. * @param method The method (default `*`) * @param path The resource path. Must start with '/' (default `*`) * @param stage The stage (default `*`) */ arnForExecuteApi(method?: string, path?: string, stage?: string): string; } /** * Represents the props that all Rest APIs share */ export interface RestApiBaseProps { /** * Indicates if a Deployment should be automatically created for this API, * and recreated when the API model (resources, methods) changes. * * Since API Gateway deployments are immutable, When this option is enabled * (by default), an AWS::ApiGateway::Deployment resource will automatically * created with a logical ID that hashes the API model (methods, resources * and options). This means that when the model changes, the logical ID of * this CloudFormation resource will change, and a new deployment will be * created. * * If this is set, `latestDeployment` will refer to the `Deployment` object * and `deploymentStage` will refer to a `Stage` that points to this * deployment. To customize the stage options, use the `deployOptions` * property. * * A CloudFormation Output will also be defined with the root URL endpoint * of this REST API. * * @default true */ readonly deploy?: boolean; /** * Options for the API Gateway stage that will always point to the latest * deployment when `deploy` is enabled. If `deploy` is disabled, * this value cannot be set. * * @default - Based on defaults of `StageOptions`. */ readonly deployOptions?: StageOptions; /** * Retains old deployment resources when the API changes. This allows * manually reverting stages to point to old deployments via the AWS * Console. * * @default false */ readonly retainDeployments?: boolean; /** * A name for the API Gateway RestApi resource. * * @default - ID of the RestApi construct. */ readonly restApiName?: string; /** * Custom header parameters for the request. * @see https://docs.aws.amazon.com/cli/latest/reference/apigateway/import-rest-api.html * * @default - No parameters. */ readonly parameters?: { [key: string]: string }; /** * A policy document that contains the permissions for this RestApi * * @default - No policy. */ readonly policy?: iam.PolicyDocument; /** * Indicates whether to roll back the resource if a warning occurs while API * Gateway is creating the RestApi resource. * * @default false */ readonly failOnWarnings?: boolean; /** * Configure a custom domain name and map it to this API. * * @default - no domain name is defined, use `addDomainName` or directly define a `DomainName`. */ readonly domainName?: DomainNameOptions; /** * Automatically configure an AWS CloudWatch role for API Gateway. * * @default - false if `@aws-cdk/aws-apigateway:disableCloudWatchRole` is enabled, true otherwise */ readonly cloudWatchRole?: boolean; /** * Export name for the CfnOutput containing the API endpoint * * @default - when no export name is given, output will be created without export */ readonly endpointExportName?: string; /** * A list of the endpoint types of the API. Use this property when creating * an API. * * @default EndpointType.EDGE */ readonly endpointTypes?: EndpointType[]; /** * Specifies whether clients can invoke the API using the default execute-api * endpoint. To require that clients use a custom domain name to invoke the * API, disable the default endpoint. * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html * * @default false */ readonly disableExecuteApiEndpoint?: boolean; /** * A description of the RestApi construct. * * @default - 'Automatically created by the RestApi construct' */ readonly description?: string; } /** * Represents the props that all Rest APIs share. * @deprecated - superseded by `RestApiBaseProps` */ export interface RestApiOptions extends RestApiBaseProps, ResourceOptions { } /** * Props to create a new instance of RestApi */ export interface RestApiProps extends RestApiOptions { /** * The list of binary media mime-types that are supported by the RestApi * resource, such as "image/png" or "application/octet-stream" * * @default - RestApi supports only UTF-8-encoded text payloads. */ readonly binaryMediaTypes?: string[]; /** * A nullable integer that is used to enable compression (with non-negative * between 0 and 10485760 (10M) bytes, inclusive) or disable compression * (when undefined) on an API. When compression is enabled, compression or * decompression is not applied on the payload if the payload size is * smaller than this value. Setting it to zero allows compression for any * payload size. * * @default - Compression is disabled. * @deprecated - superseded by `minCompressionSize` */ readonly minimumCompressionSize?: number; /** * A Size(in bytes, kibibytes, mebibytes etc) that is used to enable compression (with non-negative * between 0 and 10485760 (10M) bytes, inclusive) or disable compression * (when undefined) on an API. When compression is enabled, compression or * decompression is not applied on the payload if the payload size is * smaller than this value. Setting it to zero allows compression for any * payload size. * * @default - Compression is disabled. */ readonly minCompressionSize?: Size; /** * The ID of the API Gateway RestApi resource that you want to clone. * * @default - None. */ readonly cloneFrom?: IRestApi; /** * The source of the API key for metering requests according to a usage * plan. * * @default - Metering is disabled. */ readonly apiKeySourceType?: ApiKeySourceType; /** * The EndpointConfiguration property type specifies the endpoint types of a REST API * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-restapi-endpointconfiguration.html * * @default EndpointType.EDGE */ readonly endpointConfiguration?: EndpointConfiguration; } /** * Props to instantiate a new SpecRestApi */ export interface SpecRestApiProps extends RestApiBaseProps { /** * An OpenAPI definition compatible with API Gateway. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-import-api.html */ readonly apiDefinition: ApiDefinition; /** * A Size(in bytes, kibibytes, mebibytes etc) that is used to enable compression (with non-negative * between 0 and 10485760 (10M) bytes, inclusive) or disable compression * (when undefined) on an API. When compression is enabled, compression or * decompression is not applied on the payload if the payload size is * smaller than this value. Setting it to zero allows compression for any * payload size. * * @default - Compression is disabled. */ readonly minCompressionSize?: Size; } /** * Base implementation that are common to various implementations of IRestApi */ export abstract class RestApiBase extends Resource implements IRestApi { /** * Checks if the given object is an instance of RestApiBase. * @internal */ public static _isRestApiBase(x: any): x is RestApiBase { return x !== null && typeof(x) === 'object' && RESTAPI_SYMBOL in x; } /** * API Gateway deployment that represents the latest changes of the API. * This resource will be automatically updated every time the REST API model changes. * This will be undefined if `deploy` is false. */ public get latestDeployment() { return this._latestDeployment; } /** * The first domain name mapped to this API, if defined through the `domainName` * configuration prop, or added via `addDomainName` */ public get domainName() { return this._domainName; } /** * The ID of this API Gateway RestApi. */ public abstract readonly restApiId: string; /** * The resource ID of the root resource. * * @attribute */ public abstract readonly restApiRootResourceId: string; /** * Represents the root resource of this API endpoint ('/'). * Resources and Methods are added to this resource. */ public abstract readonly root: IResource; /** * API Gateway stage that points to the latest deployment (if defined). * * If `deploy` is disabled, you will need to explicitly assign this value in order to * set up integrations. */ public deploymentStage!: Stage; /** * A human friendly name for this Rest API. Note that this is different from `restApiId`. * @attribute */ public readonly restApiName: string; private _latestDeployment?: Deployment; private _domainName?: DomainName; protected cloudWatchAccount?: CfnAccount; constructor(scope: Construct, id: string, props: RestApiBaseProps = { }) { const restApiName = props.restApiName ?? id; super(scope, id, { physicalName: restApiName, }); this.restApiName = restApiName; Object.defineProperty(this, RESTAPI_SYMBOL, { value: true }); } /** * Returns the URL for an HTTP path. * * Fails if `deploymentStage` is not set either by `deploy` or explicitly. */ public urlForPath(path: string = '/'): string { if (!this.deploymentStage) { throw new Error('Cannot determine deployment stage for API from "deploymentStage". Use "deploy" or explicitly set "deploymentStage"'); } return this.deploymentStage.urlForPath(path); } /** * Defines an API Gateway domain name and maps it to this API. * @param id The construct id * @param options custom domain options */ public addDomainName(id: string, options: DomainNameOptions): DomainName { const domainName = new DomainName(this, id, { ...options, mapping: this, }); if (!this._domainName) { this._domainName = domainName; } return domainName; } /** * Adds a usage plan. */ public addUsagePlan(id: string, props: UsagePlanProps = {}): UsagePlan { return new UsagePlan(this, id, props); } public arnForExecuteApi(method: string = '*', path: string = '/*', stage: string = '*') { if (!Token.isUnresolved(path) && !path.startsWith('/')) { throw new Error(`"path" must begin with a "/": '${path}'`); } if (method.toUpperCase() === 'ANY') { method = '*'; } return Stack.of(this).formatArn({ service: 'execute-api', resource: this.restApiId, arnFormat: ArnFormat.SLASH_RESOURCE_NAME, resourceName: `${stage}/${method}${path}`, }); } /** * Adds a new gateway response. */ public addGatewayResponse(id: string, options: GatewayResponseOptions): GatewayResponse { return new GatewayResponse(this, id, { restApi: this, ...options, }); } /** * Add an ApiKey to the deploymentStage */ public addApiKey(id: string, options?: ApiKeyOptions): IApiKey { return new ApiKey(this, id, { stages: [this.deploymentStage], ...options, }); } /** * Returns the given named metric for this API */ public metric(metricName: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric { return new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName, dimensionsMap: { ApiName: this.restApiName }, ...props, }).attachTo(this); } /** * Metric for the number of client-side errors captured in a given period. * * Default: sum over 5 minutes */ public metricClientError(props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics._4XxErrorSum, props); } /** * Metric for the number of server-side errors captured in a given period. * * Default: sum over 5 minutes */ public metricServerError(props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics._5XxErrorSum, props); } /** * Metric for the number of requests served from the API cache in a given period. * * Default: sum over 5 minutes */ public metricCacheHitCount(props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.cacheHitCountSum, props); } /** * Metric for the number of requests served from the backend in a given period, * when API caching is enabled. * * Default: sum over 5 minutes */ public metricCacheMissCount(props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.cacheMissCountSum, props); } /** * Metric for the total number API requests in a given period. * * Default: sample count over 5 minutes */ public metricCount(props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.countSum, { statistic: 'SampleCount', ...props, }); } /** * Metric for the time between when API Gateway relays a request to the backend * and when it receives a response from the backend. * * Default: average over 5 minutes. */ public metricIntegrationLatency(props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.integrationLatencyAverage, props); } /** * The time between when API Gateway receives a request from a client * and when it returns a response to the client. * The latency includes the integration latency and other API Gateway overhead. * * Default: average over 5 minutes. */ public metricLatency(props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.latencyAverage, props); } /** * Internal API used by `Method` to keep an inventory of methods at the API * level for validation purposes. * * @internal */ public _attachMethod(method: Method) { ignore(method); } /** * Associates a Deployment resource with this REST API. * * @internal */ public _attachDeployment(deployment: Deployment) { ignore(deployment); } /** * Associates a Stage with this REST API * * @internal */ public _attachStage(stage: Stage) { if (this.cloudWatchAccount) { stage.node.addDependency(this.cloudWatchAccount); } } /** * @internal */ protected _configureCloudWatchRole(apiResource: CfnRestApi) { const role = new iam.Role(this, 'CloudWatchRole', { assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'), managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonAPIGatewayPushToCloudWatchLogs')], }); role.applyRemovalPolicy(RemovalPolicy.RETAIN); this.cloudWatchAccount = new CfnAccount(this, 'Account', { cloudWatchRoleArn: role.roleArn, }); this.cloudWatchAccount.applyRemovalPolicy(RemovalPolicy.RETAIN); this.cloudWatchAccount.node.addDependency(apiResource); } /** * @deprecated This method will be made internal. No replacement */ protected configureCloudWatchRole(apiResource: CfnRestApi) { this._configureCloudWatchRole(apiResource); } /** * @deprecated This method will be made internal. No replacement */ protected configureDeployment(props: RestApiBaseProps) { this._configureDeployment(props); } /** * @internal */ protected _configureDeployment(props: RestApiBaseProps) { const deploy = props.deploy ?? true; if (deploy) { this._latestDeployment = new Deployment(this, 'Deployment', { description: props.description? props.description :'Automatically created by the RestApi construct', api: this, retainDeployments: props.retainDeployments, }); // encode the stage name into the construct id, so if we change the stage name, it will recreate a new stage. // stage name is part of the endpoint, so that makes sense. const stageName = (props.deployOptions && props.deployOptions.stageName) || 'prod'; this.deploymentStage = new Stage(this, `DeploymentStage.${stageName}`, { deployment: this._latestDeployment, ...props.deployOptions, }); new CfnOutput(this, 'Endpoint', { exportName: props.endpointExportName, value: this.urlForPath() }); } else { if (props.deployOptions) { throw new Error('Cannot set \'deployOptions\' if \'deploy\' is disabled'); } } } /** * @internal */ protected _configureEndpoints(props: RestApiProps): CfnRestApi.EndpointConfigurationProperty | undefined { if (props.endpointTypes && props.endpointConfiguration) { throw new Error('Only one of the RestApi props, endpointTypes or endpointConfiguration, is allowed'); } if (props.endpointConfiguration) { return { types: props.endpointConfiguration.types, vpcEndpointIds: props.endpointConfiguration?.vpcEndpoints?.map(vpcEndpoint => vpcEndpoint.vpcEndpointId), }; } if (props.endpointTypes) { return { types: props.endpointTypes }; } return undefined; } private cannedMetric(fn: (dims: { ApiName: string }) => cloudwatch.MetricProps, props?: cloudwatch.MetricOptions) { return new cloudwatch.Metric({ ...fn({ ApiName: this.restApiName }), ...props, }).attachTo(this); } } /** * Represents a REST API in Amazon API Gateway, created with an OpenAPI specification. * * Some properties normally accessible on @see `RestApi` - such as the description - * must be declared in the specification. All Resources and Methods need to be defined as * part of the OpenAPI specification file, and cannot be added via the CDK. * * By default, the API will automatically be deployed and accessible from a * public endpoint. * * * @resource AWS::ApiGateway::RestApi */ export class SpecRestApi extends RestApiBase { /** * The ID of this API Gateway RestApi. */ public readonly restApiId: string; /** * The resource ID of the root resource. * * @attribute */ public readonly restApiRootResourceId: string; public readonly root: IResource; constructor(scope: Construct, id: string, props: SpecRestApiProps) { super(scope, id, props); const apiDefConfig = props.apiDefinition.bind(this); const resource = new CfnRestApi(this, 'Resource', { name: this.restApiName, policy: props.policy, failOnWarnings: props.failOnWarnings, minimumCompressionSize: props.minCompressionSize?.toBytes(), body: apiDefConfig.inlineDefinition ?? undefined, bodyS3Location: apiDefConfig.inlineDefinition ? undefined : apiDefConfig.s3Location, endpointConfiguration: this._configureEndpoints(props), parameters: props.parameters, disableExecuteApiEndpoint: props.disableExecuteApiEndpoint, }); props.apiDefinition.bindAfterCreate(this, this); this.node.defaultChild = resource; this.restApiId = resource.ref; this.restApiRootResourceId = resource.attrRootResourceId; this.root = new RootResource(this, {}, this.restApiRootResourceId); const cloudWatchRoleDefault = FeatureFlags.of(this).isEnabled(APIGATEWAY_DISABLE_CLOUDWATCH_ROLE) ? false : true; const cloudWatchRole = props.cloudWatchRole ?? cloudWatchRoleDefault; if (cloudWatchRole) { this._configureCloudWatchRole(resource); } this._configureDeployment(props); if (props.domainName) { this.addDomainName('CustomDomain', props.domainName); } } } /** * Attributes that can be specified when importing a RestApi */ export interface RestApiAttributes { /** * The ID of the API Gateway RestApi. */ readonly restApiId: string; /** * The name of the API Gateway RestApi. * * @default - ID of the RestApi construct. */ readonly restApiName?: string; /** * The resource ID of the root resource. */ readonly rootResourceId: string; } /** * Represents a REST API in Amazon API Gateway. * * Use `addResource` and `addMethod` to configure the API model. * * By default, the API will automatically be deployed and accessible from a * public endpoint. */ export class RestApi extends RestApiBase { /** * Import an existing RestApi. */ public static fromRestApiId(scope: Construct, id: string, restApiId: string): IRestApi { class Import extends RestApiBase { public readonly restApiId = restApiId; public get root(): IResource { throw new Error('root is not configured when imported using `fromRestApiId()`. Use `fromRestApiAttributes()` API instead.'); } public get restApiRootResourceId(): string { throw new Error('restApiRootResourceId is not configured when imported using `fromRestApiId()`. Use `fromRestApiAttributes()` API instead.'); } } return new Import(scope, id); } /** * Import an existing RestApi that can be configured with additional Methods and Resources. */ public static fromRestApiAttributes(scope: Construct, id: string, attrs: RestApiAttributes): IRestApi { class Import extends RestApiBase { public readonly restApiId = attrs.restApiId; public readonly restApiName = attrs.restApiName ?? id; public readonly restApiRootResourceId = attrs.rootResourceId; public readonly root: IResource = new RootResource(this, {}, this.restApiRootResourceId); } return new Import(scope, id); } public readonly restApiId: string; public readonly root: IResource; public readonly restApiRootResourceId: string; /** * The list of methods bound to this RestApi */ public readonly methods = new Array<Method>(); /** * This list of deployments bound to this RestApi */ private readonly deployments = new Array<Deployment>(); constructor(scope: Construct, id: string, props: RestApiProps = { }) { super(scope, id, props); if (props.minCompressionSize !== undefined && props.minimumCompressionSize !== undefined) { throw new Error('both properties minCompressionSize and minimumCompressionSize cannot be set at once.'); } const resource = new CfnRestApi(this, 'Resource', { name: this.physicalName, description: props.description, policy: props.policy, failOnWarnings: props.failOnWarnings, minimumCompressionSize: props.minCompressionSize?.toBytes() ?? props.minimumCompressionSize, binaryMediaTypes: props.binaryMediaTypes, endpointConfiguration: this._configureEndpoints(props), apiKeySourceType: props.apiKeySourceType, cloneFrom: props.cloneFrom?.restApiId, parameters: props.parameters, disableExecuteApiEndpoint: props.disableExecuteApiEndpoint, }); this.node.defaultChild = resource; this.restApiId = resource.ref; const cloudWatchRoleDefault = FeatureFlags.of(this).isEnabled(APIGATEWAY_DISABLE_CLOUDWATCH_ROLE) ? false : true; const cloudWatchRole = props.cloudWatchRole ?? cloudWatchRoleDefault; if (cloudWatchRole) { this._configureCloudWatchRole(resource); } this._configureDeployment(props); if (props.domainName) { this.addDomainName('CustomDomain', props.domainName); } this.root = new RootResource(this, props, resource.attrRootResourceId); this.restApiRootResourceId = resource.attrRootResourceId; this.node.addValidation({ validate: () => this.validateRestApi() }); } /** * The deployed root URL of this REST API. */ public get url() { return this.urlForPath(); } /** * Adds a new model. */ public addModel(id: string, props: ModelOptions): Model { return new Model(this, id, { ...props, restApi: this, }); } /** * Adds a new request validator. */ public addRequestValidator(id: string, props: RequestValidatorOptions): RequestValidator { return new RequestValidator(this, id, { ...props, restApi: this, }); } /** * Internal API used by `Method` to keep an inventory of methods at the API * level for validation purposes. * * @internal */ public _attachMethod(method: Method) { this.methods.push(method); // add this method as a dependency to all deployments defined for this api // when additional deployments are added, _attachDeployment is called and // this method will be added there. for (const dep of this.deployments) { dep._addMethodDependency(method); } } /** * Attaches a deployment to this REST API. * * @internal */ public _attachDeployment(deployment: Deployment) { this.deployments.push(deployment); // add all methods that were already defined as dependencies of this // deployment when additional methods are added, _attachMethod is called and // it will be added as a dependency to this deployment. for (const method of this.methods) { deployment._addMethodDependency(method); } } /** * Performs validation of the REST API. */ private validateRestApi() { if (this.methods.length === 0) { return ["The REST API doesn't contain any methods"]; } return []; } } /** * The endpoint configuration of a REST API, including VPCs and endpoint types. * * EndpointConfiguration is a property of the AWS::ApiGateway::RestApi resource. */ export interface EndpointConfiguration { /** * A list of endpoint types of an API or its custom domain name. * * @default EndpointType.EDGE */ readonly types: EndpointType[]; /** * A list of VPC Endpoints against which to create Route53 ALIASes * * @default - no ALIASes are created for the endpoint. */ readonly vpcEndpoints?: IVpcEndpoint[]; } export enum ApiKeySourceType { /** * To read the API key from the `X-API-Key` header of a request. */ HEADER = 'HEADER', /** * To read the API key from the `UsageIdentifierKey` from a custom authorizer. */ AUTHORIZER = 'AUTHORIZER', } export enum EndpointType { /** * For an edge-optimized API and its custom domain name. */ EDGE = 'EDGE', /** * For a regional API and its custom domain name. */ REGIONAL = 'REGIONAL', /** * For a private API and its custom domain name. */ PRIVATE = 'PRIVATE' } class RootResource extends ResourceBase { public readonly parentResource?: IResource; public readonly api: RestApiBase; public readonly resourceId: string; public readonly path: string; public readonly defaultIntegration?: Integration | undefined; public readonly defaultMethodOptions?: MethodOptions | undefined; public readonly defaultCorsPreflightOptions?: CorsOptions | undefined; private readonly _restApi?: RestApi; constructor(api: RestApiBase, props: ResourceOptions, resourceId: string) { super(api, 'Default'); this.parentResource = undefined; this.defaultIntegration = props.defaultIntegration; this.defaultMethodOptions = props.defaultMethodOptions; this.defaultCorsPreflightOptions = props.defaultCorsPreflightOptions; this.api = api; this.resourceId = resourceId; this.path = '/'; if (api instanceof RestApi) { this._restApi = api; } if (this.defaultCorsPreflightOptions) { this.addCorsPreflight(this.defaultCorsPreflightOptions); } } /** * Get the RestApi associated with this Resource. * @deprecated - Throws an error if this Resource is not associated with an instance of `RestApi`. Use `api` instead. */ public get restApi(): RestApi { if (!this._restApi) { throw new Error('RestApi is not available on Resource not connected to an instance of RestApi. Use `api` instead'); } return this._restApi; } } function ignore(_x: any) { return; }