import { Construct, IConstruct } from 'constructs';
import * as cdk from 'aws-cdk-lib/core';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
export interface MyStackProps extends cdk.StackProps {
stageName: string;
prefix: string;
retainData: boolean;
}
export class CdkApiSqsStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: MyStackProps) {
super(scope, id, props);
// Create an SQS queue
const queue = new sqs.Queue(this, 'BooksQueue', {
visibilityTimeout: cdk.Duration.seconds(300),
queueName: `${props.prefix}-books-queue-${props.stageName}`,
});
// Create a DynamoDB table
const carsTable = new dynamodb.Table(this, 'CarsTable', {
tableName: `${props.prefix}-cars-${props.stageName}`,
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
partitionKey: { name: 'carId', type: dynamodb.AttributeType.STRING },
removalPolicy: props.retainData ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY, // NOT recommended for production code
});
// Create a REST API
const api = new apigateway.RestApi(this, 'Api', {
restApiName: `${props.prefix}-api-${props.stageName}`,
deployOptions: {
stageName: props.stageName,
},
retainDeployments: false,
});
// Define the /books resource
const books = api.root.addResource('books');
// Add a POST method to the /books resource
books.addMethod('POST', new apigateway.AwsIntegration({
service: 'sqs',
path: `${cdk.Aws.ACCOUNT_ID}/${queue.queueName}`,
integrationHttpMethod: 'POST',
options: {
credentialsRole: new iam.Role(this, 'ApiGatewaySqsRole', {
assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSQSFullAccess')
]
}),
requestParameters: {
'integration.request.header.Content-Type': "'application/x-www-form-urlencoded'"
},
requestTemplates: {
'application/json': `Action=SendMessage&MessageBody=$util.urlEncode($input.body)`
},
integrationResponses: [
{
statusCode: '200',
responseTemplates: {
'application/json': `{"status": "message queued"}`
}
},
{
statusCode: '500',
responseTemplates: {
'application/json': `{"status": "error"}`
}
}
]
}
}), {
methodResponses: [
{
statusCode: '200'
},
{
statusCode: '500'
}
]
});
// Grant API Gateway permissions to send messages to the SQS queue
queue.grantSendMessages(new iam.ServicePrincipal('apigateway.amazonaws.com'));
// Define the /cars resource
const cars = api.root.addResource('cars');
const carSchema = {
type: 'object',
required: ['name', 'age'],
properties: {
name: { type: 'string' },
age: { type: 'number' }
}
};
// Create a model for request validation
const requestModel = api.addModel('RequestModel', {
contentType: 'application/json',
modelName: 'RequestModel',
schema: {
schema: apigateway.JsonSchemaVersion.DRAFT4,
type: apigateway.JsonSchemaType.OBJECT,
title: 'MyRequest',
required: ['name', 'age'],
additionalProperties: false,
properties: {
"name": { type: apigateway.JsonSchemaType.STRING },
"age": { type: apigateway.JsonSchemaType.INTEGER }
}
}
});
// Create a request validator
const requestValidator = new apigateway.RequestValidator(this, 'RequestValidator', {
restApi: api,
validateRequestBody: true,
requestValidatorName: 'request-validator'
});
// Add a POST method to the /cars resource
cars.addMethod('POST', new apigateway.AwsIntegration({
service: 'dynamodb',
action: 'PutItem',
integrationHttpMethod: 'POST',
options: {
credentialsRole: new iam.Role(this, 'ApiGatewayDynamoDbRole', {
assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonDynamoDBFullAccess')
]
}),
requestTemplates: {
'application/json': `{"TableName": "${carsTable.tableName}",
"Item": {
#foreach($entry in $input.path('$').entrySet())
#if($entry.value != '')
"$entry.key": { "S": "$entry.value" },
#end
#end
"carId": { "S": "$context.requestId" }
}
}`,
},
integrationResponses: [
{
statusCode: '200',
responseTemplates: {
'application/json': `{"status": "car added"}`
},
selectionPattern: '200',
},
{
statusCode: '400',
responseTemplates: {
'application/json': `{"status": "client error"}`
},
selectionPattern: '4..',
}
,
{
statusCode: '500',
responseTemplates: {
'application/json': `{"status": "server error"}`
}
}
]
}
}), {
methodResponses: [
{
statusCode: '200'
},
{
statusCode: '400'
},
{
statusCode: '500'
}
],
requestModels: {
'application/json': requestModel
},
requestValidator: requestValidator
});
// Grant API Gateway permissions to put items into the DynamoDB table
carsTable.grantWriteData(new iam.ServicePrincipal('apigateway.amazonaws.com'));
}
}
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)