Integrating OpenFaaS and GraphQL

Serverless, API Gateway, Lambda, and GraphQL is something I’ve been wanting to try out these days after watching Jared Short’s talk in Serverlessconf.

Getting inspired by this talk, I’ve came up with the architecture below.

Kong as the API Gateway and OpenFaaS to invoke GraphQL. Minio is there to serve static contents (like the SPA App itself). The problem was how I should integrate GraphQL with OpenFaaS. The core part of OpenFaaS functions is (IMO) the Watchdog.The function containers are listening at port 8080 and they transfer requests to the STDIN , then collects the STDOUT and converts it as the HTTP Response. You can further read about Watchdog here.

from the official docs

So, I can’t just spin up a graphql-express or apollo-server-express server because it will conflict with the watchdog. Of course, I can throw away Watchdog and listen on port 8080 with my own server but that will be against the OpenFaaS way (it isn’t supported).

What I’ve decided to do for now was to simply invoke the graphql-js raw library and see if it works. That means I won’t spin up any additional servers like express.

Starting with the faas-cli

OpenFaaS has a cli and there are many convenient features you can use. Let’s use the new command to create a skeleton for new functions. Below is an example.

faas-cli new --name=graphql --lang=node --gateway=http://path.to.your.gateway

There will be a few directories and files created but what you need to know for now is that you just implement what you want to inside graphql/handler.js . That’s the entry point of your function.

Implementing the function

What I want to do for now is quite simple — just see if graphql will response properly. So I’ve added graphql to my dependencies via yarn add graphql and implemented the following code.

import {
graphql,
execute
} from 'graphql';
import { StarWarsSchema } from './data/swapiSchema';
module.exports = (context: any, callback: any) => {
const body = JSON.parse(context);
graphql(StarWarsSchema, body.query).then(result => {
callback(undefined, result);
}).catch(err => callback(err, undefined));
}

The syntax will differ in what you use for JS coding — I’m using TypeScript. The StarWarsSchema is the sample schema probably everybody has seen in GraphQL sample codes. I’m just executing graphql and responding back with the results.

Deploy

All right, let’s deploy this function to the environment. You can do this via faas-cli but I wanted to use automated build so I’ve pushed the code here and built the image here.

deployment detail

Test with GraphiQL

Now that the function has gotten deployed, let’s test it out. I used the GraphiQL App for this. And as I invoked a query, it looked like this.

Not bad is it?

Looks nice. But there are things I haven’t been able to look at yet

  • auto completion in graphiql
  • mutations
  • performance

These are the things I’m going to dig into from here. And I’m hoping I can integrate with the apollo-server-core in some way.

I have so little time to look into these things so any kind of contribution would be highly appreciated!

By the way, I’m experimenting this in a Rancher environment like the following.

Looks like there are too many hops…. But the Rancher Load Balancer is so easy to use from the UI (and integrating with LetsEncrypt). I’m pretty excited how this is going to turn out to be.