Skip to main content

Artillery Probe, a Swiss army knife for testing HTTP

· 6 min read
Hassy Veldstra
Artillery Probe

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.

Artillery Probe

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

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
date: 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:

Artillery Probe Expectations

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!