UNPKG

49.1 kBMarkdownView Raw
1# Amazon API Gateway Construct Library
2<!--BEGIN STABILITY BANNER-->
3
4---
5
6![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge)
7
8![cdk-constructs: Stable](https://img.shields.io/badge/cdk--constructs-stable-success.svg?style=for-the-badge)
9
10---
11
12<!--END STABILITY BANNER-->
13
14Amazon API Gateway is a fully managed service that makes it easy for developers
15to publish, maintain, monitor, and secure APIs at any scale. Create an API to
16access data, business logic, or functionality from your back-end services, such
17as applications running on Amazon Elastic Compute Cloud (Amazon EC2), code
18running on AWS Lambda, or any web application.
19
20## Table of Contents
21
22- [Defining APIs](#defining-apis)
23 - [Breaking up Methods and Resources across Stacks](#breaking-up-methods-and-resources-across-stacks)
24- [AWS Lambda-backed APIs](#aws-lambda-backed-apis)
25- [AWS StepFunctions backed APIs](#aws-stepfunctions-backed-APIs)
26- [Integration Targets](#integration-targets)
27- [Usage Plan & API Keys](#usage-plan--api-keys)
28- [Working with models](#working-with-models)
29- [Default Integration and Method Options](#default-integration-and-method-options)
30- [Proxy Routes](#proxy-routes)
31- [Authorizers](#authorizers)
32 - [IAM-based authorizer](#iam-based-authorizer)
33 - [Lambda-based token authorizer](#lambda-based-token-authorizer)
34 - [Lambda-based request authorizer](#lambda-based-request-authorizer)
35 - [Cognito User Pools authorizer](#cognito-user-pools-authorizer)
36- [Mutual TLS](#mutal-tls-mtls)
37- [Deployments](#deployments)
38 - [Deep dive: Invalidation of deployments](#deep-dive-invalidation-of-deployments)
39- [Custom Domains](#custom-domains)
40- [Access Logging](#access-logging)
41- [Cross Origin Resource Sharing (CORS)](#cross-origin-resource-sharing-cors)
42- [Endpoint Configuration](#endpoint-configuration)
43- [Private Integrations](#private-integrations)
44- [Gateway Response](#gateway-response)
45- [OpenAPI Definition](#openapi-definition)
46 - [Endpoint configuration](#endpoint-configuration)
47- [Metrics](#metrics)
48- [APIGateway v2](#apigateway-v2)
49
50## Defining APIs
51
52APIs are defined as a hierarchy of resources and methods. `addResource` and
53`addMethod` can be used to build this hierarchy. The root resource is
54`api.root`.
55
56For example, the following code defines an API that includes the following HTTP
57endpoints: `ANY /`, `GET /books`, `POST /books`, `GET /books/{book_id}`, `DELETE /books/{book_id}`.
58
59```ts
60const api = new apigateway.RestApi(this, 'books-api');
61
62api.root.addMethod('ANY');
63
64const books = api.root.addResource('books');
65books.addMethod('GET');
66books.addMethod('POST');
67
68const book = books.addResource('{book_id}');
69book.addMethod('GET');
70book.addMethod('DELETE');
71```
72
73## AWS Lambda-backed APIs
74
75A very common practice is to use Amazon API Gateway with AWS Lambda as the
76backend integration. The `LambdaRestApi` construct makes it easy:
77
78The following code defines a REST API that routes all requests to the
79specified AWS Lambda function:
80
81```ts
82declare const backend: lambda.Function;
83new apigateway.LambdaRestApi(this, 'myapi', {
84 handler: backend,
85});
86```
87
88You can also supply `proxy: false`, in which case you will have to explicitly
89define the API model:
90
91```ts
92declare const backend: lambda.Function;
93const api = new apigateway.LambdaRestApi(this, 'myapi', {
94 handler: backend,
95 proxy: false
96});
97
98const items = api.root.addResource('items');
99items.addMethod('GET'); // GET /items
100items.addMethod('POST'); // POST /items
101
102const item = items.addResource('{item}');
103item.addMethod('GET'); // GET /items/{item}
104
105// the default integration for methods is "handler", but one can
106// customize this behavior per method or even a sub path.
107item.addMethod('DELETE', new apigateway.HttpIntegration('http://amazon.com'));
108```
109
110## AWS StepFunctions backed APIs
111
112You can use Amazon API Gateway with AWS Step Functions as the backend integration, specifically Synchronous Express Workflows.
113
114The `StepFunctionsRestApi` only supports integration with Synchronous Express state machine. The `StepFunctionsRestApi` construct makes this easy by setting up input, output and error mapping.
115
116The construct sets up an API endpoint and maps the `ANY` HTTP method and any calls to the API endpoint starts an express workflow execution for the underlying state machine.
117
118Invoking the endpoint with any HTTP method (`GET`, `POST`, `PUT`, `DELETE`, ...) in the example below will send the request to the state machine as a new execution. On success, an HTTP code `200` is returned with the execution output as the Response Body.
119
120If the execution fails, an HTTP `500` response is returned with the `error` and `cause` from the execution output as the Response Body. If the request is invalid (ex. bad execution input) HTTP code `400` is returned.
121
122The response from the invocation contains only the `output` field from the
123[StartSyncExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartSyncExecution.html#API_StartSyncExecution_ResponseSyntax) API.
124In case of failures, the fields `error` and `cause` are returned as part of the response.
125Other metadata such as billing details, AWS account ID and resource ARNs are not returned in the API response.
126
127By default, a `prod` stage is provisioned.
128
129In order to reduce the payload size sent to AWS Step Functions, `headers` are not forwarded to the Step Functions execution input. It is possible to choose whether `headers`, `requestContext`, `path`, `querystring`, and `authorizer` are included or not. By default, `headers` are excluded in all requests.
130
131More details about AWS Step Functions payload limit can be found at https://docs.aws.amazon.com/step-functions/latest/dg/limits-overview.html#service-limits-task-executions.
132
133The following code defines a REST API that routes all requests to the specified AWS StepFunctions state machine:
134
135```ts
136const stateMachineDefinition = new stepfunctions.Pass(this, 'PassState');
137
138const stateMachine: stepfunctions.IStateMachine = new stepfunctions.StateMachine(this, 'StateMachine', {
139 definition: stateMachineDefinition,
140 stateMachineType: stepfunctions.StateMachineType.EXPRESS,
141});
142
143new apigateway.StepFunctionsRestApi(this, 'StepFunctionsRestApi', {
144 deploy: true,
145 stateMachine: stateMachine,
146});
147```
148
149When the REST API endpoint configuration above is invoked using POST, as follows -
150
151```bash
152curl -X POST -d '{ "customerId": 1 }' https://example.com/
153```
154
155AWS Step Functions will receive the request body in its input as follows:
156
157```json
158{
159 "body": {
160 "customerId": 1
161 },
162 "path": "/",
163 "querystring": {}
164}
165```
166
167When the endpoint is invoked at path '/users/5' using the HTTP GET method as below:
168
169```bash
170curl -X GET https://example.com/users/5?foo=bar
171```
172
173AWS Step Functions will receive the following execution input:
174
175```json
176{
177 "body": {},
178 "path": {
179 "users": "5"
180 },
181 "querystring": {
182 "foo": "bar"
183 }
184}
185```
186
187Additional information around the request such as the request context, authorizer context, and headers can be included as part of the input
188forwarded to the state machine. The following example enables headers to be included in the input but not query string.
189
190```ts fixture=stepfunctions
191new apigateway.StepFunctionsRestApi(this, 'StepFunctionsRestApi', {
192 stateMachine: machine,
193 headers: true,
194 path: false,
195 querystring: false,
196 authorizer: false,
197 requestContext: {
198 caller: true,
199 user: true,
200 },
201});
202```
203
204In such a case, when the endpoint is invoked as below:
205
206```bash
207curl -X GET https://example.com/
208```
209
210AWS Step Functions will receive the following execution input:
211
212```json
213{
214 "headers": {
215 "Accept": "...",
216 "CloudFront-Forwarded-Proto": "...",
217 },
218 "requestContext": {
219 "accountId": "...",
220 "apiKey": "...",
221 },
222 "body": {}
223}
224```
225
226### Breaking up Methods and Resources across Stacks
227
228It is fairly common for REST APIs with a large number of Resources and Methods to hit the [CloudFormation
229limit](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html) of 500 resources per
230stack.
231
232To help with this, Resources and Methods for the same REST API can be re-organized across multiple stacks. A common
233way to do this is to have a stack per Resource or groups of Resources, but this is not the only possible way.
234The following example uses sets up two Resources '/pets' and '/books' in separate stacks using nested stacks:
235
236[Resources grouped into nested stacks](test/integ.restapi-import.lit.ts)
237
238## Integration Targets
239
240Methods are associated with backend integrations, which are invoked when this
241method is called. API Gateway supports the following integrations:
242
243- `MockIntegration` - can be used to test APIs. This is the default
244 integration if one is not specified.
245- `LambdaIntegration` - can be used to invoke an AWS Lambda function.
246- `AwsIntegration` - can be used to invoke arbitrary AWS service APIs.
247- `HttpIntegration` - can be used to invoke HTTP endpoints.
248
249The following example shows how to integrate the `GET /book/{book_id}` method to
250an AWS Lambda function:
251
252```ts
253declare const getBookHandler: lambda.Function;
254declare const book: apigateway.Resource;
255
256const getBookIntegration = new apigateway.LambdaIntegration(getBookHandler);
257book.addMethod('GET', getBookIntegration);
258```
259
260Integration options can be optionally be specified:
261
262```ts
263declare const getBookHandler: lambda.Function;
264declare const getBookIntegration: apigateway.LambdaIntegration;
265
266const getBookIntegration = new apigateway.LambdaIntegration(getBookHandler, {
267 contentHandling: apigateway.ContentHandling.CONVERT_TO_TEXT, // convert to base64
268 credentialsPassthrough: true, // use caller identity to invoke the function
269});
270```
271
272Method options can optionally be specified when adding methods:
273
274```ts
275declare const book: apigateway.Resource;
276declare const getBookIntegration: apigateway.LambdaIntegration;
277
278book.addMethod('GET', getBookIntegration, {
279 authorizationType: apigateway.AuthorizationType.IAM,
280 apiKeyRequired: true
281});
282```
283
284It is possible to also integrate with AWS services in a different region. The following code integrates with Amazon SQS in the
285`eu-west-1` region.
286
287```ts
288const getMessageIntegration = new apigateway.AwsIntegration({
289 service: 'sqs',
290 path: 'queueName',
291 region: 'eu-west-1'
292});
293```
294
295## Usage Plan & API Keys
296
297A usage plan specifies who can access one or more deployed API stages and methods, and the rate at which they can be
298accessed. The plan uses API keys to identify API clients and meters access to the associated API stages for each key.
299Usage plans also allow configuring throttling limits and quota limits that are enforced on individual client API keys.
300
301The following example shows how to create and asscociate a usage plan and an API key:
302
303```ts
304declare const integration: apigateway.LambdaIntegration;
305
306const api = new apigateway.RestApi(this, 'hello-api');
307
308const v1 = api.root.addResource('v1');
309const echo = v1.addResource('echo');
310const echoMethod = echo.addMethod('GET', integration, { apiKeyRequired: true });
311
312const plan = api.addUsagePlan('UsagePlan', {
313 name: 'Easy',
314 throttle: {
315 rateLimit: 10,
316 burstLimit: 2
317 }
318});
319
320const key = api.addApiKey('ApiKey');
321plan.addApiKey(key);
322```
323
324To associate a plan to a given RestAPI stage:
325
326```ts
327declare const plan: apigateway.UsagePlan;
328declare const api: apigateway.RestApi;
329declare const echoMethod: apigateway.Method;
330
331plan.addApiStage({
332 stage: api.deploymentStage,
333 throttle: [
334 {
335 method: echoMethod,
336 throttle: {
337 rateLimit: 10,
338 burstLimit: 2
339 }
340 }
341 ]
342});
343```
344
345Existing usage plans can be imported into a CDK app using its id.
346
347```ts
348const importedUsagePlan = apigateway.UsagePlan.fromUsagePlanId(this, 'imported-usage-plan', '<usage-plan-key-id>');
349```
350
351The name and value of the API Key can be specified at creation; if not
352provided, a name and value will be automatically generated by API Gateway.
353
354```ts
355declare const api: apigateway.RestApi;
356const key = api.addApiKey('ApiKey', {
357 apiKeyName: 'myApiKey1',
358 value: 'MyApiKeyThatIsAtLeast20Characters',
359});
360```
361
362Existing API keys can also be imported into a CDK app using its id.
363
364```ts
365const importedKey = apigateway.ApiKey.fromApiKeyId(this, 'imported-key', '<api-key-id>');
366```
367
368The "grant" methods can be used to give prepackaged sets of permissions to other resources. The
369following code provides read permission to an API key.
370
371```ts
372declare const importedKey: apigateway.ApiKey;
373declare const lambdaFn: lambda.Function;
374importedKey.grantRead(lambdaFn);
375```
376
377### ⚠️ Multiple API Keys
378
379It is possible to specify multiple API keys for a given Usage Plan, by calling `usagePlan.addApiKey()`.
380
381When using multiple API keys, a past bug of the CDK prevents API key associations to a Usage Plan to be deleted.
382If the CDK app had the [feature flag] - `@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId` - enabled when the API
383keys were created, then the app will not be affected by this bug.
384
385If this is not the case, you will need to ensure that the CloudFormation [logical ids] of the API keys that are not
386being deleted remain unchanged.
387Make note of the logical ids of these API keys before removing any, and set it as part of the `addApiKey()` method:
388
389```ts
390declare const usageplan: apigateway.UsagePlan;
391declare const apiKey: apigateway.ApiKey;
392
393usageplan.addApiKey(apiKey, {
394 overrideLogicalId: '...',
395});
396```
397
398[feature flag]: https://docs.aws.amazon.com/cdk/latest/guide/featureflags.html
399[logical ids]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html
400
401### Rate Limited API Key
402
403In scenarios where you need to create a single api key and configure rate limiting for it, you can use `RateLimitedApiKey`.
404This construct lets you specify rate limiting properties which should be applied only to the api key being created.
405The API key created has the specified rate limits, such as quota and throttles, applied.
406
407The following example shows how to use a rate limited api key :
408
409```ts
410declare const api: apigateway.RestApi;
411
412const key = new apigateway.RateLimitedApiKey(this, 'rate-limited-api-key', {
413 customerId: 'hello-customer',
414 resources: [api],
415 quota: {
416 limit: 10000,
417 period: apigateway.Period.MONTH
418 }
419});
420```
421
422## Working with models
423
424When you work with Lambda integrations that are not Proxy integrations, you
425have to define your models and mappings for the request, response, and integration.
426
427```ts
428const hello = new lambda.Function(this, 'hello', {
429 runtime: lambda.Runtime.NODEJS_12_X,
430 handler: 'hello.handler',
431 code: lambda.Code.fromAsset('lambda')
432});
433
434const api = new apigateway.RestApi(this, 'hello-api', { });
435const resource = api.root.addResource('v1');
436```
437
438You can define more parameters on the integration to tune the behavior of API Gateway
439
440```ts
441declare const hello: lambda.Function;
442
443const integration = new apigateway.LambdaIntegration(hello, {
444 proxy: false,
445 requestParameters: {
446 // You can define mapping parameters from your method to your integration
447 // - Destination parameters (the key) are the integration parameters (used in mappings)
448 // - Source parameters (the value) are the source request parameters or expressions
449 // @see: https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html
450 'integration.request.querystring.who': 'method.request.querystring.who'
451 },
452 allowTestInvoke: true,
453 requestTemplates: {
454 // You can define a mapping that will build a payload for your integration, based
455 // on the integration parameters that you have specified
456 // Check: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
457 'application/json': JSON.stringify({ action: 'sayHello', pollId: "$util.escapeJavaScript($input.params('who'))" })
458 },
459 // This parameter defines the behavior of the engine is no suitable response template is found
460 passthroughBehavior: apigateway.PassthroughBehavior.NEVER,
461 integrationResponses: [
462 {
463 // Successful response from the Lambda function, no filter defined
464 // - the selectionPattern filter only tests the error message
465 // We will set the response status code to 200
466 statusCode: "200",
467 responseTemplates: {
468 // This template takes the "message" result from the Lambda function, and embeds it in a JSON response
469 // Check https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
470 'application/json': JSON.stringify({ state: 'ok', greeting: '$util.escapeJavaScript($input.body)' })
471 },
472 responseParameters: {
473 // We can map response parameters
474 // - Destination parameters (the key) are the response parameters (used in mappings)
475 // - Source parameters (the value) are the integration response parameters or expressions
476 'method.response.header.Content-Type': "'application/json'",
477 'method.response.header.Access-Control-Allow-Origin': "'*'",
478 'method.response.header.Access-Control-Allow-Credentials': "'true'"
479 }
480 },
481 {
482 // For errors, we check if the error message is not empty, get the error data
483 selectionPattern: '(\n|.)+',
484 // We will set the response status code to 200
485 statusCode: "400",
486 responseTemplates: {
487 'application/json': JSON.stringify({ state: 'error', message: "$util.escapeJavaScript($input.path('$.errorMessage'))" })
488 },
489 responseParameters: {
490 'method.response.header.Content-Type': "'application/json'",
491 'method.response.header.Access-Control-Allow-Origin': "'*'",
492 'method.response.header.Access-Control-Allow-Credentials': "'true'"
493 }
494 }
495 ]
496});
497
498```
499
500You can define models for your responses (and requests)
501
502```ts
503declare const api: apigateway.RestApi;
504
505// We define the JSON Schema for the transformed valid response
506const responseModel = api.addModel('ResponseModel', {
507 contentType: 'application/json',
508 modelName: 'ResponseModel',
509 schema: {
510 schema: apigateway.JsonSchemaVersion.DRAFT4,
511 title: 'pollResponse',
512 type: apigateway.JsonSchemaType.OBJECT,
513 properties: {
514 state: { type: apigateway.JsonSchemaType.STRING },
515 greeting: { type: apigateway.JsonSchemaType.STRING }
516 }
517 }
518});
519
520// We define the JSON Schema for the transformed error response
521const errorResponseModel = api.addModel('ErrorResponseModel', {
522 contentType: 'application/json',
523 modelName: 'ErrorResponseModel',
524 schema: {
525 schema: apigateway.JsonSchemaVersion.DRAFT4,
526 title: 'errorResponse',
527 type: apigateway.JsonSchemaType.OBJECT,
528 properties: {
529 state: { type: apigateway.JsonSchemaType.STRING },
530 message: { type: apigateway.JsonSchemaType.STRING }
531 }
532 }
533});
534
535```
536
537And reference all on your method definition.
538
539```ts
540declare const integration: apigateway.LambdaIntegration;
541declare const resource: apigateway.Resource;
542declare const responseModel: apigateway.Model;
543declare const errorResponseModel: apigateway.Model;
544
545resource.addMethod('GET', integration, {
546 // We can mark the parameters as required
547 requestParameters: {
548 'method.request.querystring.who': true
549 },
550 // we can set request validator options like below
551 requestValidatorOptions: {
552 requestValidatorName: 'test-validator',
553 validateRequestBody: true,
554 validateRequestParameters: false
555 },
556 methodResponses: [
557 {
558 // Successful response from the integration
559 statusCode: '200',
560 // Define what parameters are allowed or not
561 responseParameters: {
562 'method.response.header.Content-Type': true,
563 'method.response.header.Access-Control-Allow-Origin': true,
564 'method.response.header.Access-Control-Allow-Credentials': true
565 },
566 // Validate the schema on the response
567 responseModels: {
568 'application/json': responseModel
569 }
570 },
571 {
572 // Same thing for the error responses
573 statusCode: '400',
574 responseParameters: {
575 'method.response.header.Content-Type': true,
576 'method.response.header.Access-Control-Allow-Origin': true,
577 'method.response.header.Access-Control-Allow-Credentials': true
578 },
579 responseModels: {
580 'application/json': errorResponseModel
581 }
582 }
583 ]
584});
585```
586
587Specifying `requestValidatorOptions` automatically creates the RequestValidator construct with the given options.
588However, if you have your RequestValidator already initialized or imported, use the `requestValidator` option instead.
589
590## Default Integration and Method Options
591
592The `defaultIntegration` and `defaultMethodOptions` properties can be used to
593configure a default integration at any resource level. These options will be
594used when defining method under this resource (recursively) with undefined
595integration or options.
596
597> If not defined, the default integration is `MockIntegration`. See reference
598documentation for default method options.
599
600The following example defines the `booksBackend` integration as a default
601integration. This means that all API methods that do not explicitly define an
602integration will be routed to this AWS Lambda function.
603
604```ts
605declare const booksBackend: apigateway.LambdaIntegration;
606const api = new apigateway.RestApi(this, 'books', {
607 defaultIntegration: booksBackend
608});
609
610const books = api.root.addResource('books');
611books.addMethod('GET'); // integrated with `booksBackend`
612books.addMethod('POST'); // integrated with `booksBackend`
613
614const book = books.addResource('{book_id}');
615book.addMethod('GET'); // integrated with `booksBackend`
616```
617
618A Method can be configured with authorization scopes. Authorization scopes are
619used in conjunction with an [authorizer that uses Amazon Cognito user
620pools](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html#apigateway-enable-cognito-user-pool).
621Read more about authorization scopes
622[here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-method.html#cfn-apigateway-method-authorizationscopes).
623
624Authorization scopes for a Method can be configured using the `authorizationScopes` property as shown below -
625
626```ts
627declare const books: apigateway.Resource;
628
629books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
630 authorizationType: apigateway.AuthorizationType.COGNITO,
631 authorizationScopes: ['Scope1','Scope2']
632});
633```
634
635## Proxy Routes
636
637The `addProxy` method can be used to install a greedy `{proxy+}` resource
638on a path. By default, this also installs an `"ANY"` method:
639
640```ts
641declare const resource: apigateway.Resource;
642declare const handler: lambda.Function;
643const proxy = resource.addProxy({
644 defaultIntegration: new apigateway.LambdaIntegration(handler),
645
646 // "false" will require explicitly adding methods on the `proxy` resource
647 anyMethod: true // "true" is the default
648});
649```
650
651## Authorizers
652
653API Gateway [supports several different authorization types](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-to-api.html)
654that can be used for controlling access to your REST APIs.
655
656### IAM-based authorizer
657
658The following CDK code provides 'execute-api' permission to an IAM user, via IAM policies, for the 'GET' method on the `books` resource:
659
660```ts
661declare const books: apigateway.Resource;
662declare const iamUser: iam.User;
663
664const getBooks = books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
665 authorizationType: apigateway.AuthorizationType.IAM
666});
667
668iamUser.attachInlinePolicy(new iam.Policy(this, 'AllowBooks', {
669 statements: [
670 new iam.PolicyStatement({
671 actions: [ 'execute-api:Invoke' ],
672 effect: iam.Effect.ALLOW,
673 resources: [ getBooks.methodArn ]
674 })
675 ]
676}))
677```
678
679### Lambda-based token authorizer
680
681API Gateway also allows [lambda functions to be used as authorizers](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html).
682
683This module provides support for token-based Lambda authorizers. When a client makes a request to an API's methods configured with such
684an authorizer, API Gateway calls the Lambda authorizer, which takes the caller's identity as input and returns an IAM policy as output.
685A token-based Lambda authorizer (also called a token authorizer) receives the caller's identity in a bearer token, such as
686a JSON Web Token (JWT) or an OAuth token.
687
688API Gateway interacts with the authorizer Lambda function handler by passing input and expecting the output in a specific format.
689The event object that the handler is called with contains the `authorizationToken` and the `methodArn` from the request to the
690API Gateway endpoint. The handler is expected to return the `principalId` (i.e. the client identifier) and a `policyDocument` stating
691what the client is authorizer to perform.
692See [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html) for a detailed specification on
693inputs and outputs of the Lambda handler.
694
695The following code attaches a token-based Lambda authorizer to the 'GET' Method of the Book resource:
696
697```ts
698declare const authFn: lambda.Function;
699declare const books: apigateway.Resource;
700
701const auth = new apigateway.TokenAuthorizer(this, 'booksAuthorizer', {
702 handler: authFn
703});
704
705books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
706 authorizer: auth
707});
708```
709
710A full working example is shown below.
711
712[Full token authorizer example](test/authorizers/integ.token-authorizer.lit.ts).
713
714By default, the `TokenAuthorizer` looks for the authorization token in the request header with the key 'Authorization'. This can,
715however, be modified by changing the `identitySource` property.
716
717Authorizers can also be passed via the `defaultMethodOptions` property within the `RestApi` construct or the `Method` construct. Unless
718explicitly overridden, the specified defaults will be applied across all `Method`s across the `RestApi` or across all `Resource`s,
719depending on where the defaults were specified.
720
721### Lambda-based request authorizer
722
723This module provides support for request-based Lambda authorizers. When a client makes a request to an API's methods configured with such
724an authorizer, API Gateway calls the Lambda authorizer, which takes specified parts of the request, known as identity sources,
725as input and returns an IAM policy as output. A request-based Lambda authorizer (also called a request authorizer) receives
726the identity sources in a series of values pulled from the request, from the headers, stage variables, query strings, and the context.
727
728API Gateway interacts with the authorizer Lambda function handler by passing input and expecting the output in a specific format.
729The event object that the handler is called with contains the body of the request and the `methodArn` from the request to the
730API Gateway endpoint. The handler is expected to return the `principalId` (i.e. the client identifier) and a `policyDocument` stating
731what the client is authorizer to perform.
732See [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html) for a detailed specification on
733inputs and outputs of the Lambda handler.
734
735The following code attaches a request-based Lambda authorizer to the 'GET' Method of the Book resource:
736
737```ts
738declare const authFn: lambda.Function;
739declare const books: apigateway.Resource;
740
741const auth = new apigateway.RequestAuthorizer(this, 'booksAuthorizer', {
742 handler: authFn,
743 identitySources: [apigateway.IdentitySource.header('Authorization')]
744});
745
746books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
747 authorizer: auth
748});
749```
750
751A full working example is shown below.
752
753[Full request authorizer example](test/authorizers/integ.request-authorizer.lit.ts).
754
755By default, the `RequestAuthorizer` does not pass any kind of information from the request. This can,
756however, be modified by changing the `identitySource` property, and is required when specifying a value for caching.
757
758Authorizers can also be passed via the `defaultMethodOptions` property within the `RestApi` construct or the `Method` construct. Unless
759explicitly overridden, the specified defaults will be applied across all `Method`s across the `RestApi` or across all `Resource`s,
760depending on where the defaults were specified.
761
762### Cognito User Pools authorizer
763
764API Gateway also allows [Amazon Cognito user pools as authorizer](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html)
765
766The following snippet configures a Cognito user pool as an authorizer:
767
768```ts
769const userPool = new cognito.UserPool(this, 'UserPool');
770
771const auth = new apigateway.CognitoUserPoolsAuthorizer(this, 'booksAuthorizer', {
772 cognitoUserPools: [userPool]
773});
774
775declare const books: apigateway.Resource;
776books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
777 authorizer: auth,
778 authorizationType: apigateway.AuthorizationType.COGNITO,
779});
780```
781
782## Mutual TLS (mTLS)
783
784Mutual TLS can be configured to limit access to your API based by using client certificates instead of (or as an extension of) using authorization headers.
785
786```ts
787declare const acm: any;
788
789new apigateway.DomainName(this, 'domain-name', {
790 domainName: 'example.com',
791 certificate: acm.Certificate.fromCertificateArn(this, 'cert', 'arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d'),
792 mtls: {
793 bucket: new s3.Bucket(this, 'bucket'),
794 key: 'truststore.pem',
795 version: 'version',
796 },
797});
798```
799
800Instructions for configuring your trust store can be found [here](https://aws.amazon.com/blogs/compute/introducing-mutual-tls-authentication-for-amazon-api-gateway/).
801
802## Deployments
803
804By default, the `RestApi` construct will automatically create an API Gateway
805[Deployment] and a "prod" [Stage] which represent the API configuration you
806defined in your CDK app. This means that when you deploy your app, your API will
807be have open access from the internet via the stage URL.
808
809The URL of your API can be obtained from the attribute `restApi.url`, and is
810also exported as an `Output` from your stack, so it's printed when you `cdk
811deploy` your app:
812
813```console
814$ cdk deploy
815...
816books.booksapiEndpointE230E8D5 = https://6lyktd4lpk.execute-api.us-east-1.amazonaws.com/prod/
817```
818
819To disable this behavior, you can set `{ deploy: false }` when creating your
820API. This means that the API will not be deployed and a stage will not be
821created for it. You will need to manually define a `apigateway.Deployment` and
822`apigateway.Stage` resources.
823
824Use the `deployOptions` property to customize the deployment options of your
825API.
826
827The following example will configure API Gateway to emit logs and data traces to
828AWS CloudWatch for all API calls:
829
830> By default, an IAM role will be created and associated with API Gateway to
831allow it to write logs and metrics to AWS CloudWatch unless `cloudWatchRole` is
832set to `false`.
833
834```ts
835const api = new apigateway.RestApi(this, 'books', {
836 deployOptions: {
837 loggingLevel: apigateway.MethodLoggingLevel.INFO,
838 dataTraceEnabled: true
839 }
840})
841```
842
843### Deep dive: Invalidation of deployments
844
845API Gateway deployments are an immutable snapshot of the API. This means that we
846want to automatically create a new deployment resource every time the API model
847defined in our CDK app changes.
848
849In order to achieve that, the AWS CloudFormation logical ID of the
850`AWS::ApiGateway::Deployment` resource is dynamically calculated by hashing the
851API configuration (resources, methods). This means that when the configuration
852changes (i.e. a resource or method are added, configuration is changed), a new
853logical ID will be assigned to the deployment resource. This will cause
854CloudFormation to create a new deployment resource.
855
856By default, old deployments are _deleted_. You can set `retainDeployments: true`
857to allow users revert the stage to an old deployment manually.
858
859[Deployment]: https://docs.aws.amazon.com/apigateway/api-reference/resource/deployment/
860[Stage]: https://docs.aws.amazon.com/apigateway/api-reference/resource/stage/
861
862## Custom Domains
863
864To associate an API with a custom domain, use the `domainName` configuration when
865you define your API:
866
867```ts
868declare const acmCertificateForExampleCom: any;
869
870const api = new apigateway.RestApi(this, 'MyDomain', {
871 domainName: {
872 domainName: 'example.com',
873 certificate: acmCertificateForExampleCom,
874 },
875});
876```
877
878This will define a `DomainName` resource for you, along with a `BasePathMapping`
879from the root of the domain to the deployment stage of the API. This is a common
880set up.
881
882To route domain traffic to an API Gateway API, use Amazon Route 53 to create an
883alias record. An alias record is a Route 53 extension to DNS. It's similar to a
884CNAME record, but you can create an alias record both for the root domain, such
885as `example.com`, and for subdomains, such as `www.example.com`. (You can create
886CNAME records only for subdomains.)
887
888```ts
889import * as route53 from '@aws-cdk/aws-route53';
890import * as targets from '@aws-cdk/aws-route53-targets';
891
892declare const api: apigateway.RestApi;
893declare const hostedZoneForExampleCom: any;
894
895new route53.ARecord(this, 'CustomDomainAliasRecord', {
896 zone: hostedZoneForExampleCom,
897 target: route53.RecordTarget.fromAlias(new targets.ApiGateway(api))
898});
899```
900
901You can also define a `DomainName` resource directly in order to customize the default behavior:
902
903```ts
904declare const acmCertificateForExampleCom: any;
905
906new apigateway.DomainName(this, 'custom-domain', {
907 domainName: 'example.com',
908 certificate: acmCertificateForExampleCom,
909 endpointType: apigateway.EndpointType.EDGE, // default is REGIONAL
910 securityPolicy: apigateway.SecurityPolicy.TLS_1_2
911});
912```
913
914Once you have a domain, you can map base paths of the domain to APIs.
915The following example will map the URL <https://example.com/go-to-api1>
916to the `api1` API and <https://example.com/boom> to the `api2` API.
917
918```ts
919declare const domain: apigateway.DomainName;
920declare const api1: apigateway.RestApi;
921declare const api2: apigateway.RestApi;
922
923domain.addBasePathMapping(api1, { basePath: 'go-to-api1' });
924domain.addBasePathMapping(api2, { basePath: 'boom' });
925```
926
927You can specify the API `Stage` to which this base path URL will map to. By default, this will be the
928`deploymentStage` of the `RestApi`.
929
930```ts
931declare const domain: apigateway.DomainName;
932declare const restapi: apigateway.RestApi;
933
934const betaDeploy = new apigateway.Deployment(this, 'beta-deployment', {
935 api: restapi,
936});
937const betaStage = new apigateway.Stage(this, 'beta-stage', {
938 deployment: betaDeploy,
939});
940domain.addBasePathMapping(restapi, { basePath: 'api/beta', stage: betaStage });
941```
942
943If you don't specify `basePath`, all URLs under this domain will be mapped
944to the API, and you won't be able to map another API to the same domain:
945
946```ts
947declare const domain: apigateway.DomainName;
948declare const api: apigateway.RestApi;
949domain.addBasePathMapping(api);
950```
951
952This can also be achieved through the `mapping` configuration when defining the
953domain as demonstrated above.
954
955If you wish to setup this domain with an Amazon Route53 alias, use the `targets.ApiGatewayDomain`:
956
957```ts
958declare const hostedZoneForExampleCom: any;
959declare const domainName: apigateway.DomainName;
960
961import * as route53 from '@aws-cdk/aws-route53';
962import * as targets from '@aws-cdk/aws-route53-targets';
963
964new route53.ARecord(this, 'CustomDomainAliasRecord', {
965 zone: hostedZoneForExampleCom,
966 target: route53.RecordTarget.fromAlias(new targets.ApiGatewayDomain(domainName))
967});
968```
969
970## Access Logging
971
972Access logging creates logs every time an API method is accessed. Access logs can have information on
973who has accessed the API, how the caller accessed the API and what responses were generated.
974Access logs are configured on a Stage of the RestApi.
975Access logs can be expressed in a format of your choosing, and can contain any access details, with a
976minimum that it must include the 'requestId'. The list of variables that can be expressed in the access
977log can be found
978[here](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#context-variable-reference).
979Read more at [Setting Up CloudWatch API Logging in API
980Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html)
981
982```ts
983// production stage
984const prdLogGroup = new logs.LogGroup(this, "PrdLogs");
985const api = new apigateway.RestApi(this, 'books', {
986 deployOptions: {
987 accessLogDestination: new apigateway.LogGroupLogDestination(prdLogGroup),
988 accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields()
989 }
990})
991const deployment = new apigateway.Deployment(this, 'Deployment', {api});
992
993// development stage
994const devLogGroup = new logs.LogGroup(this, "DevLogs");
995new apigateway.Stage(this, 'dev', {
996 deployment,
997 accessLogDestination: new apigateway.LogGroupLogDestination(devLogGroup),
998 accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields({
999 caller: false,
1000 httpMethod: true,
1001 ip: true,
1002 protocol: true,
1003 requestTime: true,
1004 resourcePath: true,
1005 responseLength: true,
1006 status: true,
1007 user: true
1008 })
1009});
1010```
1011
1012The following code will generate the access log in the [CLF format](https://en.wikipedia.org/wiki/Common_Log_Format).
1013
1014```ts
1015const logGroup = new logs.LogGroup(this, "ApiGatewayAccessLogs");
1016const api = new apigateway.RestApi(this, 'books', {
1017 deployOptions: {
1018 accessLogDestination: new apigateway.LogGroupLogDestination(logGroup),
1019 accessLogFormat: apigateway.AccessLogFormat.clf(),
1020 }});
1021```
1022
1023You can also configure your own access log format by using the `AccessLogFormat.custom()` API.
1024`AccessLogField` provides commonly used fields. The following code configures access log to contain.
1025
1026```ts
1027const logGroup = new logs.LogGroup(this, "ApiGatewayAccessLogs");
1028new apigateway.RestApi(this, 'books', {
1029 deployOptions: {
1030 accessLogDestination: new apigateway.LogGroupLogDestination(logGroup),
1031 accessLogFormat: apigateway.AccessLogFormat.custom(
1032 `${apigateway.AccessLogField.contextRequestId()} ${apigateway.AccessLogField.contextErrorMessage()} ${apigateway.AccessLogField.contextErrorMessageString()}`
1033 )
1034 }
1035});
1036```
1037
1038You can use the `methodOptions` property to configure
1039[default method throttling](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-throttling.html#apigateway-api-level-throttling-in-usage-plan)
1040for a stage. The following snippet configures the a stage that accepts
1041100 requests per minute, allowing burst up to 200 requests per minute.
1042
1043```ts
1044const api = new apigateway.RestApi(this, 'books');
1045const deployment = new apigateway.Deployment(this, 'my-deployment', { api });
1046const stage = new apigateway.Stage(this, 'my-stage', {
1047 deployment,
1048 methodOptions: {
1049 '/*/*': { // This special path applies to all resource paths and all HTTP methods
1050 throttlingRateLimit: 100,
1051 throttlingBurstLimit: 200
1052 }
1053 }
1054});
1055```
1056
1057Configuring `methodOptions` on the `deployOptions` of `RestApi` will set the
1058throttling behaviors on the default stage that is automatically created.
1059
1060```ts
1061const api = new apigateway.RestApi(this, 'books', {
1062 deployOptions: {
1063 methodOptions: {
1064 '/*/*': { // This special path applies to all resource paths and all HTTP methods
1065 throttlingRateLimit: 100,
1066 throttlingBurstLimit: 1000
1067 }
1068 }
1069 }
1070});
1071```
1072
1073## Cross Origin Resource Sharing (CORS)
1074
1075[Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) is a mechanism
1076that uses additional HTTP headers to tell browsers to give a web application
1077running at one origin, access to selected resources from a different origin. A
1078web application executes a cross-origin HTTP request when it requests a resource
1079that has a different origin (domain, protocol, or port) from its own.
1080
1081You can add the CORS [preflight](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests) OPTIONS
1082HTTP method to any API resource via the `defaultCorsPreflightOptions` option or by calling the `addCorsPreflight` on a specific resource.
1083
1084The following example will enable CORS for all methods and all origins on all resources of the API:
1085
1086```ts
1087new apigateway.RestApi(this, 'api', {
1088 defaultCorsPreflightOptions: {
1089 allowOrigins: apigateway.Cors.ALL_ORIGINS,
1090 allowMethods: apigateway.Cors.ALL_METHODS // this is also the default
1091 }
1092})
1093```
1094
1095The following example will add an OPTIONS method to the `myResource` API resource, which
1096only allows GET and PUT HTTP requests from the origin <https://amazon.com.>
1097
1098```ts
1099declare const myResource: apigateway.Resource;
1100
1101myResource.addCorsPreflight({
1102 allowOrigins: [ 'https://amazon.com' ],
1103 allowMethods: [ 'GET', 'PUT' ]
1104});
1105```
1106
1107See the
1108[`CorsOptions`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apigateway.CorsOptions.html)
1109API reference for a detailed list of supported configuration options.
1110
1111You can specify defaults this at the resource level, in which case they will be applied to the entire resource sub-tree:
1112
1113```ts
1114declare const resource: apigateway.Resource;
1115
1116const subtree = resource.addResource('subtree', {
1117 defaultCorsPreflightOptions: {
1118 allowOrigins: [ 'https://amazon.com' ]
1119 }
1120});
1121```
1122
1123This means that all resources under `subtree` (inclusive) will have a preflight
1124OPTIONS added to them.
1125
1126See [#906](https://github.com/aws/aws-cdk/issues/906) for a list of CORS
1127features which are not yet supported.
1128
1129## Endpoint Configuration
1130
1131API gateway allows you to specify an
1132[API Endpoint Type](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-endpoint-types.html).
1133To define an endpoint type for the API gateway, use `endpointConfiguration` property:
1134
1135```ts
1136const api = new apigateway.RestApi(this, 'api', {
1137 endpointConfiguration: {
1138 types: [ apigateway.EndpointType.EDGE ]
1139 }
1140});
1141```
1142
1143You can also create an association between your Rest API and a VPC endpoint. By doing so,
1144API Gateway will generate a new
1145Route53 Alias DNS record which you can use to invoke your private APIs. More info can be found
1146[here](https://docs.aws.amazon.com/apigateway/latest/developerguide/associate-private-api-with-vpc-endpoint.html).
1147
1148Here is an example:
1149
1150```ts
1151declare const someEndpoint: ec2.IVpcEndpoint;
1152
1153const api = new apigateway.RestApi(this, 'api', {
1154 endpointConfiguration: {
1155 types: [ apigateway.EndpointType.PRIVATE ],
1156 vpcEndpoints: [ someEndpoint ]
1157 }
1158});
1159```
1160
1161By performing this association, we can invoke the API gateway using the following format:
1162
1163```plaintext
1164https://{rest-api-id}-{vpce-id}.execute-api.{region}.amazonaws.com/{stage}
1165```
1166
1167## Private Integrations
1168
1169A private integration makes it simple to expose HTTP/HTTPS resources behind an
1170Amazon VPC for access by clients outside of the VPC. The private integration uses
1171an API Gateway resource of `VpcLink` to encapsulate connections between API
1172Gateway and targeted VPC resources.
1173The `VpcLink` is then attached to the `Integration` of a specific API Gateway
1174Method. The following code sets up a private integration with a network load
1175balancer -
1176
1177```ts
1178import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2';
1179
1180const vpc = new ec2.Vpc(this, 'VPC');
1181const nlb = new elbv2.NetworkLoadBalancer(this, 'NLB', {
1182 vpc,
1183});
1184const link = new apigateway.VpcLink(this, 'link', {
1185 targets: [nlb],
1186});
1187
1188const integration = new apigateway.Integration({
1189 type: apigateway.IntegrationType.HTTP_PROXY,
1190 options: {
1191 connectionType: apigateway.ConnectionType.VPC_LINK,
1192 vpcLink: link,
1193 },
1194});
1195```
1196
1197The uri for the private integration, in the case of a VpcLink, will be set to the DNS name of
1198the VPC Link's NLB. If the VPC Link has multiple NLBs or the VPC Link is imported or the DNS
1199name cannot be determined for any other reason, the user is expected to specify the `uri`
1200property.
1201
1202Any existing `VpcLink` resource can be imported into the CDK app via the `VpcLink.fromVpcLinkId()`.
1203
1204```ts
1205const awesomeLink = apigateway.VpcLink.fromVpcLinkId(this, 'awesome-vpc-link', 'us-east-1_oiuR12Abd');
1206```
1207
1208## Gateway response
1209
1210If the Rest API fails to process an incoming request, it returns to the client an error response without forwarding the
1211request to the integration backend. API Gateway has a set of standard response messages that are sent to the client for
1212each type of error. These error responses can be configured on the Rest API. The list of Gateway responses that can be
1213configured can be found [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/supported-gateway-response-types.html).
1214Learn more about [Gateway
1215Responses](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-gatewayResponse-definition.html).
1216
1217The following code configures a Gateway Response when the response is 'access denied':
1218
1219```ts
1220const api = new apigateway.RestApi(this, 'books-api');
1221api.addGatewayResponse('test-response', {
1222 type: apigateway.ResponseType.ACCESS_DENIED,
1223 statusCode: '500',
1224 responseHeaders: {
1225 'Access-Control-Allow-Origin': "test.com",
1226 'test-key': 'test-value'
1227 },
1228 templates: {
1229 'application/json': '{ "message": $context.error.messageString, "statusCode": "488", "type": "$context.error.responseType" }'
1230 }
1231});
1232```
1233
1234## OpenAPI Definition
1235
1236CDK supports creating a REST API by importing an OpenAPI definition file. It currently supports OpenAPI v2.0 and OpenAPI
1237v3.0 definition files. Read more about [Configuring a REST API using
1238OpenAPI](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-import-api.html).
1239
1240The following code creates a REST API using an external OpenAPI definition JSON file -
1241
1242```ts
1243declare const integration: apigateway.Integration;
1244
1245const api = new apigateway.SpecRestApi(this, 'books-api', {
1246 apiDefinition: apigateway.ApiDefinition.fromAsset('path-to-file.json')
1247});
1248
1249const booksResource = api.root.addResource('books')
1250booksResource.addMethod('GET', integration);
1251```
1252
1253It is possible to use the `addResource()` API to define additional API Gateway Resources.
1254
1255**Note:** Deployment will fail if a Resource of the same name is already defined in the Open API specification.
1256
1257**Note:** Any default properties configured, such as `defaultIntegration`, `defaultMethodOptions`, etc. will only be
1258applied to Resources and Methods defined in the CDK, and not the ones defined in the spec. Use the [API Gateway
1259extensions to OpenAPI](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions.html)
1260to configure these.
1261
1262There are a number of limitations in using OpenAPI definitions in API Gateway. Read the [Amazon API Gateway important
1263notes for REST APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-known-issues.html#api-gateway-known-issues-rest-apis)
1264for more details.
1265
1266**Note:** When starting off with an OpenAPI definition using `SpecRestApi`, it is not possible to configure some
1267properties that can be configured directly in the OpenAPI specification file. This is to prevent people duplication
1268of these properties and potential confusion.
1269
1270### Endpoint configuration
1271
1272By default, `SpecRestApi` will create an edge optimized endpoint.
1273
1274This can be modified as shown below:
1275
1276```ts
1277declare const apiDefinition: apigateway.ApiDefinition;
1278
1279const api = new apigateway.SpecRestApi(this, 'ExampleRestApi', {
1280 apiDefinition,
1281 endpointTypes: [apigateway.EndpointType.PRIVATE]
1282});
1283```
1284
1285**Note:** For private endpoints you will still need to provide the
1286[`x-amazon-apigateway-policy`](https://docs.aws.amazon.com/apigateway/latest/developerguide/openapi-extensions-policy.html) and
1287[`x-amazon-apigateway-endpoint-configuration`](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-endpoint-configuration.html)
1288in your openApi file.
1289
1290## Metrics
1291
1292The API Gateway service sends metrics around the performance of Rest APIs to Amazon CloudWatch.
1293These metrics can be referred to using the metric APIs available on the `RestApi` construct.
1294The APIs with the `metric` prefix can be used to get reference to specific metrics for this API. For example,
1295the method below refers to the client side errors metric for this API.
1296
1297```ts
1298const api = new apigateway.RestApi(this, 'my-api');
1299const clientErrorMetric = api.metricClientError();
1300```
1301
1302## APIGateway v2
1303
1304APIGateway v2 APIs are now moved to its own package named `aws-apigatewayv2`. For backwards compatibility, existing
1305APIGateway v2 "CFN resources" (such as `CfnApi`) that were previously exported as part of this package, are still
1306exported from here and have been marked deprecated. However, updates to these CloudFormation resources, such as new
1307properties and new resource types will not be available.
1308
1309Move to using `aws-apigatewayv2` to get the latest APIs and updates.
1310
1311----
1312
1313This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.