aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.68k stars 3.92k forks source link

apigatewayv2-integrations: Add support for SQS-SendMessage integration #24785

Open DaWyz opened 1 year ago

DaWyz commented 1 year ago

Describe the feature

ApiGatewayv2 HTTP API integrates with SQS to redirect the request into a queue. It would be nice to have CDK implement this. See documentation on SQS-SendMessage mapping.

Use Case

I want an easy way to use an SQS Queue as a proxy for my HTTP API.

Proposed Solution

Implement the construct similarly to the lambda integration.

It would look like the following:

    const stack = new Stack();
    const api = new HttpApi(stack, 'HttpApi');
    const queue = DefaultQueue(stack, 'Queue');
    new HttpRoute(stack, 'LambdaProxyRoute', {
      httpApi: api,
      integration: new HttpSqsQueueIntegration('Integration', queue, {
        parameterMapping: new ParameterMapping()
          .appendHeader('header2', MappingValue.requestHeader('header1'))
          .removeHeader('header1'),
      }),
      routeKey: HttpRouteKey.with('/pets'),
    });

Other Information

No response

Acknowledgements

CDK version used

2.70.0

Environment details (OS name and version, etc.)

Ubuntu 20

pahud commented 1 year ago

Yes this would be awesome! We'd be glad to review your PR when it is ready. Thank you.

DaWyz commented 1 year ago

@pahud , I just realized there are more than a single SQS integration type:

Should we:

pahud commented 1 year ago

Hi @DaWyz

This will need discussion with the core team maintainers, I would suggest you create a PR draft and describe your API design in the description and discuss with the maintainer in the PR draft before you finalize it.

benm5678 commented 1 year ago

In case it helps give a start, here's how I did it for the SendMessage:

Usage:

httpApi.addRoutes({
    path: `/sendMessage`,
    methods: [gw2.HttpMethod.POST],
    integration: new HttpSqsSendIntegration(this, 'MySQSSendIntegrationId', myQueue, {
      messageAttributes: '{ "test": { "DataType": "String", "StringValue": "val1" } }'
    }),
  });

Extended class:

import * as iam from 'aws-cdk-lib/aws-iam';
import * as gw2 from '@aws-cdk/aws-apigatewayv2-alpha';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { Construct } from 'constructs';

export interface HttpSqsSendIntegrationProps {
  readonly messageBody?: string;
  readonly messageAttributes?: string;
}

export class HttpSqsSendIntegration extends gw2.HttpRouteIntegration {
  private readonly sqs: sqs.Queue;
  private readonly role: iam.Role;
  private readonly props?: HttpSqsSendIntegrationProps;
  bind(options: gw2.HttpRouteIntegrationBindOptions): gw2.HttpRouteIntegrationConfig {
    return {
      type: gw2.HttpIntegrationType.AWS_PROXY,
      subtype: gw2.HttpIntegrationSubtype.SQS_SEND_MESSAGE,
      payloadFormatVersion: gw2.PayloadFormatVersion.VERSION_1_0,
      parameterMapping: new gw2.ParameterMapping()
        .custom('QueueUrl', this.sqs.queueUrl)
        .custom('MessageBody', this.props?.messageBody ?? '$request.body')
        .custom('MessageAttributes', this.props?.messageAttributes ?? ''),
      credentials: gw2.IntegrationCredentials.fromRole(this.role),
    };
  }

  constructor(scope: Construct, id: string, sqs: sqs.Queue, props?: HttpSqsSendIntegrationProps) {
    super(id);
    this.sqs = sqs;
    this.props = props;
    this.role = new iam.Role(scope, "HTTP-API-Role", {
      assumedBy: new iam.ServicePrincipal("apigateway.amazonaws.com"),
      inlinePolicies: {
        'sqs-send': new iam.PolicyDocument({
          statements: [
            new iam.PolicyStatement({
              actions: ['sqs:SendMessage'],
              resources: [sqs.queueArn],
              effect: iam.Effect.ALLOW,
            }),
          ],
        }),
      },
    });
  }
}
clutteralx commented 11 months ago

Thank you for sharing your implementation @benm5678! I have been getting this error when trying to add a route to a HttpApi using your HttpSqsSendIntegration:

firefox_jbkJtzWfeY

I haven't seen anyone else have this Mapping expression missing source or destination error.

tomgelmersio commented 11 months ago

@clutteralx This might be because, in my experience, the MessageAttributes cannot be an empty string. Try removing the mapping entirely if there is no value.

clutteralx commented 11 months ago

@clutteralx This might be because, in my experience, the MessageAttributes cannot be an empty string. Try removing the mapping entirely if there is no value.

That was the issue. It works perfectly now. Thanks so much 🎉

nicklasweasel commented 8 months ago

Is this on any roadmap? It would be nice to have CDK support for stuff you can do in the console