-
Notifications
You must be signed in to change notification settings - Fork 249
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(aws-apigateway-sqs): update construct to allow custom path params #1079
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,14 +63,17 @@ new ApiGatewayToSqs(this, "ApiGatewayToSqsPattern", new ApiGatewayToSqsProps.Bui | |
|deployDeadLetterQueue?|`boolean`|Whether to deploy a secondary queue to be used as a dead letter queue. Defaults to `true`.| | ||
|maxReceiveCount|`number`|The number of times a message can be unsuccessfully dequeued before being moved to the dead-letter queue.| | ||
|allowCreateOperation?|`boolean`|Whether to deploy an API Gateway Method for POST HTTP operations on the queue (i.e. sqs:SendMessage).| | ||
|createRequestPath?|`string`| Optional, user provided request path for POST HTTP operations.| | ||
|createRequestTemplate?|`string`|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.| | ||
|additionalCreateRequestTemplates?|`{ [contentType: string]: string; }`|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. This property can only be specified if the `allowCreateOperation` property is set to true.| | ||
|createIntegrationResponses?|[`api.IntegrationResponses[]`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.IntegrationResponse.html)|Optional, custom API Gateway Integration Response for the create method. This property can only be specified if the `allowCreateOperation` property is set to true.| | ||
|allowReadOperation?|`boolean`|Whether to deploy an API Gateway Method for GET HTTP operations on the queue (i.e. sqs:ReceiveMessage).| | ||
|readRequestPath?|`string`| Optional, user provided request path for GET HTTP operations.| | ||
|readRequestTemplate?|`string`|API Gateway Request Template for the read method for the default `application/json` content-type.| | ||
|additionalReadRequestTemplates?|`{ [contentType: string]: 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.| | ||
|readIntegrationResponses?|[`api.IntegrationResponses[]`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.IntegrationResponse.html)|Optional, custom API Gateway Integration Response for the read method.| | ||
|allowDeleteOperation?|`boolean`|Whether to deploy an API Gateway Method for HTTP DELETE operations on the queue (i.e. sqs:DeleteMessage).| | ||
|allowDeleteOperation?|`boolean`|Whether to deploy an API Gateway Method for DELETE HTTP operations on the queue (i.e. sqs:DeleteMessage).| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Swapped |
||
|deleteRequestPath?|`string`| Optional, user provided request path for DELETE HTTP operations.| | ||
|deleteRequestTemplate?|`string`|API Gateway Request Template for THE delete method for the default `application/json` content-type. This property can only be specified if the `allowDeleteOperation` property is set to true.| | ||
|additionalDeleteRequestTemplates?|`{ [contentType: string]: 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. This property can only be specified if the `allowDeleteOperation` property is set to true.| | ||
|deleteIntegrationResponses?|[`api.IntegrationResponses[]`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.IntegrationResponse.html)|Optional, custom API Gateway Integration Response for the delete method. This property can only be specified if the `allowDeleteOperation` property is set to true.| | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -169,6 +169,27 @@ export interface ApiGatewayToSqsProps { | |
* @default - None | ||
*/ | ||
readonly encryptionKeyProps?: kms.KeyProps; | ||
/** | ||
* Optional, custom API Gateway path for the GET method. | ||
* This property can only be specified if the `allowReadOperation` property is not set to false. | ||
* | ||
* @default - "" | ||
*/ | ||
readonly readRequestPath?: string; | ||
/** | ||
* Optional, custom API Gateway path for the POST method. | ||
* This property can only be specified if the `allowCreateOperation` property is not set to false. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the allowDeleteOperation and allowCreateOperation attributes default to false, it seems the wording for these would be better as "This property can only be specified if the `allowCreateOperation' is set to true." |
||
* | ||
* @default - "" | ||
*/ | ||
readonly createRequestPath?: string; | ||
/** | ||
* Optional, custom API Gateway path for the DELETE method. | ||
* This property can only be specif||ied if the `allowDeleteOperation` property is not set to false. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pretty sure you don't mean 'specif' OR 'ied' here and that this is a typo? |
||
* | ||
* @default - "message" | ||
*/ | ||
readonly deleteRequestPath?: string; | ||
} | ||
|
||
/** | ||
|
@@ -200,15 +221,15 @@ export class ApiGatewayToSqs extends Construct { | |
|
||
if (this.CheckCreateRequestProps(props)) { | ||
throw new Error(`The 'allowCreateOperation' property must be set to true when setting any of the following: ` + | ||
`'createRequestTemplate', 'additionalCreateRequestTemplates', 'createIntegrationResponses'`); | ||
`'createRequestTemplate', 'additionalCreateRequestTemplates', 'createIntegrationResponses', 'createRequestPath'`); | ||
} | ||
if (this.CheckReadRequestProps(props)) { | ||
throw new Error(`The 'allowReadOperation' property must be set to true or undefined when setting any of the following: ` + | ||
`'readRequestTemplate', 'additionalReadRequestTemplates', 'readIntegrationResponses'`); | ||
`'readRequestTemplate', 'additionalReadRequestTemplates', 'readIntegrationResponses', 'readRequestPath'`); | ||
} | ||
if (this.CheckDeleteRequestProps(props)) { | ||
throw new Error(`The 'allowDeleteOperation' property must be set to true when setting any of the following: ` + | ||
`'deleteRequestTemplate', 'additionalDeleteRequestTemplates', 'deleteIntegrationResponses'`); | ||
`'deleteRequestTemplate', 'additionalDeleteRequestTemplates', 'deleteIntegrationResponses', 'deleteRequestPath'`); | ||
} | ||
|
||
// Setup the dead letter queue, if applicable | ||
|
@@ -244,13 +265,14 @@ export class ApiGatewayToSqs extends Construct { | |
// Create | ||
const createRequestTemplate = props.createRequestTemplate ?? this.defaultCreateRequestTemplate; | ||
if (props.allowCreateOperation && props.allowCreateOperation === true) { | ||
const apiCreateRequestResource = props.createRequestPath ? this.apiGateway.root.addResource(props.createRequestPath) : this.apiGateway.root; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The first thing I tried was creating a new integration test with the following:
I think think a single resource for a workload, using the HTTP method to distinguish between operations, is a reasonable expectation of a client. While it's going to be non-trivial, it seems worthwhile to sort out the required resources prior to line 266. (I did not write this test anticipating this issue, I was lazy and reused the resource name :-) An alternative would be specifying a single, optional resource name that would be used across all implemented HTTP methods. The more I think about this, the more it appeals to me. Using different resource names for different HTTP methods on the same queue does not seem like a design we would want to encourage (and shouldn't have implemented ourselves with the 'message' resource). What do you think? |
||
this.addActionToPolicy("sqs:SendMessage"); | ||
defaults.addProxyMethodToApiResource({ | ||
service: "sqs", | ||
path: `${cdk.Aws.ACCOUNT_ID}/${this.sqsQueue.queueName}`, | ||
apiGatewayRole: this.apiGatewayRole, | ||
apiMethod: "POST", | ||
apiResource: this.apiGateway.root, | ||
apiResource: apiCreateRequestResource, | ||
requestTemplate: createRequestTemplate, | ||
additionalRequestTemplates: props.additionalCreateRequestTemplates, | ||
contentType: "'application/x-www-form-urlencoded'", | ||
|
@@ -261,13 +283,14 @@ export class ApiGatewayToSqs extends Construct { | |
// Read | ||
const readRequestTemplate = props.readRequestTemplate ?? this.defaultReadRequestTemplate; | ||
if (props.allowReadOperation === undefined || props.allowReadOperation === true) { | ||
const apiReadRequestResource = props.readRequestPath ? this.apiGateway.root.addResource(props.readRequestPath) : this.apiGateway.root; | ||
this.addActionToPolicy("sqs:ReceiveMessage"); | ||
defaults.addProxyMethodToApiResource({ | ||
service: "sqs", | ||
path: `${cdk.Aws.ACCOUNT_ID}/${this.sqsQueue.queueName}`, | ||
apiGatewayRole: this.apiGatewayRole, | ||
apiMethod: "GET", | ||
apiResource: this.apiGateway.root, | ||
apiResource: apiReadRequestResource, | ||
requestTemplate: readRequestTemplate, | ||
additionalRequestTemplates: props.additionalReadRequestTemplates, | ||
contentType: "'application/x-www-form-urlencoded'", | ||
|
@@ -278,14 +301,14 @@ export class ApiGatewayToSqs extends Construct { | |
// Delete | ||
const deleteRequestTemplate = props.deleteRequestTemplate ?? this.defaultDeleteRequestTemplate; | ||
if (props.allowDeleteOperation && props.allowDeleteOperation === true) { | ||
const apiGatewayResource = this.apiGateway.root.addResource('message'); | ||
const apiDeleteRequestResource = this.apiGateway.root.addResource(props.deleteRequestPath ?? 'message'); | ||
this.addActionToPolicy("sqs:DeleteMessage"); | ||
defaults.addProxyMethodToApiResource({ | ||
service: "sqs", | ||
path: `${cdk.Aws.ACCOUNT_ID}/${this.sqsQueue.queueName}`, | ||
apiGatewayRole: this.apiGatewayRole, | ||
apiMethod: "DELETE", | ||
apiResource: apiGatewayResource, | ||
apiResource: apiDeleteRequestResource, | ||
requestTemplate: deleteRequestTemplate, | ||
additionalRequestTemplates: props.additionalDeleteRequestTemplates, | ||
contentType: "'application/x-www-form-urlencoded'", | ||
|
@@ -294,22 +317,22 @@ export class ApiGatewayToSqs extends Construct { | |
} | ||
} | ||
private CheckReadRequestProps(props: ApiGatewayToSqsProps): boolean { | ||
if ((props.readRequestTemplate || props.additionalReadRequestTemplates || props.readIntegrationResponses) | ||
if ((props.readRequestTemplate || props.additionalReadRequestTemplates || props.readIntegrationResponses || props.readRequestPath) | ||
&& props.allowReadOperation === false) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
private CheckDeleteRequestProps(props: ApiGatewayToSqsProps): boolean { | ||
if ((props.deleteRequestTemplate || props.additionalDeleteRequestTemplates || props.deleteIntegrationResponses) | ||
if ((props.deleteRequestTemplate || props.additionalDeleteRequestTemplates || props.deleteIntegrationResponses || props.deleteRequestPath) | ||
&& props.allowDeleteOperation !== true) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
private CheckCreateRequestProps(props: ApiGatewayToSqsProps): boolean { | ||
if ((props.createRequestTemplate || props.additionalCreateRequestTemplates || props.createIntegrationResponses) | ||
if ((props.createRequestTemplate || props.additionalCreateRequestTemplates || props.createIntegrationResponses || props.createRequestPath) | ||
&& props.allowCreateOperation !== true) { | ||
return true; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should call these attributes resources rather than paths (createRequestResource, readRequestResource, etc.). We only allow one level deep - if someone tries to specify a valid "path" name of "resource/subresource" the stack will fail to launch because this is an invalid resource name.