Riposte

Scripting language for JSON HTTP APIs

Riposte is a scripting language for writing integration tests for JSON-based HTTP APIs. With it, you can direct a headless browser and test complex scenarios for your HTTP API.

The intended use case is a JSON-based HTTP API. It comes with a commandline tool, riposte, which executes Riposte scripts. Using Riposte, one writes a sequence of commands—which amount to HTTP requests—and assertions, which require that the response meets certain conditions.

What it looks like

Here’s an example. Imagine you’ve got an ecommerce shop that can be reached with an API. Your shop has a catalog from which visitors can select products and add them to their cart.

# set a header, to be added to all
# requests going forward
^Content-Type := "application/json"

# set a base URL; all URIs going forward
# will be merged with this one:
%base := https://api.example.com/v1/

$uuid := @UUID # access an env variable

# ----------------------
# Start sending requests
# ----------------------
GET checkout/cart/{uuid}
  responds with 2XX
  and satisfies schema in cart.json

Riposte builds on URI Template to express URIs. Here, we plug in the value of the uuid variable, whose value came from the environment. (The 2XX there means: we expect a 200-class response. The precise response code doesn’t matter.) We also check that the response we receive adheres to a JSON Schema stored in the cart.json file.

Let’s keep going:

# --------------------------
# Add something to the cart:
# --------------------------

$productId := 41966
$qty := 5

$payload := {
  "product_id": $productId,
  "qty": $qty # comments in JSON!
}

POST $payload checkout/cart/{uuid}
  responds with 200

# here's some JSON Pointer, referring to
# the body of the request we (hopefully)
# just received:
$itemId := /items/0/item_id # extract ID

Here, we define some data and build a JSON object with three properties. We then submit that to https://api.example.com/v1/checkout/cart/abcd. (abcd is not a well-formed UUID, of course. But I hope you understand.) In this assertion, we use a specific response code (200) rather than a pattern (2XX).

We also extract data from the response. Riposte builds on JSON Pointer, which is an IETF standard notation for referring to parts of JSON documents.

GET checkout/cart responds with 2XX

/price exists

After making a request, you can make assertions about it. Here, with exists, we’re asserting that (1) the response is a JSON object, and (2) it has a property, price. We don’t care what that value is. (Riposte comes with a ton of assertions; exists is just one.)

Here’s another Riposte script that logs in to an API by POSTing credentials (a JSON array) to a certain endpoint, which is supposed to give us back a datum that we will attach to all later requests:

$login := { # we store sensitive data
  "email": @EMAIL, # as environment
  "password": @PASSWORD # variables
}

POST $login auth/login responds with 2XX

# Extract a value from the response body
# and use it as the value of an HTTP header
# going forward
^Apikey := /key

That’s Riposte. It’s a language for testing JSON-based HTTP APIs. There’s lots more than this, but this should give you a sense of what the language looks like and what it can be used for.

Obtaining it

Riposte is implemented in Racket and is available as a Racket package. Riposte is intended to be used at the command line. Once you’ve installed Racket, install it on the command line like this:

raco pkg install riposte

(You’ll be prompted to install some additional packages on which Riposte, as a Racket program, depends.)

Running it

To run Riposte at the command line, just do

riposte let-er-rip.rip

Code

Riposte lives on GitHub. You’re welcome to submit problems, or feature requests, using GitHub Issues.