Creating a Go client for Drupal
At Pronovix, we have a daily scrum blog. I don’t really like going to a separate webpage to write about the work I do at the given day. That’s why I decided to bring this closer to where I work: the command line.
Creating a Go client for Drupal isn’t particularly hard to do, but there are a few pitfalls you can walk into. In this blogpost, I walk you through a simple client, that can update nodes on a Drupal site. This is an almost complete library, you can either integrate it to an existing software or write a little boilerplate code around it to be a complete program (a command line tool for example). The code below can be used well in REST clients that need to communicate with Drupal.
For the Drupal part, you will need to download the services and the libraries module. Go to Drupal's module admin page and enable the services, session authentication and the rest server module. Under Structure->Services create a new REST endpoint to the path "api". Enable the retrieve/create/update/delete CRUD operations for the node resource and the login/logout actions for the user resource.
The Drupal part is done. Open up your favourite editor and start working on the Go part.
First you probably want to log in to the Drupal site. You will need the credentials of a sufficiently priviliged user, once you obtain them (e.g. by requesting them) you will need to store them somewhere secure, like the keychain under Mac OS X.
You will communicate with Drupal using GET and POST requests. Let's write wrapper functions for them:
These are very simple helper methods. The get() function does not need to check for cookies, because it will always get one. Only one post() call is needed to log in, where the cookie parameter will be nil.
Drupal is written in PHP, a dynamic/weak typed language (you don't have to define types or structs), but Go is strong/static typed, that means you have to define structures before you want to use them. Let's define a structure for the data we want to extract from Drupal's response for the login request.
With the json metadata, it's very easy to tell the json encoder how the json data structure should be translated into the custom made structure.
Let's proceed to the login function.
I introduced a small utility function called getBody(). This extracts the body from a http response.
Let's advance to the next step, retrieving the node itself.
This step requires two new types to hold the node body.
Defining the json structure names is not necessary here, because it's named the same way.
Let's write a function that retrieves the node body.
This is also quite simple. The json decoder will only decode the properties the program needs.
To update the node body, the best way is to open up some kind of editor. In a web app, it's easy to generate a form for that. However, opening an editor in a command line environment is a bit trickier, so I will show you how to do it.
A few things to note here. Firstly, it's important to close the tmp file before the editor opens it. Secondly, it's very important to connect the input and output streams of the editor process with the ones of the operating system. Not doing so will cause command line based editors, such as vim or nano fail to open. It's always a good thing to clean up, and not leave stray temporary files on the hard drive.
Let's put together the update function.
It's that simple. The "und" key represents the LANGUAGE_NONE constant for Drupal. If you want to use this method to post data to a multilingual Drupal site, you want to add Node.Language instead of the hardcoded string. Also if you have other required fields, you should add data for them, too.
I hope this walkthrough clearly shows, what a good pairing building RESTful web services in Drupal and writing web service clients in Go can be.