Artillery Probe, a Swiss army knife for testing HTTP
Introducing Artillery Probe
Say hello to artillery probe
, a Swiss army knife for testing HTTP. A smart and user-friendly HTTP client for the
terminal which shows request performance waterfalls, and lets you set up expectations/checks on responses for
quick-n-easy automated testing.
Think of it as curl
with better UX for common use-cases, and a couple of extra powers.
Features
- Send HTTP requests from the command line. 📺 Use any HTTP method (GET, POST, PUT etc). With HTTP/2 support.
- Send JSON or arbitrary request bodies, custom headers, forms, file uploads, query strings, Basic Auth etc.
- See response headers and bodies with syntax highlighting & pretty-printing 🌈
- See request performance waterfalls 〰〰 (inspired by reorx/httpstat)
- Built-in support for JSON querying with the same syntax as AWS and Azure CLIs (via JMESPath). You may not need
jq
at all! - Set expectations & checks for easy acceptance testing (testing locally, or for continuous verification and post-deployment checks in CI/CD) 🔁
- These are powered by the official
expect
plugin under the hood
- These are powered by the official
Let’s look at some examples
Probe an URL quickly
Start with something simple - just give probe
an URL. (if protocol is omitted, it will default to HTTPS, it’s 2022)
artillery probe www.artillery.io
Et voilá, we can see response headers, and a waterfall chart.
Connected to https://www.artillery.io (76.76.21.61)
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
connection: keep-alive
x-matched-path: /
cache-control: public, max-age=0, must-revalidate
content-length: 275503
publishedAt: Fri, 29 Apr 2022 21:40:51 GMT
x-powered-by: Next.js
etag: "4342f-g4C79gzSagz298qfv0rAclmRmks"
x-vercel-cache: STALE
age: 90
server: Vercel
x-vercel-id: dub1::iad1::7szlw-1651268541693-cce911e1815d
strict-transport-security: max-age=63072000
DNS Lookup | TCP Connection | SSL Handshake | Time to First Byte | Content Transfer
56ms | 14ms | 19ms | 181ms | 88ms |
| | | | |
56ms | | | |
70ms | | |
89ms | |
270ms |
total:358ms
Body stored in: /var/folders/yd/nyh8vtm17w92h5hm4pdhs8j00000gn/T/2022329-40081-18t3wn9.8m17l.html
Response body is saved to a file by default in case you want to look at it, with the right extension for the MIME type.
:::info
Pro-tip! artillery probe
may also be called as artillery http
.
You can go one step further and pop something like this into your shell config:
alias http='artillery http'
Which will let you run just http www.artillery.io
for example. The rest of our examples will use just http
alias for brevity.
:::
See response bodies
To display response body in line just add a -b
to the command. We’ll use another URL for this example, which returns some data about movies as JSON:
http http://lab.artillery.io/movies -b
The output will be similar to that above, but we will see color-highlighted JSON body too:
[
{
"id": 1,
"releaseDate": "Dec 18 1985",
"director": "Terry Gilliam",
"title": "Brazil",
"genre": "Black Comedy",
"imdbRating": 8,
"runningTimeMin": 136
},
{
"id": 2,
"releaseDate": "Feb 16 1996",
"director": "Harold Becker",
"title": "City Hall",
"genre": "Drama",
"imdbRating": 6.1,
"runningTimeMin": 111
},
{
"id": 3,
"releaseDate": "Jul 12 1996",
"director": "Edward Zwick",
"title": "Courage Under Fire",
"genre": "Drama",
"imdbRating": 6.6,
"runningTimeMin": 115
},
{
"id": 4,
"releaseDate": "May 31 1996",
"director": "Rob Cohen",
"title": "Dragonheart",
"genre": "Adventure",
"imdbRating": 6.2,
"runningTimeMin": 108
},
{
"id": 5,
"releaseDate": "Jan 19 1996",
"director": "Robert Rodriguez",
"title": "From Dusk Till Dawn",
"genre": "Horror",
"imdbRating": 7.1,
"runningTimeMin": 107
},
{
"id": 6,
"releaseDate": "Mar 08 1996",
"director": "Joel Coen",
"title": "Fargo",
"genre": "Thriller/Suspense",
"imdbRating": 8.3,
"runningTimeMin": 87
},
{
"id": 7,
"releaseDate": "Oct 11 1996",
"director": "Stephen Hopkins",
"title": "The Ghost and the Darkness",
"genre": "Action",
"imdbRating": 6.6,
"runningTimeMin": 109
},
{
"id": 8,
"releaseDate": "Feb 16 1996",
"director": "Dennis Dugan",
"title": "Happy Gilmore",
"genre": "Comedy",
"imdbRating": 6.9,
"runningTimeMin": 92
},
{
"id": 9,
"releaseDate": "Jul 02 1996",
"director": "Roland Emmerich",
"title": "Independence Day",
"genre": "Adventure",
"imdbRating": 6.5,
"runningTimeMin": 145
},
{
"id": 10,
"releaseDate": "Jun 13 1980",
"director": "Michael Ritchie",
"title": "The Island",
"genre": "Adventure",
"imdbRating": 6.9,
"runningTimeMin": 138
}
]
Let’s pretty-print that JSON
That’s a lovely blob of JSON we got there, but let’s add a -p
to pretty-print it.
http http://lab.artillery.io/movies -b -p
and there we go:
[
{
"id": 1,
"releaseDate": "Dec 18 1985",
"director": "Terry Gilliam",
"title": "Brazil",
"genre": "Black Comedy",
"imdbRating": 8,
"runningTimeMin": 136
},
{
"id": 2,
"releaseDate": "Feb 16 1996",
"director": "Harold Becker",
"title": "City Hall",
"genre": "Drama",
"imdbRating": 6.1,
"runningTimeMin": 111
},
(... rest of the JSON body omitted for brevity)
]
Query JSON with JMESPath
JMESPath is a powerful querying syntax for JSON, used by AWS and Azure CLIs among many others.
The objects returned by our /movies
endpoint contain an imdbRating
field. Let’s get filter down the list from our API endpoint to highly-rated movies only:
http http://lab.artillery.io/movies -q '[?imdbRating>`8`] | [*].title'
We’re asking for titles of all movies with a rating of greater than 8. This is what we’ll see:
[
"Fargo",
"Trainspotting",
"American Beauty",
"Le Fabuleux destin d'AmÈlie Poulain",
"Batman Begins",
"The Dark Knight",
"Big Fish",
"The Big Lebowski",
"The Bourne Ultimatum",
"Inglourious Basterds",
"Children of Men"
]
POST some JSON
We can use all standard HTTP methods such as POST, PUT, PATCH etc.
Let’s send a POST request to another one of our test API endpoints.
http post \
http://lab.artillery.io/login \
--json "{username: testuser, password: testpassword}"
--json
sets request body to JSON we provide... but did you notice how we didn’t have to quote everything fully?
If you’ve ever tried sending JSON from the command-line, especially with some values set dynamically from environment variables, you’ll know how gnarly it can look.
With curl
:
export NAME=tiki
export TYPE=pony
curl \
-XPOST \
-H 'Content-Type: application/json' \
-d "{\"name\":\"$NAME\",\"type\":\"$TYPE\"}" \
https://httpbin.org/post
With Artillery:
export NAME=tiki
export TYPE=pony
http \
--json "{name:$NAME,type:$TYPE}" \
https://httpbin.org/post
Much easier on the eyes, and less error-prone.
Set checks & expectations
We can set expectations on the response and have artillery probe
verify them for us.
For example, let’s run a check on Artillery Docs to make sure the URL
returns 200 OK, that an ETag
header is set,
that the response is served by Vercel, and that the body contains the string "Artillery Docs".
http www.artillery.io/docs \
-e "statusCode: 200" \
-e "hasHeader: etag" \
-e "{headerEquals: [server, Vercel]}" \
-e "matchesRegexp: 'Artillery Docs'"
We’ll see expectation checks at the end:
These checks are powered by the official expect
plugin under the hood, which supports a number of different types of checks such as statusCode
, contentType
, hasHeader
, matchesRegexp
etc.
This is automation-friendly - if an expectation fails, the command will exit with a non-zero code. That means that if you use artillery probe
in a CI/CD job, a failing expectation will make the CI/CD pipeline go red. Continuous verification super-fast! Just throw an artillery probe
command into your CI/CD pipeline.
Get Artillery Probe
Artillery Probe is included in the latest release of Artillery:
npm install -g artillery@latest
We’d love to hear your thoughts & feedback, and learn more about your use-cases. Drop us a message on our GitHub Discussions board.
This is an early release of Artillery Probe, but we’re excited about the possibilities it has for making developers' lives easier, and we need help from our community to make it more awesome!