Announcing Hurl 1.8.0
The Hurl team is happy to announce Hurl 1.8.0 ! .
Hurl is a command line tool powered by curl, that runs HTTP requests defined in a simple plain text format:
# Get home:
GET https://example.org
HTTP/1.1 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:
HTTP/1.1 302
Hurl can be used to get data like curl, or as a testing tool for JSON/XML apis and HTML content.
So, what’s new in 1.8.0?
Polling and Retry
You can now retry requests which asserts and captures have failed. This way, you can write
polling scenarios or create robust tests even in flaky conditions. To activate retry, you can either use --retry
option (every request of the run can be retried), or you can target a specific request with an [Options]
section.
Let’s say we have an API to create a ressource. Once created, we want to poll this resource and wait until it reaches a certain state.
First we create a new resource with a POST
request. We capture the id of the resource to be able to use it
in the following requests:
# Create a new job
POST https://api.example.org/jobs
HTTP/* 201
[Captures]
job_id: jsonpath "$.id"
[Asserts]
jsonpath "$.state" == "RUNNING"
Then, we pull the resource with a GET
request and check its state
value. We’ve configured the GET
request to
be retried with an [Options]
section. The JSONPath assert tests the value of state
field. Because
of the retry option, the GET
request is going to be retried until state
’s value is COMPLETED
:
# ...
# Pull job status until it is completed
GET https://api.example.org/jobs/
[Options]
retry: 10
HTTP/* 200
[Asserts]
jsonpath "$.state" == "COMPLETED"
So, the full scenario looks like:
# Create a new job
POST https://api.example.org/jobs
HTTP/* 201
[Captures]
job_id: jsonpath "$.id"
[Asserts]
jsonpath "$.state" == "RUNNING"
# Pull job status until it is completed
GET https://api.example.org/
[Options]
retry: 10
HTTP/* 200
[Asserts]
jsonpath "$.state" == "COMPLETED"
Retry work on any asserts, whether they’re explicit (with an [Asserts]
section), or implicit (the status code). For instance, the following snippet:
GET https://api.example.org/123456
[Options]
retry: 10
retry-interval: 4000
HTTP/* 200
will poll until https://api.example.org/123456
returns a 200 OK
, with a 4 seconds delay between each retry.
Finally, one common need in shell script is to wait until a specific URL is ready and returns a 200 OK. This can be easily done now with Hurl:
$ echo -e 'GET https://example.org/health\nHTTP/* 200' | hurl --retry
URL Assert
The URL assert allows check on the final URL of a request: it’s particularly interesting when you tell Hurl to follow
redirects (either with --location
option or with an Options
section):
# Check that HTTP is redirected to HTTPS:
GET http://example.org
[Options]
location: true
HTTP/* 200
[Asserts]
url == "https://example.org"
curl Debug Logs
In Hurl 1.7.0, we introduced --very-verbose
option to output request and response bodies. Now, when very-verbose
is used, Hurl displays debug logs from libcurl (prefixed with **
), allowing displaying SSL certificates infos for instance:
$ echo 'HEAD https://hurl.dev' | hurl --very-verbose
* Options:
* fail fast: true
* follow redirect: false
* insecure: false
* max redirect: 50
* retry: false
* retry max count: 10
* ------------------------------------------------------------------------------
* Executing entry 1
*
* Cookie store:
*
* Request:
* HEAD https://hurl.dev
*
* Request can be run with the following curl command:
* curl 'https://hurl.dev' --head
*
** Trying 145.239.78.213:443...
** Connected to hurl.dev (145.239.78.213) port 443 (#0)
** ALPN, offering h2
** ALPN, offering http/1.1
** successfully set certificate verify locations:
** CAfile: /etc/ssl/cert.pem
** CApath: none
** (304) (OUT), TLS handshake, Client hello (1):
** (304) (IN), TLS handshake, Server hello (2):
** TLSv1.2 (IN), TLS handshake, Certificate (11):
** TLSv1.2 (IN), TLS handshake, Server key exchange (12):
** TLSv1.2 (IN), TLS handshake, Server finished (14):
** TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
** TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
** TLSv1.2 (OUT), TLS handshake, Finished (20):
** TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
** TLSv1.2 (IN), TLS handshake, Finished (20):
** SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
** ALPN, server accepted to use h2
** Server certificate:
** subject: CN=hurl.dev
** start date: Sep 30 22:15:32 2022 GMT
** expire date: Dec 29 22:15:31 2022 GMT
** subjectAltName: host "hurl.dev" matched cert's "hurl.dev"
** issuer: C=US; O=Let's Encrypt; CN=R3
** SSL certificate verify ok.
** Using HTTP2, server supports multiplexing
** Connection state changed (HTTP/2 confirmed)
** Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
** Using Stream ID: 1 (easy handle 0x14c811800)
> HEAD / HTTP/2
> Host: hurl.dev
> accept: */*
> user-agent: hurl/1.8.0-SNAPSHOT
>
* Request body:
*
** Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
** Connection #0 to host hurl.dev left intact
* Response: (received 0 bytes in 110 ms)
*
< HTTP/2 200
< server: nginx/1.14.2
< date: Mon, 31 Oct 2022 13:12:41 GMT
< content-type: text/html
< content-length: 28370
< last-modified: Thu, 27 Oct 2022 14:15:30 GMT
< etag: "635a9282-6ed2"
< accept-ranges: bytes
<
* Response body:
*
*
That’s All
If you like Hurl, don’t hesitate to give us a star on GitHub or share it on Twitter!
We’ll be happy to hear from you, either for enhancement requests or for sharing your success story using Hurl!