First of all, why a function as a service to wrap a REST API ?
You, may, don’t want to expose your own OpenCage API Key to your client end users; you may want to analyse requests sent to OpenCage, etc.
So here is a solution to proxy the requests on your own Google Cloud infrastructure.
Tutorial
We will first need a Google account to activate the Google Cloud Platform. Then, we will be using the Serverless Framework from serverless.com.
Prerequisites
- node with npm or yarn, or a js package manager or your choice
- serverless: for convenience you can install it globally
$ npm i -g serverless
Assuming serverless has been setup globally, the sls
and serverless
commands are both available from your command line.
Google — Credentials
The Serverless Framework needs access to account credentials for your Google Cloud account so that it can create and manage resources on your behalf.
Create a Google Cloud Account
We need a Billing Account with a credit card attached to use Google Cloud Functions. Here’s how to create one:
- Create the account.
- Enter the name of the Billing Account and enter your billing information. And click Submit to enable billing.
- A new Billing Account will offer you a free trial.
If necessary, a more detailed guide on creating a Billing Account can be found here.
Create a new Google Cloud Project
A Google Cloud Project is required to use Google Cloud Functions. Here’s how to create one:
- Go to the Google Cloud Console.
- There is a dropdown near the top left of the screen (near the search bar that lists your projects). Click it and select
Create Project
. - Enter a Project name and select the Billing Account you created in the steps above.
- Click on
Create
to start the creation process. - Wait until the Project was successfully created and Google will redirect you to your new Project.
- Verify your currently within your new Project by looking at the dropdown next to the search bar. This should mark your new Project as selected.
Enable the necessary APIs
You need to enable the following APIs so that Serverless can create the corresponding resources.
Go to the API dashboard
, select your project and enable the following APIs:
- Google Cloud Functions
- Google Cloud Deployment Manager
- Google Cloud Storage
- Stackdriver Logging
Get credentials
You need to create credentials Serverless can use to create resources in your Project.
- Go to the
Google Cloud API Manager
and selectCredentials
on the left. - Click on
Create credentials
and selectService account key
. - Select
New service account
in theService account
dropdown. - Enter a name for your
Service account name
(e.g. "opencage-function"). - Select
Project
-->Owner
as theRole
. Key type
isJSON
.- Click on
Create
to create your private key. - The so called
keyfile
will be downloaded on your machine. - Save the
keyfile
somewhere secure. I recommend making a folder in your home folder and putting it there; like this,~/.gcloud/keyfile.json
. You can change the file name fromkeyfile
to anything according to the goolge project name. Just try to remember the path you saved it to!
Create a new project from a serverless boilerplate
Serverless will help up us to bootstrap the project with the following command:
$ serverless create --template google-nodejs --path gcloud-functions-opencage-geocoder
and it will output:
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "[...]/gcloud-functions-opencage-geocoder"
_______ __
| _ .-----.----.--.--.-----.----| .-----.-----.-----.
| |___| -__| _| | | -__| _| | -__|__ --|__ --|
|____ |_____|__| \___/|_____|__| |__|_____|_____|_____|
| | | The Serverless Application Framework
| | serverless.com, v1.32.0
-------' Serverless: Successfully generated boilerplate for template: "google-nodejs"
now let’s get into the folder to have a look at what’s been created:
$ cd gcloud-functions-opencage-geocoder/$ ls -althat will output this directory structure:.
├── .gitignore
├── index.js
├── package.json
└── serverless.yml
Lock down the framework version
By adding serverless
as a development dependency, we will be ensure to get a compatible version, without using the global version (useful for your CI):
$ npm i -D serverless
Update the service name in serverless.yml
Open up your serverless.yml
file and update the service name to opencage-geocoder
service: opencage-geocoder
Update the provider config in serverless.yml
Open up your serverless.yml
file and update the provider section with your Google Cloud Project id and the path to your keyfile
file. It should look something like this:
Like in the example above, feel free to use node platform version 8 instead of 6. Indeed, node 6 is getting old and big fans of async/await
will be pleased with the version 8.
Google Cloud function are not generally available, here the region
parameter is set to us-central1
.
Install dependencies
We will hide OpenCage Geocoder API Key and we will set it in an environment file, so we will use the dotenv
library, then the OpenCage API request will be held by the opencage-api-client
library
$ npm i -S dotenv opencage-api-client
Serverless helpers
Serverless comes will some useful plugins, We will use the environment generator file plugin. Then we can, with this plugin, generate an env file containing the OpenCage API Key. If you have different API Key for your different environments (development, staging, production), the plugin still help storing all the different value regarding the stage and deploying only the targeted stage value
$ npm i -D serverless-env-generator
Edit serverless.yml
file, adding this after provider:
section
Environment variable
Use the serverless env generator to create aenvironment.yml
file. This file will hold the OpenCage Geocoder API Key.
$ serverless env --attribute OCD_API_KEY --value <YOUR-OPEN-CAGE-API-KEY> --stage devServerless: Successfuly set OCD_API_KEY 🎉
Now generate a .env
file manually.
$ serverless env generateServerless: Creating .env file...
This operation is not needed when deploying, it will be done automatically by the serverless deployment process. For security reasons, the .env
file is removed after the deployment. I recommend, for the same reasons, to avoid to store these files into the repository.
Let’s code it
Open the index.js
file and remove its content. Replace it by :
We start using dotenv to import the API Key from the .env
file.
GCloud functions for NodeJS 8 uses the same interface as ExpressJS. Actually the runtime uses ExpressJS to handle the incoming requests.
The Input Query Parameters can be found in therequest.query
object.
To proxy the API Key, we first check if a key is part of the input query string. If not we add the one from the environment variable. And in case nothing was in input query parameters and the env var was not set, we return directly an 403 error.
We do not override the API Key, if one was in as an input parameter.
Then the query is sent to the OpenCage Geocoder API endpoint via the client library. The response is sent back as is.
Edit serverless handler
As we exported opencage
from our module, we have to specify it in the serverless yml file. opencage
will be the function name, geocode
is the handler and we will use geocode
for the path
Deploy
$ serverless deployServerless: Creating .env file...
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Removed .env file
Serverless: Compiling function "opencage"...
Serverless: Creating deployment...
Serverless: Checking deployment create progress...
..
Serverless: Done...
Serverless: Uploading artifacts...
Serverless: Artifacts successfully uploaded...
Serverless: Updating deployment...
Serverless: Checking deployment update progress...
..........
Serverless: Done...
Service Information
service: opencage-geocoder
project: opencage-123456
stage: dev
region: us-central1Deployed functions
opencage
https://us-central1-opencage-123456.cloudfunctions.net/geocode
The last line of the deployments gives us the HTTP endpoint.
Test
Now we can test our new endpoint with geocoding and reverse geocoding operations:
- Geocode
Piccadilly Circus London
$ curl --request GET \
--url "https://us-central1-opencage-123456.cloudfunctions.net/geocode?q=Piccadilly%20Circus%20London"
- Reverse Geocode
-22.6792, 14.5272
$ curl --request GET \
--url "https://us-central1-opencage-123456.cloudfunctions.net/geocode?q=-22.6792%2C+14.527"
To go further
If you look at the associated repository on Github, you will find some unit tests.
Cloud Functions are at the General Availability release level since the 24th of July 2018. But Node.js 8 is still in beta. And Cloud Functions are available only in the following regions for now:
us-central1
(Iowa)us-east1
(South Carolina)europe-west1
(Belgium)asia-northeast1
(Tokyo)
The end
I hope you enjoyed this tutorial. Feel free to reach me with whatever channel suits you for comments, issue, or coffee!
Links
- Serverless Google Cloud Functions Guide
- Github repository : https://github.com/tsamaya/gcloud-functions-opencage-geocoder
- The same type of tutorial with an AWS Lambda