Deploy to Cloud Run an API built with HAPI framework

Emanuele Pecorari
4 min readMay 26, 2022

The application is quite easy. We use Airtable to store a list of services and we want to create an APIs based on the HAPI framework to retrieve the list through a GET method.

Airtable setup

First we create a base in Airtable (called “Services”) and a view that we call “General”:

The General view in Airtable

Once the view is created, Airtable creates an API that can be used to retrieve the data.

Airtable API provisioning explained

Your API documentation can be found at https://airtable.com/api clicking on the button with the name of your base (“Services” on our case). It contains the explication to request the data, how to authenticate and some code examples. Every change you will do to the existent views or a new views will be reflected in the documentation.

Airtable API documentation

Now, we need to get the api key to call the Airtable API: it can be found in the account settings reachable clicking on the icon at the top right. We’ll use it later in our code.

HAPI Framework

HApi is one of the several web frameworks based on Javascript. Originally built by Walmart, it allows to build APIs and complete them with the available plugins to guarantee security, connectivity, testing and so on.

We create our application inside a folder running

npm init

and we install hapi

npm install @hapi/hapi

Our package.json should look like:

{
"name": "myapi",
"version": "0.0.1",
"description": "My description",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Myself",
"license": "ISC",
"dependencies": {
"@hapi/hapi": "^20.2.2"
}
}

Let’s add the code of our APIs. We want to create the following resource:

GET /companies

In the index.js we can add the following code (replace <airtable_key> with the value you got from the previous script):

'use strict';
var https = require('https');
const Hapi = require('@hapi/hapi');
const { resolve } = require('path');
let get_companies_from_airtable = async () => {
return new Promise((resolve) => {
let options = {
host: 'api.airtable.com',
path: '/v0/appXQzgiXWq5DzaoI/Services?maxRecords=3&view=General',
method: 'GET',
headers: {
Authorization: 'Bearer <airtable_key>',
},
};

https.get(options, (resp) => {
let data = '';
// A chunk of data has been received.
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('error', (chunk) => {
console.log(e);
return (e.getMessage())
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
resolve(JSON.parse(data));
});
});
});
};
const port = parseInt(process.env.PORT) || 8080;const init = async () => {
let server = Hapi.server({
port: port,
host: '0.0.0.0',
});
server.route({
method: 'GET',
path: '/companies',
handler: async (request, h) => {
return await get_companies_from_airtable()
},
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();

which is quite simple:

  • it starts the server and create a route GET /companies
  • when the request arrives, the method get_companies_from_airtable is called
  • the result obtained from the Airtable api is sent as response

Pay attention at host value in the server initialization. It should be 0.0.0.0 to allow to receive the requests on Cloud Run.

const init = async () => {
let server = Hapi.server({
port: port,
host: '0.0.0.0',
});

CloudRun deployment

This time we’ll rely on the Cloud Run deployment from source: we don’t need to create any Dockerfile. This is an easier method but it gives less flexibility in terms of configuration.

To launch the deployment in the Frankfurt region, we can execute:

gcloud run deploy --region europe-west3

This command will create an image from our source code and it will upload and deploy it on Cloud Run.

If we don’t have the needed GCP API enabled (for example the Cloud Run API), we can let the command line do the job for us:

For simplicity, we allow unauthenticated calls to our endpoint:

Once the deployment ended (the url to reach our service will be shown in the terminal) we can see that everything is ok going to the GCP console (again the URL can be found as pointed by the arrow in the image below):

Dashboard of our Cloud Run service

That’s it. Our API is ready to be used.

Now, we can go to a browser and type:

https://<service_url>.run.app/companies

to retrieve the response.

For more security

Let’s use now environment variables and avoid to include the Airtable key in the source code (always a good idea when we push our application to Github for example).

Between line 8 and 15 we’ll have

let options = {
host: 'api.airtable.com',
path: '/v0/appXQzgiXWq5DzaoI/Services?maxRecords=3&view=General',
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.AIRTABLE_KEY}`,
},
};

and to deploy the application now we can execute:

gcloud run deploy — region europe-west3 — update-env-vars AIRTABLE_KEY=<key>

--

--

Emanuele Pecorari

Cloud Architect and Tech Product Owner. Soccer player and coach in the free time.