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): http api #6432

Merged
merged 52 commits into from
May 4, 2020
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
d310726
(feat)apigatewayv2: initial L2 support
pahud Feb 25, 2020
bef371a
Merge branch 'master' into apigatewayv2-L2
pahud Feb 25, 2020
2ba95d8
add the expected.json for integ test
pahud Feb 25, 2020
9f08ed4
fix package.json
pahud Feb 25, 2020
075e564
merge from master
pahud Mar 13, 2020
febd6a3
udpate README
pahud Mar 13, 2020
33dead4
update README
pahud Mar 13, 2020
02f96c2
update README
pahud Mar 13, 2020
46d3be4
remove comments and minor fix
pahud Mar 13, 2020
7265479
fix package.json
pahud Mar 13, 2020
35b8ddf
add integration and tests
pahud Mar 14, 2020
66c5022
update README
pahud Mar 14, 2020
87fbe4b
minor fix
pahud Mar 14, 2020
d26ad33
support HttpApi with no integration and no route
pahud Mar 14, 2020
4b278c0
update tests
pahud Mar 14, 2020
bef8974
remove unused type
pahud Mar 14, 2020
068b476
update integ test
pahud Mar 14, 2020
6f8f64d
support addLambdaRoute and addHttpRoute from HttpApi
pahud Mar 15, 2020
9d986d5
update README sample
pahud Mar 16, 2020
d338c41
Merge branch 'master' into apigatewayv2-L2
pahud Mar 16, 2020
32b6a31
Merge branch 'master' into apigatewayv2-L2
pahud Mar 18, 2020
b200c9f
Update packages/@aws-cdk/aws-apigatewayv2/README.md
pahud Mar 18, 2020
0bea7fc
Update packages/@aws-cdk/aws-apigatewayv2/README.md
pahud Mar 18, 2020
822cfe8
Update packages/@aws-cdk/aws-apigatewayv2/README.md
pahud Mar 18, 2020
c20a448
minor fix
pahud Mar 18, 2020
b6415e3
Merge branch 'master' into apigatewayv2-L2
pahud Mar 18, 2020
1965f59
update package.json
pahud Mar 18, 2020
6547860
update integ
pahud Mar 18, 2020
0989585
support api.addRootRoute()
pahud Mar 23, 2020
330b4af
Merge branch 'master' of https://github.com/aws/aws-cdk into apigatew…
pahud Mar 26, 2020
90204bb
support addRoutes() fro `HttpApi` and `Route` resources.
pahud Mar 26, 2020
818af1d
Merge branch 'master' into apigatewayv2-L2
Apr 27, 2020
3568779
trying to move this forward
Apr 27, 2020
7b64fd0
working basic routes and lambda integration
Apr 28, 2020
bb8857f
Working stage
Apr 28, 2020
5f44349
default integration
Apr 28, 2020
9e4deb8
docs updated & tweaks
Apr 29, 2020
35d6341
the massive restructure
Apr 29, 2020
cce22c1
Added IHttpRoute and fixed up HttpProxyIntegration
Apr 29, 2020
edba63c
http proxy now works
Apr 29, 2020
0b404dc
move stage name back to string
Apr 29, 2020
d9cd335
unit and integ tests
Apr 29, 2020
a5e2b20
addRoutes()
Apr 30, 2020
48aa1af
tests for integrations
Apr 30, 2020
ea8bea9
Merge pull request #1 from pahud/nija-at/apigwv2-pattern-setup
pahud Apr 30, 2020
c18a7d0
update README
pahud May 4, 2020
113053d
Merge branch 'master' into apigatewayv2-L2
pahud May 4, 2020
8ded78b
Update README.md
pahud May 4, 2020
df21f0f
Update package.json
pahud May 4, 2020
b808736
language and structural adjustments to the README
May 4, 2020
7cc71e0
adjust http integration
May 4, 2020
64606f3
Merge branch 'master' into apigatewayv2-L2
mergify[bot] May 4, 2020
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
96 changes: 95 additions & 1 deletion packages/@aws-cdk/aws-apigatewayv2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,100 @@

This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.


## Introduction

