#scriptable #api-testing #http-api #api #javascript #http-request #http

bin+lib dothttp

dothttp is a text-based scriptable HTTP client. It is a fork for dot-http. It is a simple language that resembles the actual HTTP protocol but with additional features to make it practical for someone who builds and tests APIs.

7 releases (breaking)

0.9.0 Feb 26, 2024
0.8.1 Feb 26, 2024
0.7.0 Nov 29, 2023
0.6.0 Nov 9, 2023
0.4.1 Oct 28, 2023

#70 in HTTP client

Download history 141/week @ 2024-02-19 301/week @ 2024-02-26 3/week @ 2024-03-04 2/week @ 2024-03-11 142/week @ 2024-04-01

144 downloads per month

Apache-2.0

130KB
3.5K SLoC

This is a fork of existing tool dot-http

dothttp

codecov Crates.io build nix

dothttp is a text-based scriptable HTTP client. It is a simple language that resembles the actual HTTP protocol but with just a smidgen of magic to make it more practical for someone who builds and tests APIs.

The difference from dot-http is that dothttp aims to provide full compatability with IntelliJ Http Client.

Current list of feature support:

  • Environment Files
  • Variables
  • Special variables: $random, $timestamp and $isoTimestamp
  • Response handlers
  • Response unit tests
  • Posting request bodies from files
  • Pre-request scripts
  • Pre-request variables block
  • Cookies
  • gRPC requests
  • WebSocket requests
  • GraphQL

Things to consider

  • terminal UI with ratatui
  • stress test support

Installation

Binary releases

The easiest way for most users is simply to download the prebuilt binaries. You can find binaries for various platforms on the release page.

Cargo

First, install cargo. Then:

$ cargo install dothttp

You will need to use the stable release for this to work; if in doubt run

rustup run stable cargo install dothttp

Nix

You can also use nix (with flakes) to run and use dothttp:

$ nix run github:alisa101rs/dothttp

Usage

See dothttp --help for usage.

The request

The request format is intended to resemble HTTP as close as possible. HTTP was initially designed to be human-readable and simple, so why not use that?

simple.http

GET http://httpbin.org
Accept: */*

Executing that script just prints the response to stdout:

$ dothttp simple.http
GET http://httpbin.org/get

HTTP/1.1 200 OK
access-control-allow-credentials: true
access-control-allow-origin: *
content-type: application/json
date: Sat, 18 Jan 2020 20:48:50 GMT
referrer-policy: no-referrer-when-downgrade
server: nginx
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block
content-length: 170
connection: keep-alive

{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin.org"
  },
  "url": "https://httpbin.org/get"
}

Variables

Use variables to build the scripts dynamically, either pulling data from your environment file or from a previous request's response handler.

simple_with_variables.http

POST http://httpbin.org/post
Accept: */*
X-Auth-Token: {{token}}

{
    "id": {{env_id}}
}

http-client.env.json

{
    "dev": {
        "env_id": 42,
        "token": "SuperSecretToken"
    }
}

Note that the variables are replaced by their values

$ dothttp simple_with_variables.http
POST http://httpbin.org/post

HTTP/1.1 200 OK
access-control-allow-credentials: true
access-control-allow-origin: *
content-type: application/json
date: Sat, 18 Jan 2020 20:55:24 GMT
referrer-policy: no-referrer-when-downgrade
server: nginx
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block
content-length: 342
connection: keep-alive

{
  "args": {},
  "data": "{\r\n    \"id\": 42\r\n}",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Content-Length": "18",
    "Host": "httpbin.org",
    "X-Auth-Token": "SuperSecretToken"
  },
  "json": {
    "id": 42
  },
  "url": "https://httpbin.org/post"
}

Environment file

Use an environment file to control what initial values variables have

http-client.env.json

{
    "dev": {
        "host": localhost,
        "token": "SuperSecretToken"
    },
    "prod": {
        "host": example.com,
        "token": "ProductionToken"
    }
}

env_demo.http

GET http://{{host}}
X-Auth-Token: {{token}}

Specifying different environments when invoking the command results in different values for the variables in the script

$ dothttp -e dev env_demo.http
GET http://localhost
X-Auth-Token: SuperSecretToken

$ dothttp -e prod env_demo.htp
GET http://example.com
X-Auth-Token: ProductionToken

Response handler

Use previous requests to populate some of the data in future requests

response_handler.http

POST http://httpbin.org/post
Content-Type: application/json

{
    "token": "sometoken",
    "id": 237
}

> {%
   client.global.set('auth_token', response.body.json.token);
   client.global.set('some_id', response.body.json.id);
%}

###

PUT http://httpbin.org/put
X-Auth-Token: {{auth_token}}

{
    "id": {{some_id}}
}

Data from a previous request

$ dothttp test.http
POST http://httpbin.org/post

HTTP/1.1 200 OK
access-control-allow-credentials: true
access-control-allow-origin: *
content-type: application/json
date: Sat, 18 Jan 2020 21:01:59 GMT
referrer-policy: no-referrer-when-downgrade
server: nginx
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block
content-length: 404
connection: keep-alive

{
  "args": {},
  "data": "{\r\n    \"token\": \"sometoken\",\r\n    \"id\": 237\r\n}",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Content-Length": "46",
    "Content-Type": "application/json",
    "Host": "httpbin.org"
  },
  "json": {
    "id": 237,
    "token": "sometoken"
  },
  "url": "https://httpbin.org/post"
}

Contributing

Contributions and suggestions are very welcome!

Please create an issue before submitting a PR, PRs will only be accepted if they reference an existing issue. If you have a suggested change please create an issue first so that we can discuss it.

License

Apache License 2.0

Dependencies

~33–48MB
~716K SLoC