AWS CDK: Amazon API Gateway integration for SQS

December 7th, 2020 327 Words

Most people know Amazon API Gateway from using it to build HTTP interfaces for AWS Lambda functions. But, in general, you can use API Gateway to call a variety AWS APIs using HTTPS. This post shows how to create an HTTPS interface for Amazon SQS using the AWS Cloud Development Kit.

When building serverless application, you are used to decouple components. Most approaches for loosely coupled services use API Gateway to trigger an AWS Lambda function and the AWS SDK to send a message to SQS. But, you can integrate SQS directly in Amazon API Gateway!

SQS and IAM

To get started, create an SQS queue with the AWS Cloud Development Kit and construct an IAM Role that can be assumed by the apigateway.amazonaws.com principle and grants access to use the sqs:SendMessage action for the created queue.

const messageQueue = new sqs.Queue(this, "Queue");

const credentialsRole = new iam.Role(this, "Role", {
  assumedBy: new iam.ServicePrincipal("apigateway.amazonaws.com"),
});

credentialsRole.attachInlinePolicy(
  new iam.Policy(this, "SendMessagePolicy", {
    statements: [
      new iam.PolicyStatement({
        actions: ["sqs:SendMessage"],
        effect: iam.Effect.ALLOW,
        resources: [messageQueue.queueArn],
      }),
    ],
  })
);

Amazon API Gateway

Using the AWS Integration in Amazon API Gateway, you can call AWS APIs whenever a matching HTTP request is handled by Amazon API Gateway. Create a new Rest API and configure an HTTP method and resource:

const api = new apigateway.RestApi(this, "Endpoint", {
  deployOptions: {
    stageName: "run",
    tracingEnabled: true,
  },
});

const queue = api.root.addResource("queue");
queue.addMethod(
  "GET",
  new apigateway.AwsIntegration({
    service: "sqs",
    path: `${cdk.Aws.ACCOUNT_ID}/${messageQueue.queueName}`,
    integrationHttpMethod: "POST",
    options: {
      credentialsRole,
      passthroughBehavior: apigateway.PassthroughBehavior.NEVER,
      requestParameters: {
        "integration.request.header.Content-Type": `'application/x-www-form-urlencoded'`,
      },
      requestTemplates: {
        "application/json": `Action=SendMessage&MessageBody=$util.urlEncode("$method.request.querystring.message")`,
      },
      integrationResponses: [
        {
          statusCode: "200",
          responseTemplates: {
            "application/json": `{"done": true}`,
          },
        },
      ],
    },
  }),
  { methodResponses: [{ statusCode: "200" }] }
);

After deploying this CloudFormation stack, you have an Amazon API Gateway for sending messages to SQS. Just use curl to send a simple GET request to the created endpoint.

$ > curl https://a4c1sff3v.execute-api.eu-central-1.amazonaws.com/run/queue\?message\=example

{"done": true}

Now, have a look at your SQS queue. There is a new message!