Skip to content

Commit

Permalink
Add optional request templates properties to apigateway constructs.
Browse files Browse the repository at this point in the history
  • Loading branch information
georgebearden committed Jan 31, 2023
1 parent 2e75412 commit 1491eab
Show file tree
Hide file tree
Showing 16 changed files with 2,546 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,77 +29,122 @@ export interface ApiGatewayToDynamoDBProps {
*
* @default - Default props are used
*/
readonly dynamoTableProps?: dynamodb.TableProps,
readonly dynamoTableProps?: dynamodb.TableProps;
/**
* Existing instance of DynamoDB table object, providing both this and `dynamoTableProps` will cause an error.
*
* @default - None
*/
readonly existingTableObj?: dynamodb.Table,
readonly existingTableObj?: dynamodb.Table;
/**
* Optional user-provided props to override the default props for the API Gateway.
*
* @default - Default properties are used.
*/
readonly apiGatewayProps?: api.RestApiProps,
readonly apiGatewayProps?: api.RestApiProps;
/**
* Whether to deploy API Gateway Method for Create operation on DynamoDB table.
* Whether to deploy an API Gateway Method for POST HTTP operations on the DynamoDB table (i.e. dynamodb:PutItem).
*
* @default - false
*/
readonly allowCreateOperation?: boolean,
readonly allowCreateOperation?: boolean;
/**
* API Gateway Request template for Create method, required if allowCreateOperation set to true
* API Gateway Request Template for the create method for the default `application/json` content-type.
* This property is required if the `allowCreateOperation` property is set to true.
*
* @default - None
*/
readonly createRequestTemplate?: string,
readonly createRequestTemplate?: string;
/**
* Whether to deploy API Gateway Method for Read operation on DynamoDB table.
* Optional Create Request Templates for content-types other than `application/json`.
* Use the `createRequestTemplate` property to set the request template for the `application/json` content-type.
*
* @default - None
*/
readonly additionalCreateRequestTemplates?: { [contentType: string]: string; };
/**
* Whether to deploy an API Gateway Method for GET HTTP operations on DynamoDB table (i.e. dynamodb:Query).
*
* @default - true
*/
readonly allowReadOperation?: boolean,
readonly allowReadOperation?: boolean;
/**
* Optional API Gateway Request template for Read method, it will use the default template if
* allowReadOperation is true and readRequestTemplate is not provided.
* API Gateway Request Template for the read method for the default `application/json` content-type,
* if the `allowReadOperation` property is set to true.
*
* The default template only supports a partition key and not partition + sort keys.
*
* @default - `{ \
* "TableName": "DYNAMODB_TABLE_NAME", \
* "KeyConditionExpression": "PARTITION_KEY_NAME = :v1", \
* "ExpressionAttributeValues": { \
* ":v1": { \
* "S": "$input.params('PARTITION_KEY_NAME')" \
* } \
* } \
* }`
*/
readonly readRequestTemplate?: string;
/**
* Optional Read Request Templates for content-types other than `application/json`.
* Use the `readRequestTemplate` property to set the request template for the `application/json` content-type.
*
* @default - None
*/
readonly readRequestTemplate?: string,
readonly additionalReadRequestTemplates?: { [contentType: string]: string; };
/**
* Whether to deploy API Gateway Method for Update operation on DynamoDB table.
* Whether to deploy API Gateway Method for PUT HTTP operations on DynamoDB table (i.e. dynamodb:UpdateItem).
*
* @default - false
*/
readonly allowUpdateOperation?: boolean,
readonly allowUpdateOperation?: boolean;
/**
* API Gateway Request Template for the update method, required if the `allowUpdateOperation` property is set to true.
*
* @default - None
*/
readonly updateRequestTemplate?: string;
/**
* API Gateway Request template for Update method, required if allowUpdateOperation set to true
* Optional Update Request Templates for content-types other than `application/json`.
* Use the `updateRequestTemplate` property to set the request template for the `application/json` content-type.
*
* @default - None
*/
readonly updateRequestTemplate?: string,
readonly additionalUpdateRequestTemplates?: { [contentType: string]: string; };
/**
* Whether to deploy API Gateway Method for Delete operation on DynamoDB table.
* Whether to deploy API Gateway Method for DELETE HTTP operations on DynamoDB table (i.e. dynamodb:DeleteItem).
*
* @default - false
*/
readonly allowDeleteOperation?: boolean,
readonly allowDeleteOperation?: boolean;
/**
* Optional API Gateway Request template for Delete method, it will use the default template if
* allowDeleteOperation is true and deleteRequestTemplate is not provided.
* The default template only supports a partition key and not partition + sort keys.
* API Gateway Request Template for the delete method for the default `application/json` content-type,
* if the `allowDeleteOperation` property is set to true.
*
* @default - `{ \
* "TableName": "DYNAMODB_TABLE_NAME", \
* "Key": { \
* "${partitionKeyName}": { \
* "S": "$input.params('PARTITION_KEY_NAME')" \
* } \
* }, \
* "ReturnValues": "ALL_OLD" \
* }`
*/
readonly deleteRequestTemplate?: string;
/**
* Optional Delete request templates for content-types other than `application/json`.
* Use the `deleteRequestTemplate` property to set the request template for the `application/json` content-type.
*
* @default - None
*/
readonly deleteRequestTemplate?: string,
readonly additionalDeleteRequestTemplates?: { [contentType: string]: string; };
/**
* User provided props to override the default props for the CloudWatchLogs LogGroup.
*
* @default - Default props are used
*/
readonly logGroupProps?: logs.LogGroupProps
readonly logGroupProps?: logs.LogGroupProps;
}

