Getting API Gateway to post direct to SQS

Written on May 3, 2019

Do more with less

In the last post we looked at using CDK to develop a serverless pipeline to deploy code. So now it’s time to iterate and see if we can improve things.

I remember seeing at post from Richard Boyd on Mastering API Gateway in 105 easy steps which is a great read on how powerful API Gateway can be integrating with a laundry list of AWS services out fo the box.

So I figured we could drop one of my Lambda functions and get API Gateway to post direct to SQS. I thought this was going to be simple, but it turns out API Gateway is a bit of a beast and requires some request/response transforms and mappings, but we got there in the end and thought I would share.

This is what the main CDK file looks like now with regards to API Gateway and SQS.

//Create an IAM Role for API Gateway to assume
const apiGatewayRole = new iam.Role(sharedStack, 'ApiGatewayRole', {
assumedBy: new ServicePrincipal('apigateway.amazonaws.com')
});

//Create an empty response model for API Gateway
var model :EmptyModel = {
modelId: "Empty"
};

//Create a method response for API Gateway using the empty model
var methodResponse :MethodResponse = {
statusCode: '200',
responseModels: {'application/json': model}
};

//Add the method options with method response to use in API Method
var methodOptions :MethodOptions = {
methodResponses: [
    methodResponse
]
};

//Create intergration response for SQS
var integrationResponse :IntegrationResponse = {
statusCode: '200'
};

//Create integration options for API Method
var integrationOptions :IntegrationOptions = {
credentialsRole: apiGatewayRole,
requestParameters: {
    'integration.request.header.Content-Type': "'application/x-www-form-urlencoded'"
},
requestTemplates: {
    'application/json': 'Action=SendMessage&QueueUrl=$util.urlEncode("' + sqsQueue.queueUrl + '")&MessageBody=$util.urlEncode($input.body)'
},
integrationResponses: [
    integrationResponse
]
};

//Create the SQS Integration
const apiGatewayIntegration = new apigw.AwsIntegration({ 
service: "sqs",
path: sharedStack.env.account + '/' + sqsQueue.queueName,
integrationHttpMethod: "POST",
options: integrationOptions,
});

//Create the API Gateway
const apiGateway = new apigw.RestApi(sharedStack, "Endpoint");

//Create a API Gateway Resource
const msg = apiGateway.root.addResource('msg');

//Create a Resource Method
msg.addMethod('POST', apiGatewayIntegration, methodOptions);

//Grant API GW IAM Role access to post to SQS
sqsQueue.grantSendMessages(apiGatewayRole);

Check out the full source here

Now I can remove the Lambda function, pipeline and most importantly save some $$$

Written on May 3, 2019