Amazon API Gateway is an AWS service for creating, publishing, maintaining, monitoring, and securing REST, HTTP, and WebSocket APIs at any scale. API developers can create APIs that access AWS or other web services, as well as data stored in the AWS Cloud. As an API Gateway API developer, you can create APIs for use in your own client applications. Or you can make your APIs available to third-party app developers. For more infomation, read the [Amazon API Gateway Developer Guide](https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html).
pahud marked this conversation as resolved.
Show resolved Hide resolved

pahud marked this conversation as resolved.
Show resolved Hide resolved

## API

This construct library at this moment implements API resources from [AWS::ApiGatewayV2::Api](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-api.html), which supports both `WebSocket APIs` and `HTTP APIs`.
pahud marked this conversation as resolved.
Show resolved Hide resolved

For more information about WebSocket APIs, see [About WebSocket APIs in API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-overview.html) in the _API Gateway Developer Guide_. For more information about HTTP APIs, see [HTTP APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html) in the _API Gateway Developer Guide_.
pahud marked this conversation as resolved.
Show resolved Hide resolved

To create [REST APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html), use `@aws-cdk/aws-apigateway` instead.


### HTTP API

`CfnApi` is the L1 construct to create either `WebSocket APIs` or `HTTP APIs`. At this moment, `HTTP APIs` supports both `Lambda Proxy Integration` and `HTTP Proxy Integration`. See [Working with AWS Lambda Proxy Integrations for HTTP APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html) and [Working with HTTP Proxy Integrations for HTTP APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-http.html) for more information.
pahud marked this conversation as resolved.
Show resolved Hide resolved


To create `HTTP APIs` with `Lambda Proxy Integration`, simply use `LambdaProxyApi`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Drop backquotes for HTTP APIs and Lambda Proxy Integration.



```ts
// Create a HTTP API with Lambda Proxy Integration as its $default route
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Create a HTTP API with Lambda Proxy Integration as its $default route
const handler = new lambda.Function(stack, 'ProxyHandler', { ... });
// Create a HTTP API with Lambda Proxy Integration as its $default route

Copy link
Contributor

Choose a reason for hiding this comment

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

This has not been addressed.

const api = new apigatewayv2.LambdaProxyApi(stack, 'LambdaProxyApi', {
handler
});
```

To create `HTTP APIs` with `HTTP Proxy Integration`, use `HttpProxyApi` instead.

```ts
// Create a HTTP API with HTTP Proxy Integration
new apigatewayv2.HttpProxyApi(stack, 'HttpProxyApi', {
url: 'https://aws.amazon.com'
});
```

pahud marked this conversation as resolved.
Show resolved Hide resolved

### WebSocket API

The WebSocket API is not implemented yet in this L2 construct library, however, as `Api` class is provided, it's still possible to create the Websocket APIs with the `Api` class.
Copy link
Contributor

Choose a reason for hiding this comment

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

Drop.



## Route

`Routes` direct incoming API requests to backend resources. `Routes` consist of two parts: an HTTP method and a resource path—for example, `GET /pets`. You can define specific HTTP methods for your route, or use the `ANY` method to match all methods that you haven't defined for a resource. You can create a `$default route` that acts as a catch-all for requests that don’t match any other routes. See [Working with Routes for HTTP APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-routes.html).
Copy link
Contributor

Choose a reason for hiding this comment

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

Drop backquote for 'Routes' and 'default route'. Use backquotes only when referring to something that's programmatic - either a classname, method name, property name, a tiny piece of code (such as GET /pets, as you've done)


When you create HTTP APIs with either `Lambda Proxy Integration` or `HTTP Proxy Integration`, the `$default route` will be created as well.
Copy link
Contributor

Choose a reason for hiding this comment

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

Drop this statement. It's a detail of the implementation and does not seem relevant here.


To create a specific route for an existing `Api` resource, specify the `httpPath` and an optional `httpMethod` property.

```ts
import apigatewayv2 = require('@aws-cdk/aws-apigatewayv2');
// create a specific 'GET /some/very/deep/route/path' route with Lambda proxy integration for an existing HTTP API
const someDeepLambdaRoute = new apigatewayv2.LambdaRoute(stack, 'SomeLambdaRoute', {
api,
handler,
Copy link
Contributor

Choose a reason for hiding this comment

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

Add two lines one declaring the HTTP API and the other declaring the lambda function (as shown in a previous comment)

httpPath: '/some/very/deep/route/path',
// optional
httpMethod: HttpMethod.GET
});
```

