100 Days of Learning: Day 3 – Calling another API from our OpenFaaS function

Photo by NASA on Unsplash

Here is my Log book

Invoking the function directly

Building on from the previous days. What might not have been obvious at first is that you can invoke the function by talking directly to the API end point and not needing to use faas-cli invoke

$ curl --data-binary '{"key":"value"}' --header "Content-Type: application/json"

Warm up for tonight – JSON prettifier

I am going to see if I can modify the helloworld function to take JSON as input and prettify it.

But first I will test out the code in the Python REPL

$ python
>>> import json
>>> req = '{"z": 1, "a": 2, "c": 3, "b": 4}'
>>> data = json.loads(req)
>>> response = json.dumps(data, indent=4, sort_keys=True)
>>> response
'{\n    "a": 2, \n    "b": 4, \n    "c": 3, \n    "z": 1\n}'

Ok that worked so next I need to modify the [handler.py](http://handler.py) file. Disclaimer: I am not worried about error handling or any of the production coding here.

import json

def handle(req):
    data = json.loads(req)
    response = json.dumps(data, indent=4, sort_keys=True)
    return response

Rebuild and redeploy with faas-cli

$ faas-cli up -f helloworld.yml
Deployed. 200 OK.

Verify by throwing some JSON at it

$ curl --data-binary '{"z": 1, "a": 2, "c": 3, "b": 4}' --header "Content-Type: application/json"
    "a": 2,
    "b": 4,
    "c": 3,
    "z": 1

Nice one! I also checked Docker Hub and indeed there is only 1 image that has been updated.

Lets write a function that calls a 3rd party API

For this I am going to be following the example from Serverless for Everyone Else that uses Node.js.

Which API to call? In the book Alex uses http://open-notify.org to get the number of Astronauts currently in space. I will be using their API that gives the geolocation of where the International Space Station is.

See "International Space Station Current Location" for more information on the API as well as a Python example.

International Space Station Location

Create a new function from the node12 template

╭ ~/Learning/faasd                                                            [20:23:45]
╰ $ faas-cli new --lang node12 iss-location

Whoops! I forgot to first create a directory in which to create the files, so now the files are mixed with my other function.

$ mkdir temp
$ mv iss* temp
$ mv template temp
$ mv temp iss-location
$ ls
helloworld/   iss-location/ password.txt
$ cd iss-location

Time to write some code $ mate iss-location/handler.js (I love TextMate, been my text editor on mac for probably 10 years). Note: I am not proficient in JS or node.

'use strict'

const axios = require("axios")

module.exports = async (event, context) => {
	let issResponse = await axios.get("http://api.open-notify.org/iss-now.json")
	let body = {"lat": issResponse.data.iss_position.latitude,
		"long": issResponse.data.iss_position.longitude
	return context
		.headers({"Content-type": "application/json"})

Need to install axios package first.

$ npm install --save axios

Build and deploy the function.

$ faas-cli up -f iss-location.yml
Deployed. 200 OK.

I tried to curl the end point and nothing. I checked the UI and it says "not ready". Ok so something is wrong (and I bet my code is wrong).

$ faas-cli describe iss-location
Name:                iss-location
Status:              Not Ready
Replicas:            0
Available replicas:  0
Invocations:         1
Function process:    node index.js

It says that the status = Not Ready and also the Replicas = 0 (whereas my other functions = 1)

$ curl -i
HTTP/1.1 500 Internal Server Error
Content-Length: 0
Content-Type: text/plain
Date: Thu, 11 Mar 2021 20:58:45 GMT
X-Call-Id: 50fb978e-160f-4f5e-824e-f5bcd4db5100
X-Duration-Seconds: 0.000556
X-Start-Time: 1615496325470597568

Learning action point: I do wonder how can you get to error logs or something when things go wrong on the webserver / multipass instance? At the moment the debugging is, poke something and see if it works.

Ok I have narrowed it down to node not being happy about the line: const axios = require("axios") which means it can’t find the node package. Watching Alex’s workshop video I can see that I was suppose to install axios inside the directory where the handler.js file is.

╭ ~/Learning/faasd/iss-location/iss-location                                             [21:09:59]
╰ $ ls
handler.js         node_modules/      package-lock.json  package.json

$ faas-cli describe iss-location
Name:                iss-location
Status:              Ready
Replicas:            1

Bingo! Ok time to put all the code back like I wrote it earlier in this post and then faas-cli up again.

Moment of truth

$ faas-cli up -f iss-location.yml
$ curl

Woo hoo!