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
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
# ... # Pull job status until it is completed GET https://api.example.org/jobs/ [Options] retry: true 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: true 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: true 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
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
# 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 18.104.22.168:443... ** Connected to hurl.dev (22.214.171.124) 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: * *
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!