Skip to content

Commit

Permalink
feat(pipes-targets): add API Gateway (#31954)
Browse files Browse the repository at this point in the history
Add API Gateway REST API as a Pipes target.

Original PR with community review from @nmussy: #30772
  • Loading branch information
msambol authored Nov 26, 2024
1 parent c789063 commit c77536f
Show file tree
Hide file tree
Showing 17 changed files with 35,067 additions and 1 deletion.
46 changes: 46 additions & 0 deletions packages/@aws-cdk/aws-pipes-targets-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ For more details see the [service documentation](https://docs.aws.amazon.com/eve
Pipe targets are the end point of an EventBridge Pipe. The following targets are supported:

* `targets.ApiDestinationTarget`: [Send event source to an EventBridge API destination](#amazon-eventbridge-api-destination)
* `targets.ApiGatewayTarget`: [Send event source to an API Gateway REST API](#amazon-api-gateway-rest-api)
* `targets.CloudWatchLogsTarget`: [Send event source to a CloudWatch Logs log group](#amazon-cloudwatch-logs-log-group)
* `targets.EventBridgeTarget`: [Send event source to an EventBridge event bus](#amazon-eventbridge-event-bus)
* `targets.KinesisTarget`: [Send event source to a Kinesis data stream](#amazon-kinesis-data-stream)
Expand Down Expand Up @@ -67,6 +68,51 @@ const pipe = new pipes.Pipe(this, 'Pipe', {
});
```

### Amazon API Gateway Rest API

A REST API can be used as a target for a pipe.
The REST API will receive the (enriched/filtered) source payload.

```ts
declare const sourceQueue: sqs.Queue;

const fn = new lambda.Function( this, 'MyFunc', {
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_LATEST,
code: lambda.Code.fromInline( 'exports.handler = e => {}' ),
});

const restApi = new api.LambdaRestApi( this, 'MyRestAPI', { handler: fn } );
const apiTarget = new targets.ApiGatewayTarget(restApi);

const pipe = new pipes.Pipe(this, 'Pipe', {
source: new SqsSource(sourceQueue),
target: apiTarget,
});
```

The input to the target REST API can be transformed:

```ts
declare const sourceQueue: sqs.Queue;

const fn = new lambda.Function( this, 'MyFunc', {
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_LATEST,
code: lambda.Code.fromInline( 'exports.handler = e => {}' ),
});

const restApi = new api.LambdaRestApi( this, 'MyRestAPI', { handler: fn } );
const apiTarget = new targets.ApiGatewayTarget(restApi, {
inputTransformation: pipes.InputTransformation.fromObject({ body: "👀" }),
});

const pipe = new pipes.Pipe(this, 'Pipe', {
source: new SqsSource(sourceQueue),
target: apiTarget,
});
```

### Amazon CloudWatch Logs Log Group

A CloudWatch Logs log group can be used as a target for a pipe.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export interface ApiDestinationTargetParameters {
}

/**
* A EventBridge Pipes target that sends messages to an EventBridge API destination.
* An EventBridge Pipes target that sends messages to an EventBridge API destination.
*/
export class ApiDestinationTarget implements ITarget {
private destination: IApiDestination;
Expand Down
110 changes: 110 additions & 0 deletions packages/@aws-cdk/aws-pipes-targets-alpha/lib/api-gateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { IInputTransformation, IPipe, ITarget, TargetConfig } from '@aws-cdk/aws-pipes-alpha';
import { IRestApi } from 'aws-cdk-lib/aws-apigateway';
import { IRole, PolicyStatement } from 'aws-cdk-lib/aws-iam';

/**
* API Gateway REST API target properties.
*/
export interface ApiGatewayTargetParameters {
/**
* The input transformation to apply to the message before sending it to the target.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargetparameters.html#cfn-pipes-pipe-pipetargetparameters-inputtemplate
* @default - none
*/
readonly inputTransformation?: IInputTransformation;

/**
* The method for API Gateway resource.
*
* @default '*' - ANY
*/
readonly method?: string;

/**
* The path for the API Gateway resource.
*
* @default '/'
*/
readonly path?: string;

/**
* The deployment stage for the API Gateway resource.
*
* @default - the value of `deploymentStage.stageName` of target API Gateway resource.
*/
readonly stage?: string;

/**
* The headers to send as part of the request invoking the API Gateway REST API.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargethttpparameters.html#cfn-pipes-pipe-pipetargethttpparameters-headerparameters
* @default - none
*/
readonly headerParameters?: Record<string, string>;

/**
* The path parameter values used to populate the API Gateway REST API path wildcards ("*").
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargethttpparameters.html#cfn-pipes-pipe-pipetargethttpparameters-pathparametervalues
* @default - none
*/
readonly pathParameterValues?: string[];

/**
* The query string keys/values that need to be sent as part of request invoking the API Gateway REST API.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargethttpparameters.html#cfn-pipes-pipe-pipetargethttpparameters-querystringparameters
* @default - none
*/
readonly queryStringParameters?: Record<string, string>;
}

/**
* An EventBridge Pipes target that sends messages to an EventBridge API destination.
*/
export class ApiGatewayTarget implements ITarget {
private restApi: IRestApi;
private restApiParameters?: ApiGatewayTargetParameters;
private restApiArn: string;
public readonly targetArn;

constructor(restApi: IRestApi, parameters?: ApiGatewayTargetParameters) {
this.restApi = restApi;
this.restApiParameters = parameters;

if (this.restApiParameters?.stage === undefined && this.restApi.deploymentStage === undefined) {
throw Error('The REST API must have a deployed stage.');
}

this.restApiArn = this.restApi.arnForExecuteApi(
this.restApiParameters?.method,
this.restApiParameters?.path || '/',
this.restApiParameters?.stage || this.restApi.deploymentStage.stageName,
);

this.targetArn = this.restApiArn;
}

grantPush(grantee: IRole): void {
grantee.addToPrincipalPolicy(new PolicyStatement({
resources: [this.restApiArn],
actions: ['execute-api:Invoke'],
}));
}

bind(pipe: IPipe): TargetConfig {
if (!this.restApiParameters) {
return {
targetParameters: {},
};
}

return {
targetParameters: {
inputTemplate: this.restApiParameters.inputTransformation?.bind(pipe).inputTemplate,
httpParameters: this.restApiParameters,
},
};
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-pipes-targets-alpha/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './api-destination';
export * from './api-gateway';
export * from './cloudwatch-logs';
export * from './event-bridge';
export * from './kinesis';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Fixture with packages imported, but nothing else
import * as cdk from 'aws-cdk-lib';
import * as api from 'aws-cdk-lib/aws-apigateway';
import * as events from 'aws-cdk-lib/aws-events';
import * as kinesis from 'aws-cdk-lib/aws-kinesis';
import * as logs from 'aws-cdk-lib/aws-logs';
Expand Down
Loading

0 comments on commit c77536f

Please sign in to comment.