Hurl 4.2.0, the HTTP/3 Edition
I'm thrilled to announce the release of Hurl 4.2.0!
Hurl is an Open Source command line tool that allow you to run and test HTTP requests with plain text. You can use it to get datas or to test HTTP APIs (JSON / GraphQL / SOAP) in a CI/CD pipeline.
A basic sample:
GET https://example.org/api/tests/4567
HTTP 200
[Asserts]
header "x-foo" contains "bar"
certificate "Expire-Date" daysAfterNow > 15
jsonpath "$.status" == "RUNNING" # Check the status code
jsonpath "$.tests" count == 25 # Check the number of items
jsonpath "$.id" matches /\\d{4}/ # Check the format of the id
Under the hood, Hurl uses curl with Rust bindings (thanks to the awesome curl-rust crate)
Documentation: https://hurl.dev
GitHub: https://github.com/Orange-OpenSource/hurl
In this new release, we have added the following features:
- HTTP/3 Support
- Install With conda-forge
- Save Response per Request
- jsonpath Filter
- More curl options: IPv6/IPv4, unix-socket etc...
- And a lot of others things (dark mode for HTML reports, skip request option etc...)
HTTP/3 Support
Hurl HTTP engine offloads the HTTP layer to libcurl. We like this design a lot because Hurl benefits directly from curl's power and capabilities "for free", adding some nice asserts and captures possibilities to chain and test HTTP requests.
Started with Hurl 4.2.0, Hurl supports now HTTP/3! Running a Hurl file with HTTP/3 can be done on the command line, with --http3 option:
$ hurl --http3 test.hurl
Like curl, there are also --http2, --http1.1 and --http1.0 options to force a certain version of HTTP. With options sections, we can specify an HTTP version per request, in the same Hurl file:
GET https://myserver.com
[Options]
http3: true
HTTP/3 200
GET https://myserver.com
[Options]
http2: true
HTTP/2 200
To use HTTP/3, the underlying libcurl used by Hurl must expose HTTP/3 features. Simply run hurl --version to check which libcurl features are supported:
$ hurl --version
hurl 4.2.0 (x86_64-apple-darwin23.0) libcurl/8.1.2 (SecureTransport) LibreSSL/3.3.6 zlib/1.2.12 nghttp2/1.55.1
Features (libcurl): alt-svc AsynchDNS HSTS HTTP2 HTTP3 IPv6 Largefile libz NTLM NTLM_WB SPNEGO SSL UnixSockets
Features (built-in): brotli
There are very few HTTP clients that support HTTP/3, so we're very happy with this new feature and look forward for feedbacks!
Install With conda-forge
Hurl can now be installed through conda-forge, a community-led packet manager for Conda:
$ conda install -c conda-forge hurl
conda-forge Hurl installation supports macOS, Linux, Windows, on x86 and ARM 64 bits architectures so we've got you covered!
What's very interesting with conda-forge is that other packet managers use it as a distribution source. For instance, pixi, a powerful and fast package management tool written in Rust, uses the existing conda ecosystem, so Hurl can be installed with pixi:
$ pixi init hello-world
$ cd hello-world
$ pixi add hurl
Save Response per Request
Hurl can be used as a testing tool, but it can be also simply used to get HTTP response when you've to chain multiple dependant requests (download a resource behind a login for instance). In a Hurl file, you can chain multiple requests, passing data from one to another:
# Get home:
GET https://example.org
HTTP 200
[Captures]
csrf_token: xpath "string(//meta[@name='_csrf_token']/@content)"
# Do login!
POST https://example.org/login?user=toto&password=1234
X-CSRF-TOKEN: {{csrf_token}}
HTTP 302
# Get our precisous resource:
GET https://example.org/protected
HTTP 200
When run, Hurl outputs the last response body on the standard output (in this case the response ofGET https://example.org/protected). Like curl, this response can be saved to a file with --output option:
$ hurl --output /tmp/response.json api.hurl
With options sections, we can now save to file each individual response of
any request.
Let's imagine we have a cat API that returns a JSON response for a given cat. If we want to
save multiple cat images on disk, we can write this Hurl file:
- Get the JSON response data for our first cat
- Extract the image's URL of this cat
- Save it to disk with [
--output] - Get the JSON response data for our second cat
- Extract the image's URL of this cat
- Save it to disk with [
--output] - Repeat...
Our Hurl file will look like this:
# Get our first cat resource and capture its image
GET https://catapi.com/cats/1
HTTP 200
[Captures]
img: jsonpath "$.url"
# Download its image and save it to disk
GET {{img}}
[Options]
output: cat1.jpg
HTTP 200
# Do the same with the second cat:
GET https://catapi.com/cats/2
HTTP 200
[Captures]
img: jsonpath "$.url"
# Download its image and save it to disk
GET {{img}}
[Options]
output: cat2.jpg
HTTP 200
jsonpath Filter
Data can be captured and/or tested from HTTP responses using JSONPath, XPath, regex etc... Filters allow us to even refine the extracted data. With the new jsonpath filter, we're able to chain XPath or regex queries with a JSONPath filter:
For instance, given this HTML file:
<!DOCTYPE html>
<html>
<body>
<p id="user"></p>
<script>
var s = '{"first_name" : "Sammy", "last_name" : "Shark", "location" : "Ocean"}';
var obj = JSON.parse(s);
document.getElementById("user").innerHTML =
"Name: " + obj.first_name + " " + obj.last_name + "<br>" +
"Location: " + obj.location;
</script>
</body>
</html>
We want to extract the string {"first_name" : "Sammy", "last_name" : "Shark", "location" : "Ocean"} and analyse it as
a JSON:
- First, with a
regexquery, we extract this stringregex /var s = '(.*)';/ - Then, with a
jsonpathfilter, we test the datajsonpath "$.first_name" == "Sammy"
So our Hurl file will be:
GET https://example.com/test.html
HTTP 200
[Asserts]
regex /var s = '(.*)';/ jsonpath "$.first_name" == "Sammy"
regex /var s = '(.*)';/ jsonpath "$.last_name" == "Shark"
regex /var s = '(.*)';/ jsonpath "$.location" == "Ocean"
Or with an intermediate capture:
GET https://example.com/test.html
HTTP 200
[Captures]
s: regex /var s = '(.*)';/
[Asserts]
variable "s" jsonpath "$.first_name" == "Sammy"
variable "s" jsonpath "$.last_name" == "Shark"
variable "s" jsonpath "$.location" == "Ocean"
More curl options: IPv6/IPv4, unix-socket etc...
Finally, in Hurl 4.2.0, more curl options have been implemented --ipv4 / --ipv6, --unix-socket and --location-trusted.
Others
There are other improvements with Hurl 4.2.0 (dark mode for HTML report, skip option request, etc...) and also a lot of bug fixes, you can check the complete list of enhancements and bug fixes in our release note.
If you like Hurl, don't hesitate to give us a star on GitHub!
We'll be happy to hear from you, either for enhancement requests or for sharing your success story using Hurl!