Skip to content

Commit cb31547

Browse files
authored
feat(apigateway): step functions integration (#16827)
- Added StepFunctionsRestApi and StepFunctionsIntegration implementation closes #15081. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 37596e6 commit cb31547

17 files changed

+1800
-0
lines changed

packages/@aws-cdk/aws-apigateway/README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ running on AWS Lambda, or any web application.
2222
- [Defining APIs](#defining-apis)
2323
- [Breaking up Methods and Resources across Stacks](#breaking-up-methods-and-resources-across-stacks)
2424
- [AWS Lambda-backed APIs](#aws-lambda-backed-apis)
25+
- [AWS StepFunctions backed APIs](#aws-stepfunctions-backed-APIs)
2526
- [Integration Targets](#integration-targets)
2627
- [Usage Plan & API Keys](#usage-plan--api-keys)
2728
- [Working with models](#working-with-models)
@@ -106,6 +107,121 @@ item.addMethod('GET'); // GET /items/{item}
106107
item.addMethod('DELETE', new apigateway.HttpIntegration('http://amazon.com'));
107108
```
108109

110+
## AWS StepFunctions backed APIs
111+
112+
You can use Amazon API Gateway with AWS Step Functions as the backend integration, specifically Synchronous Express Workflows.
113+
114+
The `StepFunctionsRestApi` only supports integration with Synchronous Express state machine. The `StepFunctionsRestApi` construct makes this easy by setting up input, output and error mapping.
115+
116+
The 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+
118+
Invoking 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+
120+
If 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+
122+
The 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.
124+
In case of failures, the fields `error` and `cause` are returned as part of the response.
125+
Other metadata such as billing details, AWS account ID and resource ARNs are not returned in the API response.
126+
127+
By default, a `prod` stage is provisioned.
128+
129+
In 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` and `querystring` are included or not. By default, `headers` are excluded in all requests.
130+
131+
More 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+
133+
The following code defines a REST API that routes all requests to the specified AWS StepFunctions state machine:
134+
135+
```ts
136+
const stateMachineDefinition = new stepfunctions.Pass(this, 'PassState');
137+
138+
const stateMachine: stepfunctions.IStateMachine = new stepfunctions.StateMachine(this, 'StateMachine', {
139+
definition: stateMachineDefinition,
140+
stateMachineType: stepfunctions.StateMachineType.EXPRESS,
141+
});
142+
143+
new apigateway.StepFunctionsRestApi(this, 'StepFunctionsRestApi', {
144+
deploy: true,
145+
stateMachine: stateMachine,
146+
});
147+
```
148+
149+
When the REST API endpoint configuration above is invoked using POST, as follows -
150+
151+
```bash
152+
curl -X POST -d '{ "customerId": 1 }' https://example.com/
153+
```
154+
155+
AWS 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+
167+
When the endpoint is invoked at path '/users/5' using the HTTP GET method as below:
168+
169+
```bash
170+
curl -X GET https://example.com/users/5?foo=bar
171+
```
172+
173+
AWS 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+
187+
Additional information around the request such as the request context and headers can be included as part of the input
188+
forwarded to the state machine. The following example enables headers to be included in the input but not query string.
189+
190+
```ts fixture=stepfunctions
191+
new apigateway.StepFunctionsRestApi(this, 'StepFunctionsRestApi', {
192+
stateMachine: machine,
193+
headers: true,
194+
path: false,
195+
querystring: false,
196+
requestContext: {
197+
caller: true,
198+
user: true,
199+
},
200+
});
201+
```
202+
203+
In such a case, when the endpoint is invoked as below:
204+
205+
```bash
206+
curl -X GET https://example.com/
207+
```
208+
209+
AWS Step Functions will receive the following execution input:
210+
211+
```json
212+
{
213+
"headers": {
214+
"Accept": "...",
215+
"CloudFront-Forwarded-Proto": "...",
216+
},
217+
"requestContext": {
218+
"accountId": "...",
219+
"apiKey": "...",
220+
},
221+
"body": {}
222+
}
223+
```
224+
109225
### Breaking up Methods and Resources across Stacks
110226

111227
It is fairly common for REST APIs with a large number of Resources and Methods to hit the [CloudFormation

packages/@aws-cdk/aws-apigateway/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export * from './authorizers';
2121
export * from './access-log';
2222
export * from './api-definition';
2323
export * from './gateway-response';
24+
export * from './stepfunctions-api';
2425

2526
// AWS::ApiGateway CloudFormation Resources:
2627
export * from './apigateway.generated';

packages/@aws-cdk/aws-apigateway/lib/integrations/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ export * from './aws';
22
export * from './lambda';
33
export * from './http';
44
export * from './mock';
5+
export * from './stepfunctions';
6+
export * from './request-context';
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/**
2+
* Configure what must be included in the `requestContext`
3+
*
4+
* More details can be found at mapping templates documentation.
5+
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
6+
*/
7+
export interface RequestContext {
8+
/**
9+
* Represents the information of $context.identity.accountId
10+
*
11+
* Whether the AWS account of the API owner should be included in the request context
12+
* @default false
13+
*/
14+
readonly accountId?: boolean;
15+
16+
/**
17+
* Represents the information of $context.apiId
18+
*
19+
* Whether the identifier API Gateway assigns to your API should be included in the request context.
20+
* @default false
21+
*/
22+
readonly apiId?: boolean;
23+
24+
/**
25+
* Represents the information of $context.identity.apiKey
26+
*
27+
* Whether the API key associated with the request should be included in request context.
28+
* @default false
29+
*/
30+
readonly apiKey?: boolean;
31+
32+
/**
33+
* Represents the information of $context.authorizer.principalId
34+
*
35+
* Whether the principal user identifier associated with the token sent by the client and returned
36+
* from an API Gateway Lambda authorizer should be included in the request context.
37+
* @default false
38+
*/
39+
readonly authorizerPrincipalId?: boolean;
40+
41+
/**
42+
* Represents the information of $context.identity.caller
43+
*
44+
* Whether the principal identifier of the caller that signed the request should be included in the request context.
45+
* Supported for resources that use IAM authorization.
46+
* @default false
47+
*/
48+
readonly caller?: boolean;
49+
50+
/**
51+
* Represents the information of $context.identity.cognitoAuthenticationProvider
52+
*
53+
* Whether the list of the Amazon Cognito authentication providers used by the caller making the request should be included in the request context.
54+
* Available only if the request was signed with Amazon Cognito credentials.
55+
* @default false
56+
*/
57+
readonly cognitoAuthenticationProvider?: boolean;
58+
59+
/**
60+
* Represents the information of $context.identity.cognitoAuthenticationType
61+
*
62+
* Whether the Amazon Cognito authentication type of the caller making the request should be included in the request context.
63+
* Available only if the request was signed with Amazon Cognito credentials.
64+
* Possible values include authenticated for authenticated identities and unauthenticated for unauthenticated identities.
65+
* @default false
66+
*/
67+
readonly cognitoAuthenticationType?: boolean;
68+
69+
/**
70+
* Represents the information of $context.identity.cognitoIdentityId
71+
*
72+
* Whether the Amazon Cognito identity ID of the caller making the request should be included in the request context.
73+
* Available only if the request was signed with Amazon Cognito credentials.
74+
* @default false
75+
*/
76+
readonly cognitoIdentityId?: boolean;
77+
78+
/**
79+
* Represents the information of $context.identity.cognitoIdentityPoolId
80+
*
81+
* Whether the Amazon Cognito identity pool ID of the caller making the request should be included in the request context.
82+
* Available only if the request was signed with Amazon Cognito credentials.
83+
* @default false
84+
*/
85+
readonly cognitoIdentityPoolId?: boolean;
86+
87+
/**
88+
* Represents the information of $context.httpMethod
89+
*
90+
* Whether the HTTP method used should be included in the request context.
91+
* Valid values include: DELETE, GET, HEAD, OPTIONS, PATCH, POST, and PUT.
92+
* @default false
93+
*/
94+
readonly httpMethod?: boolean;
95+
96+
/**
97+
* Represents the information of $context.stage
98+
*
99+
* Whether the deployment stage of the API request should be included in the request context.
100+
* @default false
101+
*/
102+
readonly stage?: boolean;
103+
104+
/**
105+
* Represents the information of $context.identity.sourceIp
106+
*
107+
* Whether the source IP address of the immediate TCP connection making the request
108+
* to API Gateway endpoint should be included in the request context.
109+
* @default false
110+
*/
111+
readonly sourceIp?: boolean;
112+
113+
/**
114+
* Represents the information of $context.identity.user
115+
*
116+
* Whether the principal identifier of the user that will be authorized should be included in the request context.
117+
* Supported for resources that use IAM authorization.
118+
* @default false
119+
*/
120+
readonly user?: boolean;
121+
122+
/**
123+
* Represents the information of $context.identity.userAgent
124+
*
125+
* Whether the User-Agent header of the API caller should be included in the request context.
126+
* @default false
127+
*/
128+
readonly userAgent?: boolean;
129+
130+
/**
131+
* Represents the information of $context.identity.userArn
132+
*
133+
* Whether the Amazon Resource Name (ARN) of the effective user identified after authentication should be included in the request context.
134+
* @default false
135+
*/
136+
readonly userArn?: boolean;
137+
138+
/**
139+
* Represents the information of $context.requestId
140+
*
141+
* Whether the ID for the request should be included in the request context.
142+
* @default false
143+
*/
144+
readonly requestId?: boolean;
145+
146+
/**
147+
* Represents the information of $context.resourceId
148+
*
149+
* Whether the identifier that API Gateway assigns to your resource should be included in the request context.
150+
* @default false
151+
*/
152+
readonly resourceId?: boolean;
153+
154+
/**
155+
* Represents the information of $context.resourcePath
156+
*
157+
* Whether the path to the resource should be included in the request context.
158+
* @default false
159+
*/
160+
readonly resourcePath?: boolean;
161+
}

0 commit comments

Comments
 (0)