Test, Save, and Execute HTTP Requests with Hurl (or restclient.el)

So I’ve used restclient.el in the past to embed HTTP requests in readmes and other kinds of documentation to test login flows and APIs as I’ve been writing the corresponding servers.

But chances are you can’t use that package since you don’t use Emacs.

I found a command-line replacement – no thanks to my web searches, but thanks to alternativeto.net listings of httpie of all things.

My problem with cURL, Httpie, netcat, etc. for this is that you need to specify the host name as a command line argument. That makes sense to pipe HTTP responses into the next request from the terminal, but it doesn’t work well to tell a program to “please execute this self-contained HTTP request”.

Hurl to the rescue. Ignoring the unfortunate name, Hurl is, of course, written in Rust. It wraps libcurl and offers standard input and file-based processing of HTTP requests like so:

$ echo "GET https://example.com" | hurl 

Their Hurl file format does far more than I need for complex workflows. But it also does the simple things, i.e. single requests with payloads.

# Get home:
GET https://example.org
HTTP 200
[Captures]
csrf_token: xpath "string(//meta[@name='_csrf_token']/@content)"


# Do login!
POST https://example.org/login?user=toto&password=1234
X-CSRF-TOKEN: {{csrf_token}}
HTTP 302

This example demonstrates how you can parse the response and capture parts of it – be it JSON, plain text, or in this case HTML to grep the CSRF token. Check out the samples page for inspiration.


Soooo …. if you happen to use md-babel (which I haven’t formally announced, yet!), and execute this httpbin.org request, say from the Markdown document of this very blog post:

POST https://httpbin.org/post
Content-Type: application/json
{ "test":"foo","bar":"baz" }

… then you get this result inserted for you right below:

{
  "args": {}, 
  "data": "{ \"test\":\"foo\",\"bar\":\"baz\" }", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "28", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "hurl/6.1.1", 
    "X-Amzn-Trace-Id": "Root=1-680093bf-142169f93e6208ec096d1024"
  }, 
  "json": {
    "bar": "baz", 
    "test": "foo"
  }, 
  "origin": "79.221.187.120", 
  "url": "https://httpbin.org/post"
}

That’s pretty cool and I’m going to be using that in the future to test my APIs in a way that non-Emacs-users can also enjoy, using hurl, Markdown, and md-babel.