Announcing Hurl 7.0.0

Partying Face In this hot summer, the Hurl team is super happy to announce Hurl 7.0.0!

Hurl is a command line tool powered by curl, that runs HTTP requests defined in a simple plain text format:

GET https://example.org/api/tests/4567
HTTP 200
[Asserts]
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
# Some tests on the HTTP layer:
header "x-foo" contains "bar"
certificate "Expire-Date" daysAfterNow > 15
ip == "2001:0db8:85a3:0000:0000:8a2e:0370:733"

What’s New in This Release

More Redirections Checks

Like its HTTP engine libcurl, Hurl doesn’t follow redirection by default: on a 30x response status code, Hurl returns the HTTP response and does not trigger a new request following Location header. Redirections have to be done manually:

# First request, users are redirected to /login 
GET https://foo.com/home
HTTP 302
[Asserts]
header "Location" == "/login"

# We manually follow the redirection
GET https://foo.com/login
HTTP 200

This way, one can test each step of a redirection and insure that everything works as expected.

Like curl, we can use --location option to ask Hurl to follow redirection, either globally using the command line option:

$ hurl --location foo.hurl

Or per request using [Options] section:

GET https://foo.com/home
[Options]
location: true
HTT 200

Using --location (or --location-trusted), Hurl obeys the redirection and will issue requests until redirection ends. Before Hurl 7.0.0, we were losing the ability to check each redirection steps using this option. The only check we could have done was using url query to give us the final effective URL:

GET https://foo.com/home
[Options]
location: true
HTTP 200
[Asserts]
url == "https://foo.com/login"

Starting with Hurl 7.0.0, we’re introducing the redirects query, that give us access to each redirection step:

GET https://foo.com/home
[Options]
location: true
HTTP 200
[Asserts]
redirects count == 3
redirects nth 0 location == "https://foo.com/redirect-1"
redirects nth 1 location == "https://foo.com/redirect-2"
redirects nth 2 location == "https://foo.com/landing"

The redirects query returns the list of each step followed during redirection. By combining nth and location filters, we are now able to check redirection steps while letting Hurl runs automatically to the final URL.

New Template Filters

Filters allow to transform data extracted from HTTP responses. In the following sample, replaceRegex, split, count and nth are filters that process input; they can be chained to transform values in asserts and captures:

GET https://example.org/api
HTTP 200
[Captures]
name: jsonpath "$.user.id" replaceRegex /\d/ "x"
[Asserts]
header "x-servers" split "," count == 2
header "x-servers" split "," nth 0 == "rec1"
header "x-servers" split "," nth 1 == "rec3"
jsonpath "$.books" count == 12

In Hurl 7.0.0, we’ve added new filters:

  • urlQueryParam
  • base64UrlSafeDecode and base64UrlSafeEncode
  • location
  • toHex
  • first and last

In detail,

  • urlQueryParam: extracts the value of a query parameter from an URL
GET https://example.org/foo
HTTP 200
[Asserts]
jsonpath "$.url" urlQueryParam "x" == "шеллы"

This filter can be useful when you need to process URL received in payload, like a back URL.

GET https://example.org/api
HTTP 200
[Asserts]
jsonpath "$.token" base64UrlSafeDecode == hex,3c3c3f3f3f3e3e;
  • location: returns the target URL location of a redirection. Combined with the new redirects query, you can check each step of a redirection:
GET https://example.org/step1
[Options]
location: true
HTTP 200
[Asserts]
redirects count == 2
redirects nth 0 location == "https://example.org/step2"
redirects nth 1 location == "https://example.org/step3"
  • toHex: converts bytes to an hexadecimal string.
GET https://example.org/foo
HTTP 200
[Asserts]
bytes toHex == "d188d0b5d0bbd0bbd18b"
  • first and last: applied to a list, returns the first and last element:
GET https://example.org/api
HTTP 200
[Asserts]
jsonpath "$..books" last jsonpath "$.title" == "Dune"

Alongside first and last, nth filter now supports negative index value for indexing from the end of the collection:

GET https://example.org/api
HTTP 200
[Asserts]
jsonpath "$..books" nth -2 jsonpath "$.title" == "Dune"

New Supported curl Options

Using libcurl as its HTTP engine, Hurl exposes many curl options. In Hurl 7.0.0, we have added these two options:

  • --max-time per request: allows you to configure timeout per request,
  • --ntlm: uses NTLM authentication,
  • --negotiate: uses Negotiate (SPNEGO) authentication,
  • --pinnedpubkey: compares the certificate public key to a local public key and abort connection if not match. Can be use either globally on command line or per request:
GET https://foo.com/hello
[Options]
# With a pinned public key local file
pinnedpubkey: tests_ssl/certs/server/key.pub.pem
# With a pinned public Hash
pinnedpubkey: "sha256//dGhpc2lzbm5vdGFyZWFsa2V5"
HTTP 200

That’s all for today!

There are a lot of other improvements with Hurl 7.0.0 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 support us with a star on GitHub and share it on [𝕏] and Bluesky!

We’ll be happy to hear from you, either for enhancement requests or for sharing your success story using Hurl!