Killring

Rick Dillon's Weblog

Effective restclient in Emacs

restclient is a major mode for Emacs that provides a simple, clear DSL for making REST API client requests and viewing the responses. I’ve found it very useful both when developing and testing API code, as well as when building clients that consume other APIs. It has numerous advantages over products like Postman since it uses clear syntax, can be operated entirely without a mouse, and is based purely on text, so it can be version controlled along with a project to document API call formats. I’m going to share a couple of tricks with restclient that make it even more useful as you make greater use of it.

Getting Started

A typical restclient file might look like this:

# -*- restclient -*-
:query = Emacs

# Emacs extract on Wikipedia
GET https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=:query

# Duck Duck Go 'instant answer' search for Emacs
GET http://api.duckduckgo.com/?format=json&q=:query

On the first line, you can see that we define a variable query that can be used in subsequent calls. This is useful to store API keys and auth tokens, as well as queries that you want to uses across multiple calls (like resource IDs).

Scaling Up

Above we define a couple of calls, but if you develop or test APIs extensively, you might find that you have dozens or even hundreds of such lines in your restclient file. Using tools like helm-occur, you can dynamically filter content based on either the URL or the title you’ve marked with request with. Then, you might find yourself even breaking your requests up into multiple files, placing them into a dedicated directory.

Another way to address this problem is by organizing all the requests into a heirarchy in a single file, like an outline. This type of functionality is offered by both outline-mode and org-mode, but both are major modes, which would replace restclient-mode, rather than augment it.

Luckily both modes also have minor modes as well. I’ve never been able to get orgstruct mode to work with restclient, but outline-minor-mode works just fine, with a bit of configuration.

Outlining restclient files

If we want this to work correctly, we can’t just enable restclient-mode when the file is opened. We actually need to do three things:

  1. Enable restclient-mode
  2. Set the outline-regexp to recognize restclient comments
  3. Enable outline-minor-mode

So, we trade in the compact local variable syntax at the top of the file (# -*- restclient -*-) for more capable (and verbose) local variables at the bottom:

# Local Variables:
# mode: restclient
# outline-regexp: "#+"
# eval: (outline-minor-mode)
# End:

So now, our file looks like this:

:query = Emacs

# Emacs extract on  Wikipedia
GET https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=:query

# Duck Duck Go 'instant answer' search for Emacs
GET http://api.duckduckgo.com/?format=json&q=:query

# Local Variables:
# mode: restclient
# outline-regexp: "#+"
# eval: (outline-minor-mode)
# End:

Now you can use C-c @ C-t to hide all the queries, but retain their descriptions. C-c @ C-a shows everything again. You can also nest calls under headings to organize things:

# Wikipedia API calls

## Emacs extract on Wikipedia
GET https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=emacs

## Lisp extract on Wikipedia
GET https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=lisp

# Duck Duck Go API calls

## Duck Duck Go 'instant answer' search for Emacs
GET http://api.duckduckgo.com/?format=json&q=emacs

These will fold and nest properly, because the outlining logic nests lines more deeply in the hierarchy the longer the match. In short, that means the more # characters you add, the deeper the nesting is.

A Bit of Magic

The default outline minor mode bindings can be a bit tough, but outline-magic provides a new command, outline-cycle, that we can bind to the outline-minor-mode-map. I assume you’ve got Melpa wired up to your package-archives. Here goes:

M-x package install <ret> outline-magic
(eval-after-load 'outline
  '(progn
    (require 'outline-magic)
    (define-key outline-minor-mode-map (kbd "<C-tab>") 'outline-cycle)))

If you already have restclient buffer open, just M-x revert-buffer to try out your new system for organizing restclient calls.