HURL: Run and Test HTTP API Requests

[ad_1]
A few weeks ago I saw a front-page Hacker News post on a new CURL-based HTTP runner written in Rust called Hurl. Interesting! We’ve been looking for an easy way to deploy and test API requests against our public API.
First, if you are looking to test API calls, there are tons of options from online testing tools, Postman, build your own, etc. Here’s a Google search on testing API calls.
These tools are probably amazing, but I want to keep things simple:
- Call API endpoints with query or post parameters.
- Confirm Answer 200.
- Validate the returned JSON.
- Call another API endpoint based on the JSON returned from the previous call.
The system should work on all endpoints and warn if something is wrong; the run may be before the release or after the code has been changed. And since I’m a terminal/CLI lover, I’d like to run the test from the command line – using Warp, my favorite Mac program.
Hurl for Testing API Endpoint
When I saw Hurl, I thought, wow, this could be perfect – although there is something to be said for the name.
As Hurl explains,
“”Hurl allows executing HTTP requests defined in plain text format. It can be used to fetch data, or play a scenario (a sequence of requests), asserting responses along the way. In its text format, it is intended for both devops and developers. With a unique simple command line / binary implementation, it is intended for both local dev and continuous integration. “
Let’s try Hurl out. You can also see how to start Hurl with script examples.
Basic Hurl Call
First install Hurl on your OS of choice. Here it is brew
on Mac:
brew install hurl
Now let’s try to make a call – we’ll just call google.com and make sure a 200 response is returned.
Create a file called basic.hurl in your favorite IDE – there is no VSCode syntax highlighter, but the Hurl team said they are working on it.
GET
HTTP/1.1 200
In the list where the basic.hurl file is saved, run the command:
hurl --test basic.hurl
The answer is:

It’s a mistake! However, this is good. As you can see the problem is google.com’s HTTP/2 response. Also note how you get statistics on how many files have been used, duration, etc. Just change this to the base.hurl file and you’re off to the races.

Advanced Hurl Call
Now for the fun stuff, making POST API calls with the body and asserting the results. In this advanced Hurl example we will call the Ayrshare social media API to send a post. You can create a free account with your API key. After creating your account connect to at least one social network, such as Twitter.
Create a new file called post.hurl and copy the following code:
# /post POST -------------
POST
Content-Type: application/json
Authorization: Bearer {{API_KEY}}
{
"randomPost": true,
"platforms": [
"twitter"
]
}
HTTP/* 200
[Asserts]
header "Content-Type" == "application/json; charset=utf-8"
jsonpath "$.status" == "success"
jsonpath "$.errors" count == 0
jsonpath "$.postIds[0].status" == "success"
jsonpath "$.postIds[0].id" exists
jsonpath "$.postIds[0].postUrl" exists
jsonpath "$.postIds[0].platform" == "twitter"
jsonpath "$.id" exists
jsonpath "$.refId" exists
jsonpath "$.post" exists
[Captures]
id: jsonpath "$['id']"
tw_id: jsonpath "$.postIds[0].id"
# -----------------------
Several things are happening. First, i {{API_KEY}}
set variable in env file. We keep this in a separate file for use with different Hurls.
Set your API key in a file called vars.env:
API_KEY=GHLOM-QW6MRC7-KX944W1-PWKJFT
The next two lines (Content-Type
again Authorization
) set the header followed by the POST JSON body. See Social media API/post endpoint for details on the POST body. This is all data related to making a call.
Line with HTTP/* 200
starts checking (* instead of 1.1 or 2 to accept any HTTP version).
[Asserts]
Of [Asserts]
part of the file we check the validity of the Header and JSON response. header "Content-Type"
checks if the content type is correct. In JSON we have to extract the key with it jsonpath
question, predicate form, and predicate value.

For example, jsonpath "$.status" == "success"
get the status key and check if the value equals “success”. If not, an error is thrown.
There are several types of predicates, such as exists
again count
.
[Captures]
I [Captures]
component captures data into variables. The format is:

In our example,
id: jsonpath "$['id']"
tw_id: jsonpath "$.postIds[0].id"
we capture the returned post ID and Tweet ID in the list field. Later we can use this variable if we want to combine requests in a format {{variable name}}
:
# /analytics/post -------
POST
Content-Type: application/json
Authorization: Bearer {{API_KEY}}
{
"id": "{{id}}"
}
Run Hurl
Finally we need to run the Hurl file through the command line, using the --very-verbose
hit the flag so we can see all the cool stuff happening:
hurl --test --very-verbose --variables-file vars.env post.hurl
and results:

Enjoy Hurl
So far so good with Hurl. I found it easy to use and feature rich. And they seem to be in the normal state of release – always a good sign.
We’ve been writing a lot of test cases over the past few weeks and as our development team uses Hurl more we’ll decide if it’s a permanent part of our test suite.
If you want to see more sample Hurl files with chaining, check out Ayrshare’s Hurl files.
– Geoff Bourne, Co-Founder Ayrshare