Building GraphQL Servers with Subscriptions in Go
At Functional Foundry, we are very excited about GraphQL. Today, we’re releasing an open source library for implementing server-side subscriptions in Go using WebSockets.
GraphQL provides a flexible and efficient way to query data from servers. It is becoming a popular technology for designing backends, often replacing or wrapping somewhat inflexible REST APIs and putting clients in charge of deciding what data they need. There are a variety of libraries and frameworks out there for writing GraphQL clients and servers in JavaScript today, most notably Apollo and Graphcool. The Apollo team has also developed a protocol for GraphQL over WebSockets, which is primarily used for subscriptions in Apollo Client and Graphcool.
While JavaScript developers have all the tools they need to create GraphQL backends without friction, the Go ecosystem has so far been lacking support for GraphQL subscriptions. The excellent graphql-go project provides the two main building blocks for Go-based GraphQL servers: graphql-go/graphql (providing ways to parse and validate GraphQL schemas and documents, define GraphQL schemas and implementing field resolvers) and graphql-go/handler (providing a handler to serve a GraphQL schema over HTTP and handle incoming requests with queries and mutations). Together, both libraries provide almost everything developers need to stand up a GraphQL server. Apart from subscriptions.
Introducing graphqlws
Today, we’re open-sourcing a new Go library to fill this gap: graphqlws. It serves a simple purpose:
- implement the GraphQL over WebSocket protocol (used by all popular GraphQL clients) so you don’t have to,
- integrate seamlessly with net/http, and
- provide a simple way to access established subscriptions, perform authentication, and send updates to the corresponding clients.
You can find it on GitHub at https://github.com/functionalfoundry/graphqlws.
Step 1 — Basic Setup
Setting up a GraphQL over WebSocket endpoint with graphqlws is easy. Create a GraphQL schema, create a subscription manager, create an HTTP handler for the communication over WebSockets, then serve the handler using net/http. Optionally, you can define a function to authenticate users (the Apollo Client sends an optional authToken
along with the initial WebSocket message when establishing a new connection; this function allows to resolve the token string into a user).
Step 2 — Working With Subscriptions
The graphqlws library by itself merely implements the GraphQL over WebSocket protocol. It does not implement any subscriptions out of the box. A typical server implementation would listen to a database for changes and react to these changes by identifying which subscriptions need to be updated, re-executing the queries of these subscriptions and send the results to the corresponding subscription clients.
The following code example shows how subscriptions can be retrieved from the subscription manager at any point. They are grouped by their connections. Each connection has a unique ID and, optionally, the user as returned by the Authenticate
function described earlier.
Each subscription stores the subscription query (Query
, Variables
and OperationName
) as well as other information that can be useful to identify what kind of data the subscription is for (e.g. Fields
and Document
).
Using Query
, Variables
and OperationName
the query of a subscription can be re-executed whenever needed. The result can then be sent to the subscribing client via the SendData
method, as shown in the code example below.
Step 3 — Combine with graphql-go/handler
Using a GraphQL over WebSocket endpoint in combination with a regular GraphQL HTTP endpoint works just like with any other net/http
handlers. All you need to do is create two handlers and serve them via different routes. The following code example demonstrates this.
Summary
If you have made it this far, you are probably interested in using Go for your own GraphQL server. With graphqlws, server-side GraphQL subscriptions can now be implemented easily. Go ahead and give it a shot! We hope you like it.
Feedback is always welcome in the form of comments to this post or — even better — bug reports or enhancement requests on GitHub.
—
If you are looking for help with React or GraphQL development on your next project we’d love to hear from you at Functional Foundry.