Node and AWS API Gateway
Happy New Year :D
You would think that integrating a call from a Node app into an AWS API Gateway would be fairly easy.
It wasn’t.
A number of things prevented me from working efficiently:
-
Context switching - I need time to learn, play, gain expertise, fine-tune, and pass on the knowledge.
This hasn’t happened. The constant problems with a third-party platform prevent this focus on a single task.
-
Different / later version of Node (which use things like async)
-
Not being able to develop locally.
-
Not having the IAM roles / permissions to work.
Over the break, I wanted to move forward, and break-the-back of this task
I went back to basics, and grabbed my notes from the February 2017 meetup, where I had presented on using the AWS API Gateway.

I used the sample PetStore (provided by the API Gateway), and created an API key, and IAM Role which was associated to the PetStore, and Usage plan
I started off by using just the API key to test an endpoint with:
GET /int//pets/1 HTTP/1.1
Content-Type: application/json
x-api-key: [snip]
Host: [snip]
Connection: close
User-Agent: Paw/3.1.4 (Macintosh; OS X/10.13.2) GCDHTTPRequest
The response is here:
HTTP/1.1 200 OK
Date: Sun, 31 Dec 2017 16:12:33 GMT
Content-Type: application/json
Content-Length: 49
Connection: close
x-amzn-RequestId: [snip]
Access-Control-Allow-Origin: *
X-Amzn-Trace-Id: Root= [snip]
{
"id": 1,
"type": "dog",
"price": 249.99
}
Integrating with Node
The next step was integrating with Node v6.10.3.
I wanted to use https://www.npmjs.com/package/aws-api-gateway-client.
I have developed the following simple Node app, which allows me to call the PetStore endpoint successfully:
const express = require('express');
const app = express();
const crontab = require('node-crontab');
const apiEndpoint = '[snip]';
const APIGatewayClientFactory = require('aws-api-gateway-client').default;
let AWS = require('aws-sdk');
let sts = new AWS.STS();
let params = {};
let AWSCredentials;
let data = {};
function updateEC2CredentialsViaCronjobEveryMinute() {
crontab.scheduleJob("* * * * *", function() {
getEC2SessionCredentials()
.then((credentials) => {
AWSCredentials = credentials;
})
.catch((err) => {
console.log(err);
});
});
}
function getAPIGatewayWrapper(AWSCredentials, params, pathTemplate){
return APIGatewayClientFactory.newClient({
invokeUrl: apiEndpoint,
accessKey: AWSCredentials.Credentials.AccessKeyId,
secretKey: AWSCredentials.Credentials.SecretAccessKey,
sessionToken: AWSCredentials.Credentials.SessionToken,
region: 'eu-west-1',
apiKey: '[snip]'
}).invokeApi(params, pathTemplate, 'GET', {}, {})
}
function getEC2SessionCredentials() {
console.log("getting creds");
let promise = new Promise((resolve,reject)=>{
data = sts.getSessionToken(params, function (err, data) {
if (err)
reject(err);
else
resolve(data);
})
});
return promise;
}
app.get('/', (req, res) => {
let params = {
number: '1'
};
let pathTemplate = '/pets/{number}';
getAPIGatewayWrapper(AWSCredentials, params, pathTemplate, res)
.then((APIGatewayResponse) => {
data = APIGatewayResponse.data;
console.log(JSON.stringify(APIGatewayResponse.data.type, null, 4));
res.status(200).send(data);
})
.catch((err)=>{
console.log(err);
data = {
"error": "an error occurred"
};
res.status(500).send(data);
});
});
getEC2SessionCredentials()
.then((credentials) => {
AWSCredentials = credentials;
updateEC2CredentialsViaCronjobEveryMinute();
app.listen(3000, () => console.log("starting"));
});
I have been experimenting with updating the session AWS credentials (used by the aws-api-gateway-client), and have opted for a Cronjob.
Running with curl gives me the output I am expecting:
http://localhost:3000/?14 --> <stdout>
--_curl_--http://localhost:3000/?14
{"id":1,"type":"dog","price":249.99}
What have I learnt?
The process of implementing my own API gateway, and local Node app has allowed me:
-
To concentrate on the task at hand.
-
Used my own AWS account, my own API keys, and my own IAM roles.
-
Completed a working POC, which has reinforced learning, by staying on track.
-
The code can be further improved, but has allowed me to gain more experience in Node..
What I have avoided?
-
Getting involved in hacking AWS IAM roles.
-
Losing focus.
-
Remote development on an EC2 box.
What I haven’t avoided?
- Interesting…yes, but spending my own time working on a “work task”
I’ve deliberately gone back to basics over the holidays, kept things simple, and focused, and surprise surprise, things have gone to plan.