This example shows how an existing hapi API can be used with Stackery to run on a serverless infrastructure.
Using serverless technologies for APIs provides multiple benefits:
- Requests are handled in parallel with unbounded horizontal scalability.
- Increased infrastructure efficiency because serverless functions run only when API requests are made. Infrequently accessed APIs no longer require base-line server instance costs.
- Ops overhead is reduced as much of the engineering challenges around scalability are handled automatically by the infrastructure provider.
However, most serverless-based APIs are built by decomposing functionality into individual functions servicing only one endpoint. This can be challenging to maintain due to the complexities of managing helper functionality used across multiple endpoints.
Instead, we can build a single function servicing all requests using a mature, popular API framework like hapi. This way developers can use tools and techniques they are already familiar with to power their API services.
This repo contains a Stackery stack that can be forked and imported into your own Stackery account. The stack contains two nodes: a Rest Api node and a Function node.
The Function node is a small wrapper around hapi-example. Only one modification to hapi apps is needed to enable them to work in serverless use cases: preventing the server from listening for HTTP connections when used as a dependency of a serverless function. You can see the modification here. With this change the server can still be run locally by running node server.js
. This is great for local testing purposes!
The only other piece of functionality needed is a hookup between an incoming Stackery HTTP request message and the hapi server, and then a hookup between the hapi response and the Stackery HTTP response. This is performed by the api function handler:
const server = require('ProductsAPI')
module.exports = function handler(message, output) {
/* If you want to output messages to further nodes, you can put the output
* function on the server object: */
server.app.output = output
/* Transform Stackery message to request message for hapi */
let request = {
method: message.method,
url: message.pathname,
headers: message.headers,
payload: message.body,
remoteAddress: message.ip
}
return server.initialize()
.then(() => server.inject(request))
.then((response) => {
/* Transform hapi response to Stackery Rest Api response message */
return {
statusCode: response.statusCode,
headers: response.headers,
body: response.rawPayload
}
})
}
- Stackery account
- AWS account with an unused API Gateway Custom Domain (e.g. hapi-demo.example.com)
- Fork this repo to your own GitHub account (you will need write access to it)
- Log into Stackery
- Create a new Stackery stack
- Name the stack (e.g. hapi-demo)
- Choose to Import Stack From GitHub
- Connect your account to GitHub if needed
- Select your fork of this repo from the list of repos
- Create stack!
- Double click on the Rest Api node on the left and select your custom domain from the drop down
- If you don't see your domain in the drop down, check that the domain exists in API Gateway for the region you provisioned Stackery into.
- Deploy your stack
- Click the Deploy button in the top right corner of the Stackery dashboard, then select the Default deployment
- Switch to the Default deployment tab
- Once the deployment change set has been created, click on the change set link to be taken to AWS CloudFormation to execute the change set
- Back in the Stackery dashboard, wait for the deployment to be deployed
- Navigate to your domain and test it out! (e.g. https://hapi-demo.example.com/products)