blog.mmalecki.com

http-console2 0.9 - a friendly REPL-based HTTP API explorer

21 Jan 2020

During the past few months I’ve been working on some projects that use OpenAPI to describe their HTTP interfaces. As such, I had the chance to play with the Swagger UI a lot. While I found it to be an amazing tool to experiment around with an API, one thing bugged me - I spend lots of my time in terminal, and Swagger UI is a browser app.

After some time of trying to find an existing tool, my mind turned to http-console2 - my fork of Alexis Sellier’s http-console. While it desperately needed a refactor, its interface seemed to be a prime candidate for extension with features that turn it into a full-fledged API explorer.

So, a couple of days later:

I am very pleased to announce a brand new http-console2, now supporting:

Feature highlights

These are the features I’m most excited about.

Multiline JSON bodies

Editing single line JSON can get very tiring, very fast. Hence, this:

Handling multiline JSON bodies

OpenAPI-based autocompletion

If the API you’re chatting with supports OpenAPI, http-console2 can now discover its specification and autocomplete based on it.

To enable OpenAPI support, launch http-console2 with the --openapi switch (and --json, when appropriate). For example, while interacting with Kubernetes API:

OpenAPI autocompletion while interacting with Kubernetes API

Per-origin command and request body histories

http-console2 now supports origin-specific command and body history. This means that if you press arrow-up when talking to http://127.0.0.1:1337, you won’t receive history suggestions from your session with http://127.0.0.1:7331.

You can, however, configure http-console2 to share histories you would like to share. This is especially helpful when you regularly connect to different servers that speak the same protocol, for example your local development server, and a remote development server:

$ http-console2 --history rabbits-dev 127.0.0.1:8000
...
$ http-console2 --history rabbits-dev https://api.dev.rabbitshq.com
# http-console2 will propose commands from your session with 127.0.0.1:8000 here.
...

Contexts

This is probably my second favorite feature in this release, right after the OpenAPI-based autocompletion, simply due to how often I need to talk to several versions of the same service, running in different environments.

Contexts are a way for http-console2 to deduce some common settings based on the URL you’re talking to. To reuse the local and remote development server example, you can place the following in ~/.http-console2/contexts.json in order to implicitly configure http-console2 with --openapi --json --history rabbits when you run http-console http://127.0.0.1:8000 or http-console https://api.dev.rabbitshq.com.

{
  "rabbits": {
    "urls": ["http://127.0.0.1:8000", "https://api.dev.rabbitshq.com"],
    "openapi": true,
    "json": true,
    "history": "rabbits-dev"
  }
}

Installing

Sounds interesting?

Give it a whirl!

npm install -g http-console2
http-console <url>

The refactor

This is a deeper dive into the refactor and some of the technical decisions made along the way. Feel free to jump straight to conclusions.

Work organization

I’ve started this refactor knowing clearly what I wanted to achieve:

  • basic UX same as http-console
  • but with more “API explorer” flavor
  • and OpenAPI support

Based on those I made a plan - funemployment rendered me with lots of time on my hands, and I was going to do my best to not let feature-creep creep me out of this refactor.

Looking back, I’m very happy with the scope I’ve set, and with the outcome that realizing this scope had brought.

Refresh

The first step was to refresh the ~9 year old codebase (I haven’t been the best maintainer).

I’ve been on a binge of trying out different new node.js HTTP clients, and I decided to use got for this project (instead of the core http module, as the original http-console does). That turned out to be a huge time saver, and I came to enjoy its API very much.

I also migrated from using the readline module to the repl module. It felt more appropriate, and gave us a couple of features for free (like REPL commands, or easy acceptance of multiline JSON bodies).

Autocompletion

I wanted to accomplish both URL and request body autocompletion, based on both history and OpenAPI spec, if available.

Setting up the barebones turned out to be easy, thanks to the the repl.start’s completer parameter. Providing request body completion proved to be more tricky. It involved setting up stream-json so that it extracts the current JSON path user is typing at the time of end of input, and flattening OpenAPI schemas into something less complex, and easy to pick at from the completer’s perspective.

Overall, this was the most challanging, but also the most fun part of this project.

An interesting fact I learned along the way was that Kubernetes’ API specification has cycles in it.

Conclusions

I am very happy with the 0.9 release. It satisfies all the requirements I had for it, and is already proving to be very useful. Additionally, I had a lot of fun writing it, as I enjoy writing developer tools.

Plans for the next version

My plans for the next release are to make this a, well, more effective REPL. I’d like to be able to run crude operations on the data returned - pick at them (preferably with JSONPath/jq/etc. style path expressions), feed them to next operations, write them to files, etc.

I also intend to make the OpenAPI completion smarter, give it an understanding of arrays and a way to preview the schema - perhaps by double-pressing Tab when having a fully completed URL.

Thank you for reading, and stay tuned for updated!