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.
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.
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.