/**
Expand Down Expand Up @@ -162,18 +207,14 @@ export class ApiGatewayToDynamoDB extends Construct {
apiGatewayRole: this.apiGatewayRole,
apiMethod: "POST",
apiResource: this.apiGateway.root,
requestTemplate: createRequestTemplate
requestTemplate: createRequestTemplate,
additionalRequestTemplates: props.additionalCreateRequestTemplates
});
}
// Read
if (props.allowReadOperation === undefined || props.allowReadOperation === true) {
let readRequestTemplate;

if (props.readRequestTemplate) {
readRequestTemplate = props.readRequestTemplate;
} else {
readRequestTemplate =
`{ \
const readRequestTemplate = props.readRequestTemplate ??
`{ \
"TableName": "${this.dynamoTable.tableName}", \
"KeyConditionExpression": "${partitionKeyName} = :v1", \
"ExpressionAttributeValues": { \
Expand All @@ -182,7 +223,6 @@ export class ApiGatewayToDynamoDB extends Construct {
} \
} \
}`;
}

this.addActionToPolicy("dynamodb:Query");
defaults.addProxyMethodToApiResource({
Expand All @@ -191,7 +231,8 @@ export class ApiGatewayToDynamoDB extends Construct {
apiGatewayRole: this.apiGatewayRole,
apiMethod: "GET",
apiResource: apiGatewayResource,
requestTemplate: readRequestTemplate
requestTemplate: readRequestTemplate,
additionalRequestTemplates: props.additionalReadRequestTemplates
});
}
// Update
Expand All @@ -204,18 +245,14 @@ export class ApiGatewayToDynamoDB extends Construct {
apiGatewayRole: this.apiGatewayRole,
apiMethod: "PUT",
apiResource: apiGatewayResource,
requestTemplate: updateRequestTemplate
requestTemplate: updateRequestTemplate,
additionalRequestTemplates: props.additionalUpdateRequestTemplates
});
}
// Delete
if (props.allowDeleteOperation && props.allowDeleteOperation === true) {
let deleteRequestTemplate;

if (props.deleteRequestTemplate) {
deleteRequestTemplate = props.deleteRequestTemplate;
} else {
deleteRequestTemplate =
`{ \
const deleteRequestTemplate = props.deleteRequestTemplate ??
`{ \
"TableName": "${this.dynamoTable.tableName}", \
"Key": { \
"${partitionKeyName}": { \
Expand All @@ -224,7 +261,6 @@ export class ApiGatewayToDynamoDB extends Construct {
}, \
"ReturnValues": "ALL_OLD" \
}`;
}

this.addActionToPolicy("dynamodb:DeleteItem");
defaults.addProxyMethodToApiResource({
Expand All @@ -233,7 +269,8 @@ export class ApiGatewayToDynamoDB extends Construct {
apiGatewayRole: this.apiGatewayRole,
apiMethod: "DELETE",
apiResource: apiGatewayResource,
requestTemplate: deleteRequestTemplate
requestTemplate: deleteRequestTemplate,
additionalRequestTemplates: props.additionalDeleteRequestTemplates
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,83 @@ test("check setting allowReadOperation=false for dynamodb", () => {

// Expect only one APIG Method (DELETE) for allowDeleteOperation
expect(stack2).toCountResources("AWS::ApiGateway::Method", 1);
});

test('Construct accepts additional create request templates', () => {
const stack = new Stack();
new ApiGatewayToDynamoDB(stack, 'api-gateway-dynamodb', {
allowCreateOperation: true,
createRequestTemplate: 'create-me',
additionalCreateRequestTemplates: {
'text/plain': 'Hello'
}
});

expect(stack).toHaveResourceLike('AWS::ApiGateway::Method', {
HttpMethod: 'POST',
Integration: {
RequestTemplates: {
'application/json': 'create-me',
'text/plain': 'Hello'
}
}
});
});

test('Construct accepts additional read request templates', () => {
const stack = new Stack();
new ApiGatewayToDynamoDB(stack, 'api-gateway-dynamodb', {
additionalReadRequestTemplates: {
'text/plain': 'Hello'
}
});

expect(stack).toHaveResourceLike('AWS::ApiGateway::Method', {
HttpMethod: 'GET',
Integration: {
RequestTemplates: {
'text/plain': 'Hello'
}
}
});
});

test('Construct accepts additional update request templates', () => {
const stack = new Stack();
new ApiGatewayToDynamoDB(stack, 'api-gateway-dynamodb', {
allowUpdateOperation: true,
updateRequestTemplate: 'default-update-template',
additionalUpdateRequestTemplates: {
'text/plain': 'additional-update-template'
}
});

expect(stack).toHaveResourceLike('AWS::ApiGateway::Method', {
HttpMethod: 'PUT',
Integration: {
RequestTemplates: {
'application/json': 'default-update-template',
'text/plain': 'additional-update-template'
}
}
});
});

test('Construct accepts additional delete request templates', () => {
const stack = new Stack();
new ApiGatewayToDynamoDB(stack, 'api-gateway-dynamodb', {
allowDeleteOperation: true,
additionalDeleteRequestTemplates: {
'text/plain': 'DeleteMe'
}
});

expect(stack).toHaveResourceLike('AWS::ApiGateway::Method', {
HttpMethod: 'DELETE',
Integration: {
RequestTemplates: {
'text/plain': 'DeleteMe'
}
}
});
});
Loading

0 comments on commit 1491eab

Please sign in to comment.