I’ve been using restclient
for quite some time now, but it wasn’t until a couple of months ago I got annoyed enough to find its variable and scripting support. To showcase my findings I’ve put together a small example of accessing the GitHub GraphQL API using the graphql
package. This is only a sample, and for proper GitHub interaction it would be better to use the ghub
package.
The most basic assignment using plain =
operator:
:graphql-url = https://api.github.com/graphql
Replacing the =
operator with :=
evaluates the right hand side as elisp:
:github-token := (auth-source-pass-get "token" "web/github")
This also showcases accessing extra data in the password store pass
, via auth-password-store
. The content of web/github
would be something like:
$ pass web/github
s1kr1ttp4zzw0rd
token: b0baf377b0baf377b0baf377b0baf377b0baf377
Multi-line support via <<
, and referring to other variables:
:headers = <<
Authorization: Bearer :github-token
User-Agent: Emacs
#
…and for scripting by combining the :=
and <<
operators:
:query-repos := <<
(graphql-query
((viewer
(repositories
:arguments
((first . 3)
(orderBy . ((direction . DESC)
(field . UPDATED_AT))))
(nodes
name
pushedAt)))))
#
Finally the actual HTTP call, using the variables now assigned:
POST :graphql-url
:headers
{ "query": ":query-repos"}
Executing the following via C-c +
v will result in:
As seen by the screenshot, the elisp sections are highlighted correctly. This performed by the polymode
package which enables embedding of multiple major modes within the same buffer. While configuring this for restclient
I found a couple of bugs, and within a day of interacting with the maintainer the issues got resolved - so it seems like a good package to depend on.
The definition for the elisp sections within restclient
buffers is as follows:
(define-hostmode pm/restclient-hostmode
:mode 'restclient-mode)
(define-innermode pm/restclient-innermode
:mode 'emacs-lisp-mode
:head-mode 'host
:tail-mode 'host)
(define-innermode pm/restclient-single-innermode pm/restclient-innermode
:head-matcher "^:[^ ]+ :="
:tail-matcher "\n")
(define-innermode pm/restclient-multi-innermode pm/restclient-innermode
:head-matcher "^:[^ ]+ := <<\n"
:tail-matcher "^#\n")
(define-polymode pm/restclient-mode
:hostmode 'pm/restclient-hostmode
:innermodes '(pm/restclient-single-innermode
pm/restclient-multi-innermode))
Another useful package is company-restclient
which, thanks to know-your-http-well
, adds completion for pretty much everything that goes into a HTTP header.