### `addLambdaRoute` and `addHttpRoute`
pahud marked this conversation as resolved.
Show resolved Hide resolved

To extend the routes from an existing HTTP API, use `addLambdaRoute` for Lambda proxy integration or `addHttpRoute` for HTTP Proxy Intgegration.
pahud marked this conversation as resolved.
Show resolved Hide resolved

Consider the providewd example above

```ts
// create a specific 'GET /some/very/deep/route/path' route with Lambda proxy integration for an existing HTTP API
const someDeepLambdaRoute = new apigatewayv2.LambdaRoute(stack, 'SomeLambdaRoute', {
api,
handler,
httpPath: '/some/very/deep/route/path',
httpMethod: HttpMethod.GET
});

someDeepLambdaRoute
// HTTP ANY /some/very/deep/route/path/bar
.addLambdaRoute('bar', 'SomeDeepPathBar', {
target: handler,
method: apigatewayv2.HttpMethod.GET
})
// HTTP ANY /some/very/deep/route/path/bar/checkip
.addHttpRoute('checkip', 'SomeDeepPathBarCheckIp', {
targetUrl: 'https://checkip.amazonaws.com',
method: apigatewayv2.HttpMethod.ANY
});

// print the full URL in the Outputs
new cdk.CfnOutput(stack, 'SomeDeepLambdaRouteURL', {
value: someDeepLambdaRoute.fullUrl
});
pahud marked this conversation as resolved.
Show resolved Hide resolved
```

239 changes: 239 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/lib/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
import * as lambda from '@aws-cdk/aws-lambda';
import * as cdk from '@aws-cdk/core';
import * as apigatewayv2 from '../lib';
import { CfnApiProps } from './apigatewayv2.generated';

/**
* the HTTP API interface
*/
export interface IApi extends cdk.IResource {
pahud marked this conversation as resolved.
Show resolved Hide resolved
/**
* The ID of this API Gateway HTTP Api.
* @attribute
*/
readonly apiId: string;
}
/**
* the ApiBase interface
*/
export interface IApiBase extends IApi {
/**
* http url of this api
*/
readonly url: string
}

/**
* HttpProxyApi interface
*/
export interface IHttpProxyApi extends IApi {}
/**
* LambdaProxyApi interface
*/
export interface ILambdaProxyApi extends IApi { }

abstract class ApiBase extends cdk.Resource implements IApi {
/**
* API ID
*/
public abstract readonly apiId: string;
/**
* API URL
*/
public abstract readonly url: string;
}
pahud marked this conversation as resolved.
Show resolved Hide resolved

/**
* API properties
*/
export interface ApiProps extends cdk.StackProps {
/**
* API Name
* @default - the logic ID of the API
*/
readonly apiName?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

this is mandatory.

Copy link
Contributor Author

@pahud pahud Mar 18, 2020

Choose a reason for hiding this comment

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

If apiName is a mandatory property of HttpApiProps then when we new HttpApi() we always need to specify an apiName for it. Is it correct?

I noticed the restApiName is optional. Did I miss something?

/**
* A name for the API Gateway RestApi resource.
*
* @default - ID of the RestApi construct.
*/
readonly restApiName?: string;

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry I wasn't clear.

The Name parameter in ApiGatewayv2::Api is mandatory (unless an OpenAPI definition is provided).

What is it going to be in the case that a user does not specify it? The CDK has to set some value here, correct? The @default annotation says the ID of the HttpApi construct, but that isn't available at the time of construction of CfnApi.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, this should be named httpApiName.

/**
* API protocol
* @default HTTP
*/
readonly protocol?: ApiProtocol;
/**
* the default integration target of this API
*/
readonly target: string;

}

/**
* API protocols
*/
export enum ApiProtocol {
/**
* HTTP protocol
*/
HTTP = 'HTTP',
/**
* Websocket protocol
*/
WEBSOCKET = 'WEBSOCKET'
}

