8 releases (breaking)
0.8.0 | May 10, 2024 |
---|---|
0.7.1 | Apr 22, 2024 |
0.5.0 | Feb 19, 2024 |
0.4.0 | Feb 2, 2024 |
0.1.0 | Dec 31, 2023 |
#205 in HTTP client
105KB
3K
SLoC
HITMAN
A command line tool for hitting API endpoints.
Basic setup
Create your project folder, containing a TOML config file, and HTTP request files for each API you want to hit.
Example layout:
project
├── hitman.toml
├── login.http
├── apple/get_apples.http
├── apple/post_new_apple.http
├── apple/delete_apple.http
The HTTP files are templates for literal HTTP requests. Variables in double curly braces will be substituted with values from the config file.
POST {{base_url}}/login HTTP/1.1
Content-Type: application/json
{
"username": "{{api_username}}",
"password": "{{api_password}}"
}
The configuration file can contain global default variables, and target specific variables. It must contain at least one target, as a TOML table:
api_username = "admin"
[default]
base_url = "http://example.com"
[development]
base_url = "http://localhost:8080"
In addition to the main configuration file hitman.toml
, there can be another
called hitman.local.toml
. The recommended setup, is to have a hitman.toml
in a shared repository, and have a git ignored hitman.local.toml
where each
team member can have their personal credentials and such.
Substitutions can be nested, so that variables can contain references to other variables. For example:
authorization_header: "Authorization: Bearer {{auth_token}}"
Be careful, since there is currently no protection against cyclic references,
something like foo: "{{foo}}"
will likely overflow and crash.
Running
First, select which target to use:
$ hitman --select
? Select target ›
default
development
Then run requests directly by passing a request file:
$ hitman login.http
Or, use the interactive mode:
$ hitman
? Make request ›
login.http
apple/get_apples.http
apple/post_new_apple.http
apple/delete_apple.http
Capturing responses
The core concept of HITMAN is to extract values from responses, so that they can be referred to in templates, and substituted in subsequent requests.
A typical use-case, is to capture a token from a login response, and use it in the authorization header in subsequent requests:
We can define how values are to be extracted in the main config file, but more
typically, we can define them specific to one request. We add request-specific
configuration by creating a file with the same name as the request file, with
.http.toml
extension.
The _extract
section defines which values are to be extracted from the
response, as JSON-path expressions.
# login.http.toml
[_extract]
access_token = "$.result.access_token"
refresh_token = "$.result.refresh_token"
When receiving a successful login response, these values are extracted, and saved as configuration variables, which can be used in other requests:
GET {{base_url}}/apple HTTP/1.1
Authorization: Bearer {{access_token}}
Fallback values
A variable expression can have a default value, denoted by a pipe character:
{{user_id | 1000}}
.
When executing this request, if there is no value for user_id
in scope,
hitman will use the fallback value, dependig on how it was invoked.
By default, hitman will ask the user to input a value. The prompt will show to the user that there is a default value, which will be used if the user simple hits Enter, instead of the empty string.
When run in a non-interactive mode (-n
, --flurry
etc), the fallback value
will be used without prompting the user, unless a value is specified in the
config, or given on the command line.
List value selection
It's possible to specify multiple values for a variable in the config file, as a TOML array. By default, hitman will prompt the user to select a value from a menu, using arrow keys or fuzzy search.
Each value in the array can be specified as a simple scalar value (string,
number etc), or each can be given as a table containing a name
and value
.
The name
will be shown to the user for selection, and value
will be
inserted into the request. A typical use-case for this, is when an API uses
numerical IDs, which are inconvenient for selection.
Lists of substitution values can also be extracted from responses. Consider an
API that has an end-point like GET /apples
and GET /apple/{{apple_id}}
. To
be able to call the second end-point, we can set up the first to extract a list
of all available ID's. The syntax for this extraction is as follows:
[_extract]
apple_id = { _ = "$", name = "$.name", value = "$.id" }
There are three JSON-path expressions. The key _
specifies how to extract the
list from the response. It's assumed to point to a JSON array. In this case,
the symbol $
simply means that the whole response should contain and array.
In other cases, we might need something like $.items
, $.data
etc.
The other JSON-paths, name
and value
refer to data within each object of
the array.
Flurry rush attack
It's possible to use hitman for simple performance/stress testing an API. This
is done by giving --flurry N
on the command line, where N
is the number of
requests to send. In this mode, interactive prompts are currently not
supported, so it can only be used when all substitutions are available in
scope, have fallback values, or are given on the command line.
By default, it uses 10 parallel connections to execute N
requests as quickly
as possible. It's possible to specify the number of connections with the
--connections
option. For instance, --flurry 100 --connections 100
will try
to send all 100 requests in parallel.
Watch mode
There is a --watch
option that will keep hitman watching for file changes,
and re-execute the same request every time a file is changed. The http
request file itself, and the different config files are all watched for
changes.
Currently, the 'data' file that is updated when hitman extracts variables from requests, is not watched, because it might create infinite loops.
Dependencies
~20–37MB
~533K SLoC