/**
* Api Resource Class
*/
export class Api extends ApiBase implements IApi {
/**
* import from ApiId
*/
public static fromApiId(scope: cdk.Construct, id: string, apiId: string): IApi {
class Import extends cdk.Resource implements IApi {
public readonly apiId = apiId;
}

return new Import(scope, id);
}
/**
* the API identifer
*/
public readonly apiId: string;
/**
* AWS partition either `aws` or `aws-cn`
*/
public readonly partition: string;
/**
* AWS region of this stack
*/
public readonly region: string;
/**
* AWS account of this stack
*/
public readonly account: string;
/**
* AWS domain name either `amazonaws.com` or `amazonaws.com.cn`
*/
public readonly awsdn: string;
pahud marked this conversation as resolved.
Show resolved Hide resolved
/**
* the full URL of this API
*/
public readonly url: string;

constructor(scope: cdk.Construct, id: string, props?: ApiProps) {
super(scope, id, {
physicalName: props?.apiName || id,
});

this.region = cdk.Stack.of(this).region;
this.partition = this.region.startsWith('cn-') ? 'aws-cn' : 'aws';
this.account = cdk.Stack.of(this).account;
this.awsdn = this.partition === 'aws-cn' ? 'amazonaws.com.cn' : 'amazonaws.com';

const apiProps: CfnApiProps = {
name: this.physicalName,
protocolType: props?.protocol ?? ApiProtocol.HTTP,
target: props?.target
};
const api = new apigatewayv2.CfnApi(this, 'Resource', apiProps );
this.apiId = api.ref;
this.url = `https://${this.apiId}.execute-api.${this.region}.${this.awsdn}`;
}

}

/**
* LambdaProxyApi properties interface
*/
export interface LambdaProxyApiProps {
/**
* API name
* @default - the logic ID of the API
*/
readonly apiName?: string,
/**
* Lambda handler function
*/
readonly handler: lambda.IFunction
}

/**
* HttpProxyApi properties interface
*/
export interface HttpProxyApiProps {
/**
* API Name
* @default - the logic ID of the API
*/
readonly apiName?: string,
/**
* API URL
*/
readonly url: string
}

/**
* API with Lambda Proxy integration as the default route
*/
export class LambdaProxyApi extends Api implements ILambdaProxyApi {
/**
* import from api id
*/
public static fromLambdaProxyApiId(scope: cdk.Construct, id: string, lambdaProxyApiId: string): ILambdaProxyApi {
class Import extends cdk.Resource implements ILambdaProxyApi {
public readonly apiId = lambdaProxyApiId;
}
return new Import(scope, id);
}
/**
* the root route of the API
*/
public root?: apigatewayv2.IRouteBase;
constructor(scope: cdk.Construct, id: string, props: LambdaProxyApiProps) {
super(scope, id, {
target: props.handler.functionArn
});

new lambda.CfnPermission(this, 'Permission', {
action: 'lambda:InvokeFunction',
principal: 'apigateway.amazonaws.com',
functionName: props.handler.functionName,
sourceArn: `arn:${this.partition}:execute-api:${this.region}:${this.account}:${this.apiId}/*/*`,
});

// this.root = new RootRoute(this, 'RootRoute', this, {
// target: props.handler.functionArn,
// });

new cdk.CfnOutput(this, 'LambdaProxyApiUrl', {
value: this.url
});
}
}

/**
* API with HTTP Proxy integration as the default route
*/
export class HttpProxyApi extends Api implements IHttpProxyApi {
/**
* import from api id
*/
public static fromHttpProxyApiId(scope: cdk.Construct, id: string, httpProxyApiId: string): IHttpProxyApi {
class Import extends cdk.Resource implements IHttpProxyApi {
public readonly apiId = httpProxyApiId;
}
return new Import(scope, id);
}

/**
* the root route of the API
*/
public root?: apigatewayv2.IRouteBase;
constructor(scope: cdk.Construct, id: string, props: HttpProxyApiProps) {
super(scope, id, {
target: props.url,
apiName: props.apiName ?? id
});

new cdk.CfnOutput(this, 'HttpProxyApiUrl', {
value: this.url
});
}
}
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
// AWS::APIGatewayv2 CloudFormation Resources:
export * from './apigatewayv2.generated';
export * from './api';
export * from './route';
Loading