From 42ef4125fe12f0fc6e9f68e0b6565d1fb6ac657a Mon Sep 17 00:00:00 2001 From: jcamiel Date: Mon, 19 Dec 2022 21:30:08 +0100 Subject: [PATCH] Update docs for Hurl 2.0.0. --- README.md | 325 ++++++++++++++++---------- bin/docs/build_man_md.py | 6 +- contrib/npm/hurl/README.md | 53 ++++- docs/asserting-response.md | 274 +++++++++++++--------- docs/assets/cast/hurl.cast | 250 ++++++++++++++++++++ docs/assets/img/hurl-html-report.png | Bin 33729 -> 164674 bytes docs/capturing-response.md | 119 ++++------ docs/entry.md | 40 ++-- docs/filters.md | 189 +++++++++++++++ docs/home.md | 39 +++- docs/hurl-file.md | 7 +- docs/installation.md | 26 +-- docs/manual.md | 145 ++++++------ docs/manual/hurl.1 | 68 ++++-- docs/manual/hurl.md | 66 ++++-- docs/manual/hurlfmt.1 | 2 +- docs/request.md | 182 ++++++++++++--- docs/response.md | 4 +- docs/running-tests.md | 17 +- docs/samples.md | 110 +++++++-- docs/templates.md | 52 +++-- docs/tutorial/adding-asserts.md | 24 +- docs/tutorial/captures.md | 35 +-- docs/tutorial/chaining-requests.md | 23 +- docs/tutorial/ci-cd-integration.md | 22 +- docs/tutorial/debug-tips.md | 69 +++--- docs/tutorial/security.md | 34 +-- docs/tutorial/your-first-hurl-file.md | 6 +- packages/hurl/README.md | 325 ++++++++++++++++---------- packages/hurl/src/cli/options.rs | 8 +- 30 files changed, 1735 insertions(+), 785 deletions(-) create mode 100644 docs/assets/cast/hurl.cast create mode 100644 docs/filters.md diff --git a/README.md b/README.md index 8aef570a8..175fd9db0 100644 --- a/README.md +++ b/README.md @@ -12,21 +12,24 @@ Hurl is a command line tool that runs HTTP requests defined in a simple plain text format. It can chain requests, capture values and evaluate queries on headers and body response. Hurl is very -versatile: it can be used for fetching data, testing HTTP sessions and testing XML / JSON APIs. +versatile: it can be used for both fetching data and testing HTTP sessions. + +Hurl makes it easy to work with HTML content, REST / SOAP / GraphQL APIs, or any other XML / JSON based APIs. ```hurl # Get home: GET https://example.org -HTTP/1.1 200 +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/1.1 302 +HTTP 302 ``` Chaining multiple requests is easy: @@ -55,7 +58,7 @@ POST https://example.org/api/tests "evaluate": true } -HTTP/1.1 200 +HTTP 200 [Asserts] header "X-Frame-Options" == "SAMEORIGIN" jsonpath "$.status" == "RUNNING" # Check the status code @@ -68,12 +71,27 @@ jsonpath "$.id" matches /\d{4}/ # Check the format of the id ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "normalize-space(//head/title)" == "Hello world!" ``` -and even SOAP APIs +GraphQL + +~~~hurl +POST https://example.org/graphql +```graphql +{ + human(id: "1000") { + name + height(unit: FOOT) + } +} +``` +HTTP 200 +~~~ + +and even SOAP APIs ```hurl POST https://example.org/InStock @@ -88,8 +106,7 @@ SOAPAction: "http://www.w3.org/2003/05/soap-envelope" - -HTTP/1.1 200 +HTTP 200 ``` Hurl can also be used to performance test HTTP endpoints: @@ -97,7 +114,7 @@ Hurl can also be used to performance test HTTP endpoints: ```hurl GET https://example.org/api/v1/pets -HTTP/1.0 200 +HTTP 200 [Asserts] duration < 1000 # Duration in ms ``` @@ -107,7 +124,7 @@ And response bytes ```hurl GET https://example.org/data.tar.gz -HTTP/1.0 200 +HTTP 200 [Asserts] sha256 == hex,039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81; ``` @@ -138,7 +155,7 @@ POST https://hurl.dev/api/feedback "name": "John Doe", "feedback": "Hurl is awesome !" } -HTTP/1.1 200 +HTTP 200 ``` # Resources @@ -164,7 +181,9 @@ Table of Contents * [Sending HTML Form Data](#sending-html-form-data) * [Sending Multipart Form Data](#sending-multipart-form-data) * [Posting a JSON Body](#posting-a-json-body) - * [Templating a JSON / XML Body](#templating-a-json--xml-body) + * [Templating a JSON Body](#templating-a-json-body) + * [Templating a XML Body](#templating-a-xml-body) + * [Using GraphQL Query](#using-graphql-query) * [Testing Response](#testing-response) * [Testing Response Headers](#testing-response-headers) * [Testing REST APIs](#testing-rest-apis) @@ -172,6 +191,7 @@ Table of Contents * [Testing Set-Cookie Attributes](#testing-set-cookie-attributes) * [Testing Bytes Content](#testing-bytes-content) * [Others](#others) + * [HTTP Version](#http-version) * [Polling and Retry](#polling-and-retry) * [Testing Endpoint Performance](#testing-endpoint-performance) * [Using SOAP APIs](#using-soap-apis) @@ -354,15 +374,11 @@ file,data.json; [Doc](https://hurl.dev/docs/request.html#file-body) -### Templating a JSON / XML Body +### Templating a JSON Body -Using templates with [JSON body] or [XML body] is not currently supported in Hurl. -Besides, you can use templates in [multiline string body] with variables to send a JSON or XML body: - -~~~hurl +```hurl PUT https://example.org/api/hits Content-Type: application/json -``` { "key0": "{{a_string}}", "key1": {{a_bool}}, @@ -370,7 +386,6 @@ Content-Type: application/json "key3": {{a_number}} } ``` -~~~ Variables can be initialized via command line: @@ -393,8 +408,67 @@ Resulting in a PUT request with the following JSON body: } ``` +[Doc](https://hurl.dev/docs/templates.html) + +### Templating a XML Body + +Using templates with [XML body] is not currently supported in Hurl. You can use templates in +[XML multiline string body] with variables to send a variable XML body: + +~~~hurl +POST https://example.org/echo/post/xml +```xml + + + {{login}} + {{password}} + +``` +~~~ + [Doc](https://hurl.dev/docs/request.html#multiline-string-body) +### Using GraphQL Query + +A simple GraphQL query: + +~~~hurl +POST https://example.org/starwars/graphql +```graphql +{ + human(id: "1000") { + name + height(unit: FOOT) + } +} +``` +~~~ + +A GraphQL query with variables: + +~~~hurl +POST https://example.org/starwars/graphql +```graphql +query Hero($episode: Episode, $withFriends: Boolean!) { + hero(episode: $episode) { + name + friends @include(if: $withFriends) { + name + } + } +} + +variables { + "episode": "JEDI", + "withFriends": false +} +``` +~~~ + +GraphQL queries can also use [Hurl templates]. + +[Doc](https://hurl.dev/docs/request.html#graphql-body) + ## Testing Response ### Testing Response Headers @@ -404,7 +478,7 @@ Use implicit response asserts to test header values: ```hurl GET https://example.org/index.html -HTTP/1.0 200 +HTTP 200 Set-Cookie: theme=light Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT ``` @@ -417,7 +491,7 @@ Or use explicit response asserts with [predicates]: ```hurl GET https://example.org -HTTP/1.1 302 +HTTP 302 [Asserts] header "Location" contains "www.example.net" ``` @@ -433,7 +507,7 @@ Asserting JSON body response (node values, collection count etc...) with [JSONPa GET https://example.org/order screencapability: low -HTTP/1.1 200 +HTTP 200 [Asserts] jsonpath "$.validated" == true jsonpath "$.userInfo.firstName" == "Franck" @@ -453,7 +527,7 @@ Testing status code: ```hurl GET https://example.org/order/435 -HTTP/1.1 200 +HTTP 200 ``` [Doc](https://hurl.dev/docs/asserting-response.html#version-status) @@ -462,7 +536,7 @@ HTTP/1.1 200 GET https://example.org/order/435 # Testing status code is in a 200-300 range -HTTP/1.1 * +HTTP * [Asserts] status >= 200 status < 300 @@ -476,7 +550,7 @@ status < 300 ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 Content-Type: text/html; charset=UTF-8 [Asserts] @@ -495,7 +569,7 @@ xpath "string(//div[1])" matches /Hello.*/ ```hurl GET http://myserver.com/home -HTTP/1.0 200 +HTTP 200 [Asserts] cookie "JSESSIONID" == "8400BAFE2F66443613DC38AE3D9D6239" cookie "JSESSIONID[Value]" == "8400BAFE2F66443613DC38AE3D9D6239" @@ -525,6 +599,17 @@ sha256 == hex,039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81; ## Others +### HTTP Version + +Testing HTTP version (1.0, 1.1 or 2): + +```hurl +GET https://example.org/order/435 +HTTP/2 200 +``` + +[Doc](https://hurl.dev/docs/asserting-response.html#version-status) + ### Polling and Retry Retry request on any errors (asserts, captures, status code, runtime etc...): @@ -533,7 +618,7 @@ Retry request on any errors (asserts, captures, status code, runtime etc...): # Create a new job POST https://api.example.org/jobs -HTTP/* 201 +HTTP 201 [Captures] job_id: jsonpath "$.id" [Asserts] @@ -545,7 +630,7 @@ GET https://api.example.org/jobs/{{job_id}} [Options] retry: true -HTTP/* 200 +HTTP 200 [Asserts] jsonpath "$.state" == "COMPLETED" ``` @@ -559,7 +644,7 @@ jsonpath "$.state" == "COMPLETED" ```hurl GET https://sample.org/helloworld -HTTP/* * +HTTP * [Asserts] duration < 1000 # Check that response time is less than one second ``` @@ -582,7 +667,7 @@ SOAPAction: "http://www.w3.org/2003/05/soap-envelope" -HTTP/1.1 200 +HTTP 200 ``` [Doc](https://hurl.dev/docs/request.html#xml-body) @@ -592,14 +677,14 @@ HTTP/1.1 200 ```hurl GET https://example.org -HTTP/* 200 +HTTP 200 [Captures] csrf_token: xpath "string(//meta[@name='_csrf_token']/@content)" POST https://example.org/login?user=toto&password=1234 X-CSRF-TOKEN: {{csrf_token}} -HTTP/* 302 +HTTP 302 ``` [Doc](https://hurl.dev/docs/capturing-response.html#xpath-capture) @@ -609,7 +694,7 @@ HTTP/* 302 ```hurl GET https://example.org/data.bin -HTTP/* 200 +HTTP 200 [Asserts] bytes startsWith hex,efbbbf; ``` @@ -631,9 +716,9 @@ hurl - run and test HTTP requests. ## Description -**Hurl** is an HTTP client that performs HTTP requests defined in a simple plain text format. +**Hurl** is a command line tool that runs HTTP requests defined in a simple plain text format. -Hurl is very versatile. It enables chaining HTTP requests, capturing values from HTTP responses, and making assertions. +It can chain requests, capture values and evaluate queries on headers and body response. Hurl is very versatile, it can be used for fetching data and testing HTTP sessions: HTML content, REST / SOAP / GraphQL APIs, or any other XML / JSON based APIs. ```shell $ hurl session.hurl @@ -690,11 +775,11 @@ GET http:/example.org/endpoint2 A value from an HTTP response can be-reused for successive HTTP requests. -A typical example occurs with csrf tokens. +A typical example occurs with CSRF tokens. ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 # Capture the CSRF token value from html body. [Captures] csrf_token: xpath "normalize-space(//meta[@name='_csrf_token']/@content)" @@ -708,28 +793,28 @@ More information on captures can be found here [https://hurl.dev/docs/capturing- ### Asserts -The HTTP response defined in the Hurl session are used to make asserts. +The HTTP response defined in the Hurl file are used to make asserts. Responses are optional. -At the minimum, the response includes the asserts on the HTTP version and status code. +At the minimum, response includes assert on the HTTP status code. ```hurl -GET http:/google.com -HTTP/1.1 301 +GET http:/example.org +HTTP 301 ``` It can also include asserts on the response headers ```hurl -GET http:/google.com -HTTP/1.1 301 -Location: http://www.google.com +GET http:/example.org +HTTP 301 +Location: http://www.example.org ``` Explicit asserts can be included by combining a query and a predicate ```hurl -GET http:/google.com -HTTP/1.1 301 +GET http:/example.org +HTTP 301 [Asserts] xpath "string(//title)" == "301 Moved" ``` @@ -753,56 +838,61 @@ $ hurl --location foo.hurl will follow redirection for each entry in `foo.hurl`. You can also define an option only for a particular entry with an `[Options]` section. For instance, this Hurl file: ```hurl -GET https://google.com -HTTP/* 301 +GET https://example.org +HTTP 301 -GET https://google.com +GET https://example.org [Options] location: true -HTTP/* 200 +HTTP 200 ``` will follow a redirection only for the second entry. -Option | Description - --- | --- ---cacert | Specifies the certificate file for peer verification. The file may contain multiple CA certificates and must be in PEM format.
Normally Hurl is built to use a default file for this, so this option is typically used to alter that default file.
---color | Colorize Output.
---compressed | Request a compressed response using one of the algorithms br, gzip, deflate and automatically decompress the content.
---connect-timeout <SECONDS> | Maximum time in seconds that you allow Hurl's connection to take.

See also [`-m, --max-time`](#max-time) option.
--b, --cookie <FILE> | Read cookies from FILE (using the Netscape cookie file format).

Combined with [`-c, --cookie-jar`](#cookie-jar), you can simulate a cookie storage between successive Hurl runs.
--c, --cookie-jar <FILE> | Write cookies to FILE after running the session (only for one session).
The file will be written using the Netscape cookie file format.

Combined with [`-b, --cookie`](#cookie), you can simulate a cookie storage between successive Hurl runs.
---fail-at-end | Continue executing requests to the end of the Hurl file even when an assert error occurs.
By default, Hurl exits after an assert error in the HTTP response.

Note that this option does not affect the behavior with multiple input Hurl files.

All the input files are executed independently. The result of one file does not affect the execution of the other Hurl files.
---file-root <DIR> | Set root file system to import files in Hurl. This is used for both files in multipart form data and request body.
When this is not explicitly defined, the files are relative to the current directory in which Hurl is running.
--L, --location | Follow redirect. To limit the amount of redirects to follow use the [`--max-redirs`](#max-redirs) option
---glob <GLOB> | Specify input files that match the given glob pattern.

Multiple glob flags may be used. This flag supports common Unix glob patterns like *, ? and [].
However, to avoid your shell accidentally expanding glob patterns before Hurl handles them, you must use single quotes or double quotes around each pattern.
--i, --include | Include the HTTP headers in the output (last entry).
---ignore-asserts | Ignore all asserts defined in the Hurl file.
--k, --insecure | This option explicitly allows Hurl to perform "insecure" SSL connections and transfers.
---interactive | Stop between requests.
This is similar to a break point, You can then continue (Press C) or quit (Press Q).
---json | Output each hurl file result to JSON. The format is very closed to HAR format.
---max-redirs <NUM> | Set maximum number of redirection-followings allowed
By default, the limit is set to 50 redirections. Set this option to -1 to make it unlimited.
--m, --max-time <SECONDS> | Maximum time in seconds that you allow a request/response to take. This is the standard timeout.

See also [`--connect-timeout`](#connect-timeout) option.
---no-color | Do not colorize output.
---no-output | Suppress output. By default, Hurl outputs the body of the last response.
---noproxy <HOST(S)> | Comma-separated list of hosts which do not use a proxy.
Override value from Environment variable no_proxy.
--o, --output <FILE> | Write output to FILE instead of stdout.
--x, --proxy [protocol://]host[:port] | Use the specified proxy.
---report-junit <FILE> | Generate JUnit File.

If the FILE report already exists, it will be updated with the new test results.
---report-html <DIR> | Generate HTML report in DIR.

If the HTML report already exists, it will be updated with the new test results.
---retry | Retry requests if any error occurs (asserts, captures, runtimes etc...).
---retry-interval <MILLISECONDS> | Duration in milliseconds between each retry. Default is 1000 ms.
---retry-max-count <NUM> | Maximum number of retries. Set this option to -1 to make it unlimited. Default is 10.
---test | Activate test mode: with this, the HTTP response is not outputted anymore, progress is reported for each Hurl file tested, and a text summary is displayed when all files have been run.
---to-entry <ENTRY_NUMBER> | Execute Hurl file to ENTRY_NUMBER (starting at 1).
Ignore the remaining of the file. It is useful for debugging a session.
--u, --user <USER:PASSWORD> | Add basic Authentication header to each request.
--A, --user-agent <NAME> | Specify the User-Agent string to send to the HTTP server.
---variable <NAME=VALUE> | Define variable (name/value) to be used in Hurl templates.
---variables-file <FILE> | Set properties file in which your define your variables.

Each variable is defined as name=value exactly as with [`--variable`](#variable) option.

Note that defining a variable twice produces an error.
--v, --verbose | Turn on verbose output on standard error stream.
Useful for debugging.

A line starting with '>' means data sent by Hurl.
A line staring with '<' means data received by Hurl.
A line starting with '*' means additional info provided by Hurl.

If you only want HTTP headers in the output, [`-i, --include`](#include) might be the option you're looking for.
---very-verbose | Turn on more verbose output on standard error stream.

In contrast to [`--verbose`](#verbose) option, this option outputs the full HTTP body request and response on standard error. In addition, lines starting with '**' are libcurl debug logs.
--h, --help | Usage help. This lists all current command line options with a short description.
--V, --version | Prints version information
+| Option | Description | +|------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| --cacert <FILE> | Specifies the certificate file for peer verification. The file may contain multiple CA certificates and must be in PEM format.
Normally Hurl is built to use a default file for this, so this option is typically used to alter that default file.
| +| -E, --cert <CERTIFICATE[:PASSWORD]> | Client certificate file and password.

See also [`--key`](#key).
| +| --color | Colorize Output.
| +| --compressed | Request a compressed response using one of the algorithms br, gzip, deflate and automatically decompress the content.
| +| --connect-timeout <SECONDS> | Maximum time in seconds that you allow Hurl's connection to take.

See also [`-m, --max-time`](#max-time).
| +| --connect-to <HOST1:PORT1:HOST2:PORT2> | For a request to the given HOST1:PORT1 pair, connect to HOST2:PORT2 instead. This option can be used several times in a command line.

See also [`--resolve`](#resolve).
| +| -b, --cookie <FILE> | Read cookies from FILE (using the Netscape cookie file format).

Combined with [`-c, --cookie-jar`](#cookie-jar), you can simulate a cookie storage between successive Hurl runs.
| +| -c, --cookie-jar <FILE> | Write cookies to FILE after running the session (only for one session).
The file will be written using the Netscape cookie file format.

Combined with [`-b, --cookie`](#cookie), you can simulate a cookie storage between successive Hurl runs.
| +| --fail-at-end | Continue executing requests to the end of the Hurl file even when an assert error occurs.
By default, Hurl exits after an assert error in the HTTP response.

Note that this option does not affect the behavior with multiple input Hurl files.

All the input files are executed independently. The result of one file does not affect the execution of the other Hurl files.
| +| --file-root <DIR> | Set root file system to import files in Hurl. This is used for both files in multipart form data and request body.
When this is not explicitly defined, the files are relative to the current directory in which Hurl is running.
| +| -L, --location | Follow redirect. To limit the amount of redirects to follow use the [`--max-redirs`](#max-redirs) option
| +| --glob <GLOB> | Specify input files that match the given glob pattern.

Multiple glob flags may be used. This flag supports common Unix glob patterns like *, ? and [].
However, to avoid your shell accidentally expanding glob patterns before Hurl handles them, you must use single quotes or double quotes around each pattern.
| +| -i, --include | Include the HTTP headers in the output (last entry).
| +| --ignore-asserts | Ignore all asserts defined in the Hurl file.
| +| -k, --insecure | This option explicitly allows Hurl to perform "insecure" SSL connections and transfers.
| +| --interactive | Stop between requests.
This is similar to a break point, You can then continue (Press C) or quit (Press Q).
| +| --json | Output each hurl file result to JSON. The format is very closed to HAR format.
| +| --key <KEY> | Private key file name.
| +| --max-redirs <NUM> | Set maximum number of redirection-followings allowed
By default, the limit is set to 50 redirections. Set this option to -1 to make it unlimited.
| +| -m, --max-time <SECONDS> | Maximum time in seconds that you allow a request/response to take. This is the standard timeout.

See also [`--connect-timeout`](#connect-timeout).
| +| --no-color | Do not colorize output.
| +| --no-output | Suppress output. By default, Hurl outputs the body of the last response.
| +| --noproxy <HOST(S)> | Comma-separated list of hosts which do not use a proxy.
Override value from Environment variable no_proxy.
| +| -o, --output <FILE> | Write output to FILE instead of stdout.
| +| -x, --proxy <[PROTOCOL://]HOST[:PORT]> | Use the specified proxy.
| +| --report-junit <FILE> | Generate JUnit File.

If the FILE report already exists, it will be updated with the new test results.
| +| --report-html <DIR> | Generate HTML report in DIR.

If the HTML report already exists, it will be updated with the new test results.
| +| --resolve <HOST:PORT:ADDR> | Provide a custom address for a specific host and port pair. Using this, you can make the Hurl requests(s) use a specified address and prevent the otherwise normally resolved address to be used. Consider it a sort of /etc/hosts alternative provided on the command line.
| +| --retry | Retry requests if any error occurs (asserts, captures, runtimes etc...).
| +| --retry-interval <MILLISECONDS> | Duration in milliseconds between each retry. Default is 1000 ms.
| +| --retry-max-count <NUM> | Maximum number of retries. Set this option to -1 to make it unlimited. Default is 10.
| +| --ssl-no-revoke | (Windows) This option tells Hurl to disable certificate revocation checks. WARNING: this option loosens the SSL security, and by using this flag you ask for exactly that.
| +| --test | Activate test mode: with this, the HTTP response is not outputted anymore, progress is reported for each Hurl file tested, and a text summary is displayed when all files have been run.
| +| --to-entry <ENTRY_NUMBER> | Execute Hurl file to ENTRY_NUMBER (starting at 1).
Ignore the remaining of the file. It is useful for debugging a session.
| +| -u, --user <USER:PASSWORD> | Add basic Authentication header to each request.
| +| -A, --user-agent <NAME> | Specify the User-Agent string to send to the HTTP server.
| +| --variable <NAME=VALUE> | Define variable (name/value) to be used in Hurl templates.
| +| --variables-file <FILE> | Set properties file in which your define your variables.

Each variable is defined as name=value exactly as with [`--variable`](#variable) option.

Note that defining a variable twice produces an error.
| +| -v, --verbose | Turn on verbose output on standard error stream.
Useful for debugging.

A line starting with '>' means data sent by Hurl.
A line staring with '<' means data received by Hurl.
A line starting with '*' means additional info provided by Hurl.

If you only want HTTP headers in the output, [`-i, --include`](#include) might be the option you're looking for.
| +| --very-verbose | Turn on more verbose output on standard error stream.

In contrast to [`--verbose`](#verbose) option, this option outputs the full HTTP body request and response on standard error. In addition, lines starting with '**' are libcurl debug logs.
| +| -h, --help | Usage help. This lists all current command line options with a short description.
| +| -V, --version | Prints version information
| ## Environment @@ -810,23 +900,23 @@ Environment variables can only be specified in lowercase. Using an environment variable to set the proxy has the same effect as using the [`-x, --proxy`](#proxy) option. -Variable | Description - --- | --- -`http_proxy [protocol://][:port]` | Sets the proxy server to use for HTTP.
-`https_proxy [protocol://][:port]` | Sets the proxy server to use for HTTPS.
-`all_proxy [protocol://][:port]` | Sets the proxy server to use if no protocol-specific proxy is set.
-`no_proxy ` | List of host names that shouldn't go through any proxy.
-`HURL_name value` | Define variable (name/value) to be used in Hurl templates. This is similar than [`--variable`](#variable) and [`--variables-file`](#variables-file) options.
-`NO_COLOR` | When set to a non-empty string, do not colorize output (see [`--no-color`](#no-color) option).
+| Variable | Description | +|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `http_proxy [protocol://][:port]` | Sets the proxy server to use for HTTP.
| +| `https_proxy [protocol://][:port]` | Sets the proxy server to use for HTTPS.
| +| `all_proxy [protocol://][:port]` | Sets the proxy server to use if no protocol-specific proxy is set.
| +| `no_proxy ` | List of host names that shouldn't go through any proxy.
| +| `HURL_name value` | Define variable (name/value) to be used in Hurl templates. This is similar than [`--variable`](#variable) and [`--variables-file`](#variables-file) options.
| +| `NO_COLOR` | When set to a non-empty string, do not colorize output (see [`--no-color`](#no-color) option).
| ## Exit Codes -Value | Description - --- | --- -`1` | Failed to parse command-line options.
-`2` | Input File Parsing Error.
-`3` | Runtime error (such as failure to connect to host).
-`4` | Assert Error.
+| Value | Description | +|-------|---------------------------------------------------------| +| `1` | Failed to parse command-line options.
| +| `2` | Input File Parsing Error.
| +| `3` | Runtime error (such as failure to connect to host).
| +| `4` | Assert Error.
| ## WWW @@ -843,12 +933,12 @@ curl(1) hurlfmt(1) ### Linux -Precompiled binary is available at [hurl-1.8.0-x86_64-linux.tar.gz]: +Precompiled binary is available at [hurl-2.0.0-x86_64-linux.tar.gz]: ```shell $ INSTALL_DIR=/tmp -$ curl -sL https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-x86_64-linux.tar.gz | tar xvz -C $INSTALL_DIR -$ export PATH=$INSTALL_DIR/hurl-1.8.0:$PATH +$ curl -sL https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-x86_64-linux.tar.gz | tar xvz -C $INSTALL_DIR +$ export PATH=$INSTALL_DIR/hurl-2.0.0:$PATH ``` #### Debian / Ubuntu @@ -856,8 +946,8 @@ $ export PATH=$INSTALL_DIR/hurl-1.8.0:$PATH For Debian / Ubuntu, Hurl can be installed using a binary .deb file provided in each Hurl release. ```shell -$ curl -LO https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl_1.8.0_amd64.deb -$ sudo apt update && apt install ./hurl_1.8.0_amd64.deb +$ curl -LO https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl_2.0.0_amd64.deb +$ sudo apt update && apt install ./hurl_2.0.0_amd64.deb ``` #### Arch Linux / Manjaro @@ -870,7 +960,7 @@ $ sudo apt update && apt install ./hurl_1.8.0_amd64.deb ### macOS -Precompiled binary is available at [hurl-1.8.0-x86_64-macos.tar.gz] for x86 CPUs and [hurl-1.8.0-arm64-macos.tar.gz] for ARM CPUS. +Precompiled binary is available at [hurl-2.0.0-x86_64-macos.tar.gz] for x86 CPUs and [hurl-2.0.0-arm64-macos.tar.gz] for ARM CPUS. #### Homebrew @@ -894,11 +984,11 @@ $ sudo pkg install hurl #### Zip File -Hurl can be installed from a standalone zip file [hurl-1.8.0-win64.zip]. You will need to update your `PATH` variable. +Hurl can be installed from a standalone zip file [hurl-2.0.0-win64.zip]. You will need to update your `PATH` variable. #### Installer -An installer [hurl-1.8.0-win64-installer.exe] is also available. +An installer [hurl-2.0.0-win64-installer.exe] is also available. #### Chocolatey @@ -1011,7 +1101,7 @@ Please follow the [contrib on Windows section]. [libcurl]: https://curl.se/libcurl/ [JSON body]: https://hurl.dev/docs/request.html#json-body [XML body]: https://hurl.dev/docs/request.html#xml-body -[multiline string body]: https://hurl.dev/docs/request.html#multiline-string-body +[XML multiline string body]: https://hurl.dev/docs/request.html#multiline-string-body [predicates]: https://hurl.dev/docs/asserting-response.html#predicates [JSONPath]: https://goessner.net/articles/JsonPath/ [Basic authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#basic_authentication_scheme @@ -1022,12 +1112,13 @@ Please follow the [contrib on Windows section]. [curl]: https://curl.se [entry]: https://hurl.dev/docs/entry.html [`--test` option]: https://hurl.dev/docs/manual.html#test +[Hurl templates]: https://hurl.dev/docs/templates.html [GitHub]: https://github.com/Orange-OpenSource/hurl -[hurl-1.8.0-win64.zip]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-win64.zip -[hurl-1.8.0-win64-installer.exe]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-win64-installer.exe -[hurl-1.8.0-x86_64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-x86_64-macos.tar.gz -[hurl-1.8.0-arm64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-arm64-macos.tar.gz -[hurl-1.8.0-x86_64-linux.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-x86_64-linux.tar.gz +[hurl-2.0.0-win64.zip]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-win64.zip +[hurl-2.0.0-win64-installer.exe]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-win64-installer.exe +[hurl-2.0.0-x86_64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-x86_64-macos.tar.gz +[hurl-2.0.0-arm64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-arm64-macos.tar.gz +[hurl-2.0.0-x86_64-linux.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-x86_64-linux.tar.gz [AUR]: https://wiki.archlinux.org/index.php/Arch_User_Repository [`hurl-bin` package]: https://aur.archlinux.org/packages/hurl-bin/ [install]: https://www.rust-lang.org/tools/install diff --git a/bin/docs/build_man_md.py b/bin/docs/build_man_md.py index ce2061176..58ec0e658 100644 --- a/bin/docs/build_man_md.py +++ b/bin/docs/build_man_md.py @@ -45,7 +45,7 @@ def process_table(doc: MarkdownDoc, nodes: List[Node], col_name: str) -> None: new_nodes = [ Whitespace(content="\n"), - Paragraph(content=f"{col_name} | Description\n --- | --- \n"), + Paragraph(content=f"| {col_name} | Description |\n| --- | --- |\n"), ] h3s = [n for n in nodes if isinstance(n, Header)] @@ -78,9 +78,9 @@ def process_table(doc: MarkdownDoc, nodes: List[Node], col_name: str) -> None: paragraphs = doc.slice(first_p, next_node) paragraphs_contents = [p.content for p in paragraphs if p.content] description = "".join(paragraphs_contents) - description = description.replace("\n", "
") + description = description.replace("\n", "
") - new_node = Paragraph(content=f"{name} | {description}\n") + new_node = Paragraph(content=f"| {name} | {description} |\n") new_nodes.append(new_node) # Delete all previous options: diff --git a/contrib/npm/hurl/README.md b/contrib/npm/hurl/README.md index 19376c22a..fa4954463 100644 --- a/contrib/npm/hurl/README.md +++ b/contrib/npm/hurl/README.md @@ -4,15 +4,15 @@ Hurl is a command line tool written in Rust that runs HTTP requests defin The `@orangeopensource/hurl` package allows JavaScript developers to use Hurl in npm scripts. -Hurl can perform requests, capture values and evaluate queries on headers and body response. Hurl is very -versatile: it can be used for both fetching data and testing HTTP sessions. +It can chain requests, capture values and evaluate queries on headers and body response. Hurl is very +versatile, it can be used for fetching data and testing HTTP sessions: HTML content, REST / SOAP / GraphQL APIs, or any other XML / JSON based APIs. ```hurl # Get home: GET https://example.net -HTTP/1.1 200 +HTTP 200 [Captures] csrf_token: xpath "string(//meta[@name='_csrf_token']/@content)" @@ -20,23 +20,23 @@ csrf_token: xpath "string(//meta[@name='_csrf_token']/@content)" POST https://example.net/login?user=toto&password=1234 X-CSRF-TOKEN: {{csrf_token}} -HTTP/1.1 302 +HTTP 302 ``` Hurl can run HTTP requests but can also be used to test HTTP responses. Different types of queries and predicates are supported, from [XPath](https://en.wikipedia.org/wiki/XPath) and [JSONPath](https://goessner.net/articles/JsonPath/) on body response, to assert on status code and response headers. -It is well adapted for REST / JSON apis +It is well adapted for REST / JSON APIs ```hurl -POST https://api.example.net/tests +POST https://example.org/api/tests { "id": "4568", "evaluate": true } -HTTP/1.1 200 +HTTP 200 [Asserts] header "X-Frame-Options" == "SAMEORIGIN" jsonpath "$.status" == "RUNNING" # Check the status code @@ -44,16 +44,49 @@ jsonpath "$.tests" count == 25 # Check the number of items jsonpath "$.id" matches /\d{4}/ # Check the format of the id ``` -and HTML content +HTML content ```hurl -GET https://example.net +GET https://example.org -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "normalize-space(//head/title)" == "Hello world!" ``` +GraphQL + +~~~hurl +POST https://example.org/graphql +```graphql +{ + human(id: "1000") { + name + height(unit: FOOT) + } +} +``` +HTTP 200 +~~~ + +and even SOAP APIs + +```hurl +POST https://example.org/InStock +Content-Type: application/soap+xml; charset=utf-8 +SOAPAction: "http://www.w3.org/2003/05/soap-envelope" + + + + + + GOOG + + + +HTTP 200 +``` + ## Installation ``` diff --git a/docs/asserting-response.md b/docs/asserting-response.md index 74255bf8a..ddcd2b820 100644 --- a/docs/asserting-response.md +++ b/docs/asserting-response.md @@ -1,32 +1,60 @@ # Asserting Response -## Version - Status +## Asserts + +Asserts are used to test various properties of an HTTP response. Asserts can be implicits (such as version, status, +headers) or explicit within an `[Asserts]` section. + + +```hurl +GET https://api/example.org/cats + +HTTP 200 +Content-Type: application/json; charset=utf-8 # Implicit assert on Content-Type Hedaer +[Asserts] # Explicit asserts section +bytes count == 120 +header "Content-Type" contains "utf-8" +jsonpath "$.cats" count == 49 +jsonpath "$.cats[0].name" == "Felix" +jsonpath "$.cats[0].lives" == 9 +``` + +## Implicit asserts + +### Version - Status Expected protocol version and status code of the HTTP response. Protocol version is one of `HTTP/1.0`, `HTTP/1.1`, `HTTP/2` or -`HTTP/*`; `HTTP/*` describes any version. Note that there are no status text following the status code. +`HTTP`; `HTTP` describes any version. Note that there are no status text following the status code. ```hurl GET https://example.org/404.html - -HTTP/1.1 404 +HTTP 404 ``` -Wildcard keywords (`HTTP/*`, `*`) can be used to disable tests on protocol version and status: +Wildcard keywords `HTTP` and `*` can be used to disable tests on protocol version and status: ```hurl GET https://example.org/api/pets -HTTP/1.0 * +HTTP * # Check that response status code is > 400 and <= 500 [Asserts] status > 400 status <= 500 ``` +While `HTTP/1.0`, `HTTP/1.1` and `HTTP/2` explicitly check HTTP version: -## Headers +```hurl +# Check that our server responds with HTTP/2 +GET https://example.org/api/pets +HTTP/2 200 +``` + + +### Headers Optional list of the expected HTTP response headers that must be in the received response. @@ -43,7 +71,7 @@ POST https://example.org/login user: toto password: 12345678 -HTTP/1.1 302 +HTTP 302 Location: https://example.org/home ``` @@ -71,7 +99,7 @@ You can either test the two header values: GET https://example.org/index.html Host: example.net -HTTP/1.0 200 +HTTP 200 Set-Cookie: theme=light Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT ``` @@ -82,7 +110,7 @@ Or only one: GET https://example.org/index.html Host: example.net -HTTP/1.0 200 +HTTP 200 Set-Cookie: theme=light ``` @@ -91,9 +119,9 @@ if you want to test header value with [predicates] (like `startsWith`, `contains you can use the explicit [header assert]. -## Asserts +## Explicit asserts -Optional list of assertions on the HTTP response. Assertions can describe checks +Optional list of assertions on the HTTP response within an `[Asserts]` section. Assertions can describe checks on status code, on the received body (or part of it) and on response headers. Structure of an assert: @@ -132,31 +160,33 @@ is shared with [captures], and can be one of : - [`variable`](#variable-assert) - [`duration`](#duration-assert) -Queries, as in captures, can be refined with subqueries. [`count`] subquery can be used -with various predicates to add tests on collections sizes. +Queries are used to extract data from the HTTP response. Queries, in asserts and in captures, can be refined with [filters], like +[`count`][count] to add tests on collections sizes. ### Predicates -Predicates consist of a predicate function, and a predicate value. Predicate functions are: +Predicates consist of a predicate function and a predicate value. Predicate functions are: -- `==` (`equals`): check equality of query and predicate value -- `!=`: check that query and predicate value are different -- `>` (`greaterThan`): check that query number is greater than predicate value -- `>=` (`greaterThanOrEquals`): check that query number is greater than or equal to the predicate value -- `<` (`lessThan`): check that query number is less than that predicate value -- `<=` (`lessThanOrEquals`): check that query number is less than or equal to the predicate value -- `startsWith`: check that query starts with the predicate value (query can return a string or a binary content) -- `endsWith`: check that query ends with the predicate value (query can return a string or a binary content) -- `contains`: check that query contains the predicate value (query can return a string or a binary content) -- `includes`: check that query collections includes the predicate value -- `matches`: check that query string matches the regex pattern described by the predicate value -- `exists`: check that query returns a value -- `isInteger`: check that query returns an integer -- `isFloat`: check that query returns a float -- `isBoolean`: check that query returns a boolean -- `isString`: check that query returns a string -- `isCollection`: check that query returns a collection +| Predicate | Description | Example | +|--------------------|-------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------| +| __`==`__ | Query and predicate value are equals | `jsonpath "$.book" == "Dune"` | +| __`!=`__ | Query and predicate value are different | `jsonpath "$.color" != "red"` | +| __`>`__ | Query number is greater than predicate value | `jsonpath "$.year" > 1978` | +| __`>=`__ | Query number is greater than or equal to the predicate value | `jsonpath "$.year" >= 1978` | +| __`<`__ | Query number is less than that predicate value | `jsonpath "$.year" < 1978` | +| __`<=`__ | Query number is less than or equal to the predicate value | `jsonpath "$.year" <= 1978` | +| __`startsWith`__ | Query starts with the predicate value
Value is string or a binary content | `jsonpath "$.movie" startsWith "The"`

`bytes startsWith hex,efbbbf;` | +| __`endsWith`__ | Query ends with the predicate value
Value is string or a binary content | `jsonpath "$.movie" endsWith "Back"`

`bytes endsWith hex,ab23456;` | +| __`contains`__ | Query contains the predicate value
Value is string or a binary content | `jsonpath "$.movie" contains "Empire"`

`bytes contains hex,beef;` | +| __`includes`__ | Query collections includes the predicate value | `jsonpath "$.nooks" includes "Dune"` | +| __`matches`__ | Part of the query string matches the regex pattern described by the predicate value | `jsonpath "$.release" matches "\\d{4}"`

`jsonpath "$.release" matches /\d{4}/` | +| __`exists`__ | Query returns a value | `jsonpath "$.book" exists` | +| __`isInteger`__ | Query returns an integer | `jsonpath "$.count" isInteger` | +| __`isFloat`__ | Query returns a float | `jsonpath "$.height" isFloat` | +| __`isBoolean`__ | Query returns a boolean | `jsonpath "$.suceeded" isBoolean` | +| __`isString`__ | Query returns a string | `jsonpath "$.name" isString` | +| __`isCollection`__ | Query returns a collection | `jsonpath "$.books" isCollection` | Each predicate can be negated by prefixing it with `not` (for instance, `not contains` or `not exists`) @@ -170,7 +200,7 @@ Each predicate can be negated by prefixing it with `not` (for instance, `not con -A predicate values is typed, and can be a string, a boolean, a number, a bytestream, `null` or a collection. Note that +A predicate value is typed, and can be a string, a boolean, a number, a bytestream, `null` or a collection. Note that `"true"` is a string, whereas `true` is a boolean. For instance, to test the presence of a h1 node in an HTML response, the following assert can be used: @@ -178,7 +208,7 @@ For instance, to test the presence of a h1 node in an HTML response, the followi ```hurl GET https://example.org/home -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "boolean(count(//h1))" == true xpath "//h1" exists # Equivalent but simpler @@ -201,7 +231,7 @@ The following assert will check the value of the `data-visible` attribute: ```hurl GET https://example.org/home -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//article/@data-visible)" == "true" ``` @@ -209,14 +239,14 @@ xpath "string(//article/@data-visible)" == "true" In this case, the XPath query `string(//article/@data-visible)` returns a string, so the predicate value must be a string. -The predicate function `equals` can work with string, number or boolean while `matches`, `startWith` and `contains` work -only on string. If a query returns a number, a `contains` predicate will raise a runner error. +The predicate function `equals` can be used with string, numbers or booleans; `startWith` and `contains` can only +be used with strings and bytes, while `matches` only works on string. If a query returns a number, using a `matches` predicate will cause a runner error. ```hurl # A really well tested web page... GET https://example.org/home -HTTP/1.1 200 +HTTP 200 [Asserts] header "Content-Type" contains "text/html" header "Last-Modified" == "Wed, 21 Oct 2015 07:28:00 GMT" @@ -234,22 +264,23 @@ function and value. ```hurl GET https://example.org -HTTP/1.1 * +HTTP * [Asserts] status < 300 ``` ### Header assert -Check the value of a received HTTP response header. Header assert consists of the keyword `header` followed by a predicate -function and value. +Check the value of a received HTTP response header. Header assert consists of the keyword `header` followed by the value +of the header, a predicate function and a predicate value. ```hurl GET https://example.org -HTTP/1.1 302 +HTTP 302 [Asserts] header "Location" contains "www.example.net" +header "Last-Modified" matches /\d{2} [a-z-A-Z]{3} \d{4}/ ``` If there are multiple headers with the same name, the header assert returns a collection, so `count`, `includes` can be @@ -261,7 +292,7 @@ Let's say we have this request and response: > GET /hello HTTP/1.1 > Host: example.org > Accept: */* -> User-Agent: hurl/1.8.0-SNAPSHOT +> User-Agent: hurl/2.0.0-SNAPSHOT > * Response: (received 12 bytes in 11 ms) * @@ -279,7 +310,7 @@ One can use explicit header asserts: ```hurl GET https://example.org/hello -HTTP/* 200 +HTTP 200 [Asserts] header "Vary" count == 2 header "Vary" includes "User-Agent" @@ -291,7 +322,7 @@ Or implicit header asserts: ```hurl GET https://example.org/hello -HTTP/* 200 +HTTP 200 Vary: User-Agent Vary: Content-Type ``` @@ -306,7 +337,7 @@ GET https://example.org/redirecting [Options] location: true -HTTP/* 200 +HTTP 200 [Asserts] url == "https://example.org/redirected" ``` @@ -325,7 +356,7 @@ Cookie attributes value can be checked by using the following format: ```hurl GET http://localhost:8000/cookies/set -HTTP/1.0 200 +HTTP 200 # Explicit check of Set-Cookie header value. If the attributes are # not in this exact order, this assert will fail. @@ -361,13 +392,11 @@ value. The encoding used to decode the body is based on the `charset` value in t ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 [Asserts] body contains "

Welcome!

" ``` -> Precise the encoding used to decode the text body. - ### Bytes assert Check the value of the received HTTP response body as a bytestream. Body assert @@ -376,9 +405,11 @@ consists of the keyword `bytes` followed by a predicate function and value. ```hurl GET https://example.org/data.bin -HTTP/* 200 +HTTP 200 [Asserts] bytes startsWith hex,efbbbf; +bytes count == 12424 +header "Content-Length" == "12424" ``` ### XPath assert @@ -418,9 +449,8 @@ With Hurl, we can write multiple XPath asserts describing the DOM content: ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 Content-Type: text/html; charset=UTF-8 - [Asserts] xpath "string(/html/head/title)" contains "Example" # Check title xpath "count(//p)" == 2 # Check the number of

@@ -446,7 +476,7 @@ This XML response can be tested with the following Hurl file: ```hurl GET http://localhost:8000/assert-xpath -HTTP/1.0 200 +HTTP 200 [Asserts] xpath "string(//bk:book/bk:title)" == "Cheaper by the Dozen" @@ -467,7 +497,7 @@ namespaces. ### JSONPath assert Check the value of a [JSONPath] query on the received HTTP body decoded as a JSON -document. Body assert consists of the keyword `jsonpath` followed by a predicate +document. JSONPath assert consists of the keyword `jsonpath` followed by a predicate function and value. Let's say we want to check this JSON response: @@ -501,7 +531,7 @@ With Hurl, we can write multiple JSONPath asserts describing the DOM content: ```hurl GET http://httpbin.org/json -HTTP/1.1 200 +HTTP 200 [Asserts] jsonpath "$.slideshow.author" == "Yours Truly" jsonpath "$.slideshow.slides[0].title" contains "Wonder" @@ -520,7 +550,7 @@ the readability: ```hurl GET https://sample.org/hello -HTTP/1.0 200 +HTTP 200 [Asserts] # Predicate value with matches predicate: jsonpath "$.date" matches "^\\d{4}-\\d{2}-\\d{2}$" @@ -537,11 +567,19 @@ Check that the HTTP received body, decoded as text, matches a regex pattern. ```hurl GET https://sample.org/hello -HTTP/1.0 200 +HTTP 200 [Asserts] -regex "^\\d{4}-\\d{2}-\\d{2}$" == "2018-12-31" +regex "^(\\d{4}-\\d{2}-\\d{2})$" == "2018-12-31" +# Same assert as previous using regex literals +regex /^(\d{4}-\d{2}-\d{2})$/ == "2018-12-31" ``` +The regex pattern must have at least one capture group, otherwise the +assert will fail. The assertion is done on the captured group value. When the regex pattern is a double-quoted string, +metacharacters beginning with a backslash in the pattern (like `\d`, `\s`) must be escaped; literal pattern enclosed by +`/` can also be used to avoid metacharacters escaping. + + ### SHA-256 assert Check response body [SHA-256] hash. @@ -549,7 +587,7 @@ Check response body [SHA-256] hash. ```hurl GET https://example.org/data.tar.gz -HTTP/* * +HTTP 200 [Asserts] sha256 == hex,039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81; ``` @@ -561,7 +599,7 @@ Check response body [MD5] hash. ```hurl GET https://example.org/data.tar.gz -HTTP/* * +HTTP 200 [Asserts] md5 == hex,ed076287532e86365e841e92bfc50d8c; ``` @@ -572,7 +610,8 @@ md5 == hex,ed076287532e86365e841e92bfc50d8c; ```hurl # Test that the XML endpoint return 200 pets GET https://example.org/api/pets -HTTP/* 200 + +HTTP 200 [Captures] pets: xpath "//pets" [Asserts] @@ -586,37 +625,11 @@ Check the total duration (sending plus receiving time) of the HTTP transaction. ```hurl GET https://sample.org/helloworld -HTTP/1.0 200 +HTTP 200 [Asserts] duration < 1000 # Check that response time is less than one second ``` -## Filters - -Optionally, asserts can be refined using filters `count` and `regex`. - -### Count filter - -```hurl -GET https://pets.org/cats/cutest - -HTTP/1.0 200 -[Asserts] -jsonpath "$.cats" count == 12 -``` - -### Regex filter - -```hurl -GET https://pets.org/cats/cutest - -HTTP/1.0 200 -# Cat name are structured like this `meow + id`: for instance `meow123456` -[Asserts] -jsonpath "$.cats[0].name" regex /meow(\d+)/ == "123456" -``` - - ## Body Optional assertion on the received HTTP response body. Body section can be seen @@ -634,7 +647,7 @@ the body byte content to check. # Get a doggy thing: GET https://example.org/api/dogs/{{dog-id}} -HTTP/1.1 200 +HTTP 200 { "id": 0, "name": "Frieda", @@ -645,12 +658,32 @@ HTTP/1.1 200 } ``` +JSON response body can be seen as syntactic sugar of [multiline string body] with `json` identifier: + +~~~hurl +# Get a doggy thing: +GET https://example.org/api/dogs/{{dog-id}} + +HTTP 200 +```json +{ + "id": 0, + "name": "Frieda", + "picture": "images/scottish-terrier.jpeg", + "age": 3, + "breed": "Scottish Terrier", + "location": "Lisco, Alabama" +} +``` +~~~ + + ### XML body ~~~hurl GET https://example.org/api/catalog -HTTP/1.1 200 +HTTP 200 @@ -664,12 +697,34 @@ HTTP/1.1 200 ~~~ +XML response body can be seen as syntactic sugar of [multiline string body] with `xml` identifier: + +~~~hurl +GET https://example.org/api/catalog + +HTTP 200 +```xml + + + + Gambardella, Matthew + XML Developer's Guide + Computer + 44.95 + 2000-10-01 + An in-depth look at creating applications with XML. + + +``` +~~~ + + ### Multiline string body ~~~hurl GET https://example.org/models -HTTP/1.1 200 +HTTP 200 ``` Year,Make,Model,Description,Price 1997,Ford,E350,"ac, abs, moon",3000.00 @@ -689,41 +744,28 @@ line3 ``` ~~~ -is evaluated as "line1\nline2\nline3\n". +#### Oneline string body +For text based response body that do not contain newlines, one can use oneline string, started and ending with `. -To construct an empty string : +~~~hurl +POST https://example.org/helloworld -~~~ -``` -``` +HTTP 200 +`Hello world!` ~~~ -or - -~~~ -`````` -~~~ - - -Finally, multiline can be used without any newline: - -~~~ -```line``` -~~~ - -is evaluated as "line". ### Base64 body -Base64 body assert starts with `base64,` and end with `;`. MIME's Base64 encoding +Base64 response body assert starts with `base64,` and end with `;`. MIME's Base64 encoding is supported (newlines and white spaces may be present anywhere but are to be ignored on decoding), and `=` padding characters might be added. ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIG FkaXBpc2NpbmcgZWxpdC4gSW4gbWFsZXN1YWRhLCBuaXNsIHZlbCBkaWN0dW0g aGVuZHJlcml0LCBlc3QganVzdG8gYmliZW5kdW0gbWV0dXMsIG5lYyBydXRydW @@ -738,7 +780,7 @@ can be used. File body starts with `file,` and ends with `;`` ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 file,data.bin; ``` @@ -760,9 +802,11 @@ of all file nodes. [XML]: https://en.wikipedia.org/wiki/XML [Base64]: https://en.wikipedia.org/wiki/Base64 [`--file-root` option]: /docs/manual.md#file-root -[`count`]: /docs/capturing-response.md#count-subquery [Javascript-like Regular expression syntax]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions [MD5]: https://en.wikipedia.org/wiki/MD5 [SHA-256]: https://en.wikipedia.org/wiki/SHA-2 [options]: /docs/request.md#options [`--location` option]: /docs/manual.md#location +[multiline string body]: #multiline-string-body +[filters]: /docs/filters.md +[count]: /docs/filters.md#count \ No newline at end of file diff --git a/docs/assets/cast/hurl.cast b/docs/assets/cast/hurl.cast new file mode 100644 index 000000000..6ebd76209 --- /dev/null +++ b/docs/assets/cast/hurl.cast @@ -0,0 +1,250 @@ +{"version": 2, "width": 80, "height": 25, "timestamp": 1665239255, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color", "PROMPT": "%F{cyan}$%f "}} +[0.01621, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] +[0.027176, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[36m$\u001b[39m \u001b[K\u001b[?2004h"] +[0.51818, "o", "v"] +[0.667008, "o", "\bvi"] +[0.906839, "o", "m"] +[0.967164, "o", " "] +[1.297275, "o", "s"] +[1.509441, "o", "t"] +[1.688824, "o", "a"] +[1.824537, "o", "r"] +[2.318819, "o", "w"] +[2.527648, "o", "a"] +[2.708786, "o", "r"] +[2.798336, "o", "s"] +[3.247485, "o", "."] +[3.578633, "o", "h"] +[3.757589, "o", "u"] +[3.846672, "o", "r"] +[4.088367, "o", "l"] +[4.95909, "o", "\u001b[?2004l\r\r\n"] +[5.010246, "o", "\u001b[?1049h\u001b[>4;2m\u001b[?1h\u001b=\u001b[?2004h\u001b[?1004h\u001b[1;25r\u001b[?12h\u001b[?12l\u001b[22;2t\u001b[22;1t"] +[5.010721, "o", "\u001b[27m\u001b[29m\u001b[m\u001b[H\u001b[2J\u001b[?25l\u001b[25;1H\"starwars.hurl\" [New]"] +[5.015574, "o", "\u001b[2;1H▽\u001b[6n\u001b[2;1H \u001b[3;1H\u001bPzz\u001b\\\u001b[0%m\u001b[6n\u001b[3;1H \u001b[1;1H\u001b[>c"] +[5.015583, "o", "\u001b]10;?\u0007\u001b]11;?\u0007"] +[5.016023, "o", "\u001b[1;1H\u001b[38;5;242m 1 \u001b[m\r\n\u001b[94m~ \u001b[3;1H~ \u001b[4;1H~ \u001b[5;1H~ \u001b[6;1H~ \u001b[7;1H~ \u001b[8;1H~ \u001b[9;1H~ \u001b[10;1H~ \u001b[11;1H~ \u001b[12;1H~ \u001b[13;1H~ "] +[5.016049, "o", " \u001b[14;1H~ \u001b[15;1H~ \u001b[16;1H~ \u001b[17;1H~ \u001b[18;1H~ \u001b[19;1H~ \u001b[20;1H~ \u001b[21;1H~ \u001b[22;1H~ \u001b[23;1H~ \u001b[m\u001b[24;1H\u001b[38;5;238m\u001b[48;5;117m NORMAL "] +[5.016131, "o", "\u001b[m\u001b[38;5;252m\u001b[48;5;240m starwars.hurl \u001b[m\u001b[38;5;248m\u001b[48;5;238m unix | utf-8 | hurl \u001b[m\u001b[38;5;247m\u001b[48;5;240m 100% \u001b[m\u001b[38;5;238m\u001b[48;5;244m 0:0 \u001b[1;5H\u001b[?25h"] +[5.016144, "o", "\u001b[?12$p"] +[5.980583, "o", "\u001b[m\u001b[24;1H\u001b[38;5;238m\u001b[48;5;119m INSERT \u001b[m\u001b[69C\u001b[38;5;238m\u001b[48;5;244m1\u001b[1;5H\u001b[?25l\u001b[?25h"] +[6.339754, "o", "\u001b[?25l\u001b[mG\u001b[24;24H\u001b[38;5;252m\u001b[48;5;240m| + \u001b[m\u001b[48C\u001b[38;5;238m\u001b[48;5;244m1:2\u001b[1;6H\u001b[?25h"] +[6.426642, "o", "\u001b[?25l\u001b[mE\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m3\u001b[1;7H\u001b[?25h"] +[6.580036, "o", "\u001b[?25l\u001b[m\b\b\u001b[93mGET\u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m4\u001b[1;8H\u001b[?25h"] +[6.656322, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m5\u001b[1;9H\u001b[?25h"] +[7.720245, "o", "\u001b[?25l\u001b[mh\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m6\u001b[1;10H\u001b[?25h"] +[7.959788, "o", "\u001b[?25l\u001b[mt\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m7\u001b[1;11H\u001b[?25h"] +[8.064465, "o", "\u001b[?25l\u001b[mt\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m8\u001b[1;12H\u001b[?25h"] +[8.350182, "o", "\u001b[?25l\u001b[mp\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m9\u001b[1;13H\u001b[?25h"] +[8.530041, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m10\u001b[1;14H\u001b[?25h"] +[8.82781, "o", "\u001b[?25l\u001b[m:\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[1;15H\u001b[?25h"] +[9.159365, "o", "\u001b[?25l\u001b[m/\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[1;16H\u001b[?25h"] +[9.29217, "o", "\u001b[?25l\u001b[m/\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[1;17H\u001b[?25h"] +[9.608683, "o", "\u001b[?25l\u001b[ms\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[1;18H\u001b[?25h"] +[9.772887, "o", "\u001b[?25l\u001b[mw\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[1;19H\u001b[?25h"] +[9.998823, "o", "\u001b[?25l\u001b[ma\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m6\u001b[1;20H\u001b[?25h"] +[10.18035, "o", "\u001b[?25l\u001b[mp\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m7\u001b[1;21H\u001b[?25h"] +[10.222808, "o", "\u001b[?25l\u001b[mi\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m8\u001b[1;22H\u001b[?25h"] +[10.599361, "o", "\u001b[?25l\u001b[m.\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m9\u001b[1;23H\u001b[?25h"] +[10.809162, "o", "\u001b[?25l\u001b[md\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m20\u001b[1;24H\u001b[?25h"] +[10.959103, "o", "\u001b[?25l\u001b[me\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[1;25H\u001b[?25h"] +[11.034188, "o", "\u001b[?25l\u001b[mv\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[1;26H\u001b[?25h"] +[11.52938, "o", "\u001b[?25l\u001b[m/\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[1;27H\u001b[?25h"] +[11.769769, "o", "\u001b[?25l\u001b[ma\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[1;28H\u001b[?25h"] +[11.979865, "o", "\u001b[?25l\u001b[mp\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[1;29H\u001b[?25h"] +[11.993141, "o", "\u001b[?25l\u001b[mi\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m6\u001b[1;30H\u001b[?25h"] +[12.444503, "o", "\u001b[?25l\u001b[m/\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m7\u001b[1;31H\u001b[?25h"] +[12.792815, "o", "\u001b[?25l\u001b[mp\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m8\u001b[1;32H\u001b[?25h"] +[12.938877, "o", "\u001b[?25l\u001b[me\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m9\u001b[1;33H\u001b[?25h"] +[13.149924, "o", "\u001b[?25l\u001b[mo\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m30\u001b[1;34H\u001b[?25h"] +[13.360561, "o", "\u001b[?25l\u001b[mp\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[1;35H\u001b[?25h"] +[13.509042, "o", "\u001b[?25l\u001b[ml\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[1;36H\u001b[?25h"] +[13.644134, "o", "\u001b[?25l\u001b[me\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[1;37H\u001b[?25h"] +[14.230904, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 2 \u001b[m\u001b[2;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m2:1 \u001b[2;5H\u001b[?25h"] +[14.366055, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 3 \u001b[m\u001b[3;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m3\u001b[3;5H\u001b[?25h"] +[16.118006, "o", "\u001b[?25l\u001b[mH\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m2\u001b[3;6H\u001b[?25h"] +[16.361333, "o", "\u001b[?25l\u001b[mT\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m3\u001b[3;7H\u001b[?25h"] +[16.479912, "o", "\u001b[?25l\u001b[mT\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m4\u001b[3;8H\u001b[?25h"] +[16.765441, "o", "\u001b[?25l\u001b[mP\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m5\u001b[3;9H\u001b[?25h"] +[17.089972, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m8\u001b[3;10H\u001b[?25h"] +[17.479949, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m2\u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m9\u001b[3;11H\u001b[?25h"] +[17.750065, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m0\u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m10\u001b[3;12H\u001b[?25h"] +[17.885149, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m0\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[3;13H\u001b[?25h"] +[18.938288, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 4 \u001b[m\u001b[4;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m4:1 \u001b[4;5H\u001b[?25h"] +[19.930771, "o", "\u001b[?25l\u001b[m[\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m2\u001b[4;6H\u001b[?25h"] +[20.469027, "o", "\u001b[?25l\u001b[mA\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m3\u001b[4;7H\u001b[?25h"] +[20.777164, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m4\u001b[4;8H\u001b[?25h"] +[20.903673, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m5\u001b[4;9H\u001b[?25h"] +[21.160428, "o", "\u001b[?25l\u001b[me\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m6\u001b[4;10H\u001b[?25h"] +[21.368903, "o", "\u001b[?25l\u001b[mr\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m7\u001b[4;11H\u001b[?25h"] +[21.609942, "o", "\u001b[?25l\u001b[mt\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m8\u001b[4;12H\u001b[?25h"] +[21.775268, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m9\u001b[4;13H\u001b[?25h"] +[22.688437, "o", "\u001b[?25l\u001b[m\u001b[4;5H\u001b[95m[Asserts]\u001b[m\u001b[4;5H\u001b[95m\u001b[46m[\u001b[7C]\u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m10\u001b[4;14H\u001b[?25h"] +[22.9887, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 5 \u001b[m\u001b[5;5H\u001b[K\u001b[4;5H\u001b[95m[\u001b[7C]\u001b[m\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m5:1 \u001b[5;5H\u001b[?25h"] +[23.68264, "o", "\u001b[?25l\u001b[mj\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m2\u001b[5;6H\u001b[?25h"] +[23.78524, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m3\u001b[5;7H\u001b[?25h"] +[23.919476, "o", "\u001b[?25l\u001b[mo\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m4\u001b[5;8H\u001b[?25h"] +[23.980456, "o", "\u001b[?25l\u001b[mn\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m5\u001b[5;9H\u001b[?25h"] +[24.189599, "o", "\u001b[?25l\u001b[mp\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m6\u001b[5;10H\u001b[?25h"] +[24.291845, "o", "\u001b[?25l\u001b[ma\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m7\u001b[5;11H\u001b[?25h"] +[24.45999, "o", "\u001b[?25l\u001b[mt\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m8\u001b[5;12H\u001b[?25h"] +[24.639712, "o", "\u001b[?25l\u001b[mh\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m9\u001b[5;13H\u001b[?25h"] +[24.684401, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m10\u001b[5;14H\u001b[?25h"] +[25.000139, "o", "\u001b[?25l\u001b[m\u001b[92m\"\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[5;15H\u001b[?25h"] +[25.51158, "o", "\u001b[?25l\u001b[m\u001b[92m$\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[5;16H\u001b[?25h"] +[25.8998, "o", "\u001b[?25l\u001b[m\u001b[92m.\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[5;17H\u001b[?25h"] +[26.138606, "o", "\u001b[?25l\u001b[m\u001b[92mc\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[5;18H\u001b[?25h"] +[26.318844, "o", "\u001b[?25l\u001b[m\u001b[92mo\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[5;19H\u001b[?25h"] +[26.349408, "o", "\u001b[?25l\u001b[m\u001b[92mu\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m6\u001b[5;20H\u001b[?25h"] +[26.589545, "o", "\u001b[?25l\u001b[m\u001b[92mn\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m7\u001b[5;21H\u001b[?25h"] +[26.666032, "o", "\u001b[?25l\u001b[m\u001b[92mt\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m8\u001b[5;22H\u001b[?25h"] +[26.98015, "o", "\u001b[?25l\u001b[m\u001b[92m\"\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m9\u001b[5;23H\u001b[?25h"] +[27.400301, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m20\u001b[5;24H\u001b[?25h"] +[27.940385, "o", "\u001b[?25l\u001b[m=\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[5;25H\u001b[?25h"] +[28.058324, "o", "\u001b[?25l\u001b[m=\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[5;26H\u001b[?25h"] +[28.330285, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[5;27H\u001b[?25h"] +[28.869495, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m8\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[5;28H\u001b[?25h"] +[29.16975, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m2\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[5;29H\u001b[?25h"] +[29.559967, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 6 \u001b[m\u001b[6;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m6:1 \u001b[6;5H\u001b[?25h"] +[29.679857, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 7 \u001b[m\u001b[7;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m7\u001b[7;5H\u001b[?25h"] +[29.890601, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 8 \u001b[m\u001b[8;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m8\u001b[8;5H\u001b[?25h"] +[31.299997, "o", "\u001b[?25l\u001b[mG\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m2\u001b[8;6H\u001b[?25h"] +[31.418839, "o", "\u001b[?25l\u001b[mE\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m3\u001b[8;7H\u001b[?25h"] +[31.538763, "o", "\u001b[?25l\u001b[m\b\b\u001b[93mGET\u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m4\u001b[8;8H\u001b[?25h"] +[31.614974, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m5\u001b[8;9H\u001b[?25h"] +[32.680907, "o", "\u001b[?25l\u001b[mh\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m6\u001b[8;10H\u001b[?25h"] +[32.890015, "o", "\u001b[?25l\u001b[mt\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m7\u001b[8;11H\u001b[?25h"] +[33.008892, "o", "\u001b[?25l\u001b[mt\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m8\u001b[8;12H\u001b[?25h"] +[33.340299, "o", "\u001b[?25l\u001b[mp\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m9\u001b[8;13H\u001b[?25h"] +[33.487104, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m10\u001b[8;14H\u001b[?25h"] +[33.702452, "o", "\u001b[?25l\u001b[m:\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[8;15H\u001b[?25h"] +[33.984328, "o", "\u001b[?25l\u001b[m/\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[8;16H\u001b[?25h"] +[34.119828, "o", "\u001b[?25l\u001b[m/\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[8;17H\u001b[?25h"] +[34.328978, "o", "\u001b[?25l\u001b[ms\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[8;18H\u001b[?25h"] +[34.508459, "o", "\u001b[?25l\u001b[mw\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[8;19H\u001b[?25h"] +[34.690022, "o", "\u001b[?25l\u001b[ma\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m6\u001b[8;20H\u001b[?25h"] +[34.870277, "o", "\u001b[?25l\u001b[mp\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m7\u001b[8;21H\u001b[?25h"] +[34.94284, "o", "\u001b[?25l\u001b[mi\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m8\u001b[8;22H\u001b[?25h"] +[35.271978, "o", "\u001b[?25l\u001b[m.\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m9\u001b[8;23H\u001b[?25h"] +[35.530057, "o", "\u001b[?25l\u001b[md\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m20\u001b[8;24H\u001b[?25h"] +[35.679772, "o", "\u001b[?25l\u001b[me\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[8;25H\u001b[?25h"] +[35.785471, "o", "\u001b[?25l\u001b[mv\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[8;26H\u001b[?25h"] +[36.234008, "o", "\u001b[?25l\u001b[m/\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[8;27H\u001b[?25h"] +[36.429984, "o", "\u001b[?25l\u001b[ma\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[8;28H\u001b[?25h"] +[36.639217, "o", "\u001b[?25l\u001b[mp\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[8;29H\u001b[?25h"] +[36.700511, "o", "\u001b[?25l\u001b[mi\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m6\u001b[8;30H\u001b[?25h"] +[37.179882, "o", "\u001b[?25l\u001b[m/\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m7\u001b[8;31H\u001b[?25h"] +[38.199234, "o", "\u001b[?25l\u001b[mp\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m8\u001b[8;32H\u001b[?25h"] +[38.320493, "o", "\u001b[?25l\u001b[me\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m9\u001b[8;33H\u001b[?25h"] +[38.500165, "o", "\u001b[?25l\u001b[mo\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m30\u001b[8;34H\u001b[?25h"] +[38.737671, "o", "\u001b[?25l\u001b[mp\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[8;35H\u001b[?25h"] +[38.889822, "o", "\u001b[?25l\u001b[ml\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[8;36H\u001b[?25h"] +[39.010086, "o", "\u001b[?25l\u001b[me\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[8;37H\u001b[?25h"] +[39.354628, "o", "\u001b[?25l\u001b[m/\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[8;38H\u001b[?25h"] +[39.669139, "o", "\u001b[?25l\u001b[m1\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[8;39H\u001b[?25h"] +[40.300656, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 9 \u001b[m\u001b[9;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m9:1 \u001b[9;5H\u001b[?25h"] +[40.405191, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 10 \u001b[m\u001b[10;5H\u001b[K\u001b[24;75H\u001b[38;5;238m\u001b[48;5;244m10\u001b[10;5H\u001b[?25h"] +[41.200373, "o", "\u001b[?25l\u001b[mH\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m2\u001b[10;6H\u001b[?25h"] +[41.409986, "o", "\u001b[?25l\u001b[mT\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m3\u001b[10;7H\u001b[?25h"] +[41.543744, "o", "\u001b[?25l\u001b[mT\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m4\u001b[10;8H\u001b[?25h"] +[41.888207, "o", "\u001b[?25l\u001b[mP\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m5\u001b[10;9H\u001b[?25h"] +[42.466984, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m8\u001b[10;10H\u001b[?25h"] +[42.885714, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m2\u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m9\u001b[10;11H\u001b[?25h"] +[43.09993, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m0\u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m10\u001b[10;12H\u001b[?25h"] +[43.750093, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m0\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[10;13H\u001b[?25h"] +[44.379124, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 11 \u001b[m\u001b[11;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m1:1 \u001b[11;5H\u001b[?25h"] +[45.520172, "o", "\u001b[?25l\u001b[m[\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m2\u001b[11;6H\u001b[?25h"] +[46.331364, "o", "\u001b[?25l\u001b[mA\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m3\u001b[11;7H\u001b[?25h"] +[47.410577, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m4\u001b[11;8H\u001b[?25h"] +[47.54615, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m5\u001b[11;9H\u001b[?25h"] +[47.800418, "o", "\u001b[?25l\u001b[me\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m6\u001b[11;10H\u001b[?25h"] +[47.979125, "o", "\u001b[?25l\u001b[mr\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m7\u001b[11;11H\u001b[?25h"] +[48.188143, "o", "\u001b[?25l\u001b[mt\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m8\u001b[11;12H\u001b[?25h"] +[48.355861, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m9\u001b[11;13H\u001b[?25h"] +[49.001936, "o", "\u001b[?25l\u001b[m\u001b[11;5H\u001b[95m[Asserts]\u001b[m\u001b[11;5H\u001b[95m\u001b[46m[\u001b[7C]\u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m10\u001b[11;14H\u001b[?25h"] +[49.327319, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 12 \u001b[m\u001b[12;5H\u001b[K\u001b[11;5H\u001b[95m[\u001b[7C]\u001b[m\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m2:1 \u001b[12;5H\u001b[?25h"] +[50.02065, "o", "\u001b[?25l\u001b[mj\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m2\u001b[12;6H\u001b[?25h"] +[50.288374, "o", "\u001b[?25l\u001b[ms\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m3\u001b[12;7H\u001b[?25h"] +[50.619446, "o", "\u001b[?25l\u001b[mo\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m4\u001b[12;8H\u001b[?25h"] +[50.646937, "o", "\u001b[?25l\u001b[mn\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m5\u001b[12;9H\u001b[?25h"] +[50.859392, "o", "\u001b[?25l\u001b[mp\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m6\u001b[12;10H\u001b[?25h"] +[50.979905, "o", "\u001b[?25l\u001b[ma\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m7\u001b[12;11H\u001b[?25h"] +[51.160997, "o", "\u001b[?25l\u001b[mt\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m8\u001b[12;12H\u001b[?25h"] +[51.370097, "o", "\u001b[?25l\u001b[mh\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m9\u001b[12;13H\u001b[?25h"] +[51.415244, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m10\u001b[12;14H\u001b[?25h"] +[51.700144, "o", "\u001b[?25l\u001b[m\u001b[92m\"\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[12;15H\u001b[?25h"] +[52.360838, "o", "\u001b[?25l\u001b[m\u001b[92m$\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[12;16H\u001b[?25h"] +[52.809737, "o", "\u001b[?25l\u001b[m\u001b[92m.\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[12;17H\u001b[?25h"] +[53.470085, "o", "\u001b[?25l\u001b[m\u001b[92mn\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[12;18H\u001b[?25h"] +[53.560389, "o", "\u001b[?25l\u001b[m\u001b[92ma\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[12;19H\u001b[?25h"] +[53.800169, "o", "\u001b[?25l\u001b[m\u001b[92mm\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m6\u001b[12;20H\u001b[?25h"] +[53.873787, "o", "\u001b[?25l\u001b[m\u001b[92me\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m7\u001b[12;21H\u001b[?25h"] +[54.13006, "o", "\u001b[?25l\u001b[m\u001b[92m\"\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m8\u001b[12;22H\u001b[?25h"] +[54.430549, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m9\u001b[12;23H\u001b[?25h"] +[54.999008, "o", "\u001b[?25l\u001b[m=\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m20\u001b[12;24H\u001b[?25h"] +[55.103269, "o", "\u001b[?25l\u001b[m=\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[12;25H\u001b[?25h"] +[55.419937, "o", "\u001b[?25l\u001b[m\u001b[38;5;81m \u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[12;26H\u001b[?25h"] +[55.541378, "o", "\u001b[?25l\u001b[m\u001b[92m\"\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[12;27H\u001b[?25h"] +[56.169023, "o", "\u001b[?25l\u001b[m\u001b[92mD\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[12;28H\u001b[?25h"] +[56.530119, "o", "\u001b[?25l\u001b[m\u001b[92ma\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[12;29H\u001b[?25h"] +[56.66352, "o", "\u001b[?25l\u001b[m\u001b[92mr\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m6\u001b[12;30H\u001b[?25h"] +[56.888287, "o", "\u001b[?25l\u001b[m\u001b[92mt\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m7\u001b[12;31H\u001b[?25h"] +[57.217614, "o", "\u001b[?25l\u001b[m\u001b[92mh\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m8\u001b[12;32H\u001b[?25h"] +[57.729172, "o", "\u001b[?25l\u001b[m\u001b[92m \u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m9\u001b[12;33H\u001b[?25h"] +[58.089175, "o", "\u001b[?25l\u001b[m\u001b[92mV\u001b[m\u001b[24;78H\u001b[38;5;238m\u001b[48;5;244m30\u001b[12;34H\u001b[?25h"] +[58.810289, "o", "\u001b[?25l\u001b[m\u001b[92ma\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m1\u001b[12;35H\u001b[?25h"] +[59.050431, "o", "\u001b[?25l\u001b[m\u001b[92md\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m2\u001b[12;36H\u001b[?25h"] +[59.230771, "o", "\u001b[?25l\u001b[m\u001b[92me\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m3\u001b[12;37H\u001b[?25h"] +[59.407561, "o", "\u001b[?25l\u001b[m\u001b[92mr\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m4\u001b[12;38H\u001b[?25h"] +[59.619514, "o", "\u001b[?25l\u001b[m\u001b[92m\"\u001b[m\u001b[24;79H\u001b[38;5;238m\u001b[48;5;244m5\u001b[12;39H\u001b[?25h"] +[60.251408, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 13 \u001b[m\u001b[13;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m3:1 \u001b[13;5H\u001b[?25h"] +[60.400358, "o", "\u001b[?25l\u001b[m\r\n\u001b[38;5;242m 14 \u001b[m\u001b[14;5H\u001b[K\u001b[24;76H\u001b[38;5;238m\u001b[48;5;244m4\u001b[14;5H\u001b[?25h"] +[61.870358, "o", "\u001b[m\u001b[24;1H\u001b[38;5;238m\u001b[48;5;117m NORMAL \u001b[m\u001b[69C\u001b[38;5;238m\u001b[48;5;244m0\u001b[14;5H\u001b[?25l\u001b[m\u001b[25;1H\u001b[K\u001b[25;1H:\u001b[?25h"] +[62.003726, "o", "w"] +[62.199186, "o", "q"] +[62.303996, "o", "\r"] +[62.305851, "o", "\u001b[?25l\u001b[?2004l\u001b[>4;m\"starwars.hurl\""] +[62.327041, "o", " [New] 14L, 176B written"] +[62.331626, "o", "\r\u001b[23;2t\u001b[23;1t\r\r\n\u001b[?1004l\u001b[?2004l\u001b[?1l\u001b>\u001b[?25h\u001b[>4;m\u001b[?1049l"] +[62.333658, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] +[62.352147, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[36m$\u001b[39m \u001b[K\u001b[?2004h"] +[63.369186, "o", "h"] +[63.549714, "o", "\bhu"] +[64.062416, "o", "r"] +[64.222636, "o", "l"] +[64.298216, "o", " "] +[64.627363, "o", "-"] +[64.748937, "o", "-"] +[65.106564, "o", "t"] +[65.167739, "o", "e"] +[65.347715, "o", "s"] +[65.438304, "o", "t"] +[65.498885, "o", " "] +[65.963696, "o", "*"] +[66.308602, "o", "."] +[66.608382, "o", "h"] +[66.789524, "o", "u"] +[66.862967, "o", "r"] +[67.012863, "o", "l"] +[67.749707, "o", "\u001b[?2004l\r\r\n"] +[67.760315, "o", "\u001b[1mbasic.hurl\u001b[0m: \u001b[1;36mRunning\u001b[0m [1/8]\r\n"] +[68.192546, "o", "\u001b[1mbasic.hurl\u001b[0m: \u001b[1;32mSuccess\u001b[0m (4 request(s) in 431 ms)\r\n"] +[68.196455, "o", "\u001b[1mhealth.hurl\u001b[0m: \u001b[1;36mRunning\u001b[0m [2/8]\r\n"] +[68.458322, "o", "\u001b[1mhealth.hurl\u001b[0m: \u001b[1;32mSuccess\u001b[0m (6 request(s) in 261 ms)\r\n"] +[68.462394, "o", "\u001b[1mlogin.hurl\u001b[0m: \u001b[1;36mRunning\u001b[0m [3/8]\r\n"] +[68.724943, "o", "\u001b[1mlogin.hurl\u001b[0m: \u001b[1;32mSuccess\u001b[0m (6 request(s) in 261 ms)\r\n"] +[68.728932, "o", "\u001b[1mlogout.hurl\u001b[0m: \u001b[1;36mRunning\u001b[0m [4/8]\r\n"] +[68.995074, "o", "\u001b[1mlogout.hurl\u001b[0m: \u001b[1;32mSuccess\u001b[0m (6 request(s) in 265 ms)\r\n"] +[69.001866, "o", "\u001b[1mnew-user.hurl\u001b[0m: \u001b[1;36mRunning\u001b[0m [5/8]\r\n"] +[69.202078, "o", "\u001b[1mnew-user.hurl\u001b[0m: \u001b[1;32mSuccess\u001b[0m (4 request(s) in 200 ms)\r\n"] +[69.206269, "o", "\u001b[1msecurity.hurl\u001b[0m: \u001b[1;36mRunning\u001b[0m [6/8]\r\n"] +[69.410651, "o", "\u001b[1msecurity.hurl\u001b[0m: \u001b[1;32mSuccess\u001b[0m (4 request(s) in 203 ms)\r\n"] +[69.414707, "o", "\u001b[1mstarwars.hurl\u001b[0m: \u001b[1;36mRunning\u001b[0m [7/8]\r\n"] +[69.744533, "o", "\u001b[1;31merror\u001b[0m: \u001b[1mAssert failure\u001b[0m\r\n \u001b[1;34m-->\u001b[0m starwars.hurl:12:0\r\n \u001b[1;34m|\u001b[0m\r\n\u001b[1;34m12\u001b[0m \u001b[1;34m|\u001b[0m jsonpath \"$.name\" == \"Darth Vader\"\r\n \u001b[1;34m|\u001b[0m \u001b[1;31mactual: string \u001b[0m\r\n \u001b[1;34m|\u001b[0m \u001b[1;31mexpected: string \u001b[0m\r\n \u001b[1;34m|\u001b[0m\r\n\r\n\u001b[1mstarwars.hurl\u001b[0m: \u001b[1;31mFailure\u001b[0m (2 request(s) in 329 ms)\r\n"] +[69.74857, "o", "\u001b[1mstress.hurl\u001b[0m: \u001b[1;36mRunning"] +[69.748646, "o", "\u001b[0m [8/8]\r\n"] +[69.967151, "o", "\u001b[1mstress.hurl\u001b[0m: \u001b[1;32mSuccess\u001b[0m (4 request(s) in 218 ms)\r\n"] +[69.971905, "o", "--------------------------------------------------------------------------------\r\nExecuted files: 8\r\nSucceeded files: 7 (87.5%)\r\nFailed files: 1 (12.5%)\r\nDuration: 2211 ms\r\n\r\n"] +[69.97336, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] +[69.991528, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[36m$\u001b[39m \u001b[K\u001b[?2004h"] +[90.954253, "o", "\u001b[?2004l\r\r\n"] diff --git a/docs/assets/img/hurl-html-report.png b/docs/assets/img/hurl-html-report.png index 37998e123a4d3c4a87a67708a6e8c86d8a8245e8..4389a444289504a34fcd07635ef5149338e8ce40 100644 GIT binary patch literal 164674 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ⅆD-4N$)N3i@N9ZFUBoaicI#ho160>9)My->p#y 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 Mo!SY=@1~c$C~&3{^#!j*`6>mlGE_riKb#4 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 d|9@-lz=)3w( zp)wMp>K+isv#<~#GSG)#H!MPG_c>4p&Y({SAUHe_6w?3e9unsL=>Nw(#E19q|IdAA z-~aRM|MQIh`!!%N1aLhV3@hLcnp`1(aeU77mQ;z$&94YAri{;BP_Oo*{0x}@RS#0t zp^Yduimxy2w;_{PQ&m9hEB{$bKci_~SlYm6{o{1=vGPi1+`hGSUZ_2bbYdiR&GNY^ z(`Bu%Pg2I85eE^(ON1ih|M>X$$*g~1fC{ce{kyk!=5x*#kq85W9CNakh6Y{Y->j^x zhlhvh>1iuYgg`VgpC^!B#oWq@{w!BetgNhsr6phV2eCnimAhC92`hF%Cy45!k<>`xCse1dL{EF zA0NL5SL;@go!{OD3-NJq#Gi5gq;z$6-_D~9M4N>2u(OLK&rqb<5F|krw`$Nu6G|RV z^a2M-NlW8zU0k61V8cPtGcYV#US3^2h<$jFmZ!!PmKB3TR|6*}C*ybTUqM7~^9HA6 zWI#;{@bf>qe`u?(??q!_VL>zf_AQb8`n%B2-j-GS%~W&*R&t3M2=4SzB&Q!g5S#Dr z+=Eln(jJ2$3=9pGXgkNp#}{_(kdcu;VO(EdtLy59N5-Lv(RN}PL8Qv}3&+RDf1pGs z8nEU}V~P4-2ZF@9&^8_MSSj}^7N(~BWB&X4EhIfXJs=>UwN(Hern$0``N5$x_Vdp1 z@yM<-G$h1lT~<6nVd1s4HJozoZV~A0jErO8b8?cIogE^U^X8gBG|EA~yrkouaM{la;Z zRvTyMle0Dr^ojHzKZpRDk$f`S6l-6WwtzffO>HK^WK+8oA#S<4Wmexz4nl)7v>X zMqhM)+&TGZ3^lo*o$@rDiR@=^?32bTVN@_f^0=I?v}~!As1J_D@lywpk=V|aJBd8p zo)GeF8s%VJn=vE%S=g!W`F()x{V*XZJT(wQ%44@cMq)?MEQdl+pCHj62U}N@VT{+G zt@EMXXwkVE>q*QogsT-P@<}%6Vxy*r__n`Ev)jzjUXcCseYiCL zkR0bQdKZUAxz>WPfz-qLDh=7@`}W$gMI`jSUL5lIbhTAJl~mBfF&gwiQZ}qpWywhK z$9lVWCUa+%VTVDrkzb&dt*wg_iJ%ABh98MQ4A7cz*j;08&asc&kn!vlB0jb^hqJl= z);oNSS$Q1{&U61w6%3bYRb@z5Xkwll$-0;(W281wGxo6hFhGov8-i;dhOvyY8dD(! zz3v_1YfSnO{7GsXK1xT=oK1T{ShR6yIgyyPaTh4Vi+)e4`DG|A z`X`6c_e(UO-RnUWPNwzS5p}qD2nru+BO)Y8dFJUG2DDlaL2UvPWoNK49(8A+_di&z z&FLZ~Od7?6?BkV|x`!_l1QovN++QEhHv{CHPgnR<91R9NH*o1TL+&9! zda|U`$x;IhV*z}%G2UF@EI(uqlL6l3ky1&s>=#tfPx;;@x#2hbmym`mO#+7 zGZnd&=05#M3Y+++8xeuNouT+?i{#zpDX0b3$hj^kJY=gbm4pPpfQr6{>=wfgA5{cl zZFq=6`E>3QN|&sIZBCaxc@;*3w&oqxG|;{&UNC$$JS)qu2?q3P$?umtGT+2&>VEbL8|TU$#zDOo;3BVw zT3S5UJ{p-6d{SXA-m7H$#oE4i!|fSE+Cd_vJX2y!0`9V3{84gKIjd{OH1^V@P%f>6wKT(KGD*UL0MZwRi2X zgN78qluxz!0)eU4i8={XwiWB79XSUZ}Nzf>*^s- z3|f^V`hPJX%lBQ`$K%jfzGoZbNm-gemUBdX-w{I#l*J133{)=mwh@5HdRlIBNJhhD zF>nnB!c^fdWf$P)lu$4Il~@DO#PM)S*}@7<__mH0c}s_agK{oznqo$2!!2ZQiN|Gl z`6EpgP!HPnNK^$(|D& zDS@cw`sBNHQf1po;1hVe=k`W126v!B-n9byx?sI*)ZPjnxY!;b=Cr5t6KOG`@Y|%3 z&wWL2uiJI50KW$e-iZUp=@84UAVl2Ip6l()zljX5bXcQtRC1xtm+|#{*C)&FYi*u8 zguYOo$EcK0@Z)mH%mqRVsRyLTNd6^iMY*3UKN^K~m=2(XP3K9YnjIX?SD^?xLQ#k% z!g-++-yQw6-5LO5eYREiR3q{+xd+7CU==3^K^i*67MoEg*v&?nEneY3$msDzKPC#SB%K;ZeIUr{xcHb}bXyU@N(JFcMvU-q~s^&Ce0Z?O?rs zw^Owhb${C!>k!lMVg&`L`E~!j&6x=yLO#7KdYAdLv}D2A5;}Z z;s;N{r+_fEWME5XZJx=ZA*Vze?N<*4KYxsm-+^F4=w>0w^TFlx{$$2`cf8o+MaAB4 zre<9*_VyfT!VDD*kvoJ(t8!W~mH2ISt=y&K8tq`L5OAtG6}Z2Gb;7Y=|qYMJgYOM!pYr|HzSsY%(<0T+cXRwQwKTk&C~2Hie8 z`_1kkN>pn@8zvWlcGZazmuv`#Qx;%GR{X+bgE)>jTvcb9(Mt|MoX;C}P^d$k^ zUL(|7S_&$EJzqI(?jz*YOZqYEHs zUbJgmw5t`j@B09ScL{qx3WCCeAc>Ny@c=RLOZAzPg*8gl(?<7>5tiEf5GA= zoE_3*3>azFCQ2%A`NY0y`M#vjgl+78s1h4Ibp^F44h~eNgn*`%&BdTY$3~!_P^T>^ zm6iQPh9L9P|FTF`U9y-$CNV)dmW)<4A3^o4s<>gOxwX(i`MnXbDMuxt!GOLi#%gqf{m0<)xY31eR+uNo> z-ErT2e0=)*`_ae&nov|!TwwCw+1u;qj{wMMX~X*K*Qn^|eo_fsbVq<17(5nwdwT)0 z0WPSkCu`#v`|G7?&*|K*Dl2CG$_4}d4G zPEIPEv`kFUAK6-V9v=yGwAq3V4{hRZ09LK9=WN6&;NjwGC@n>pjW_~8sspe9<~Z3l zB_$;-0TdKec~zC|u7iVvsi`SB8XjKgS=j06X>~R0bA+h;(9!A_)_BJ-Mppekr?QMCro|aZoihn@B2OEwqNv!L;I{@=cnA)#`LqZrB7*hNE{2)9% zJtr!rm1>BAhne&TjBD64V&amIp;i>oh!6fYRCH^r}qM_77~(^=K)iR+>R_S6Nd6GgJ_|flPN$Fqz$48uxF_7 z@LgDxK+isqF%0G80KA)*ZS3yO1CVV*EF$X{)F~c3RH#nTfq?y+Wi0u+( zuNV{(988&w`wn_jbVw8^d5epS0OMywg-Ig*QD!QehJn|nCakKeN}faojBIXZ_6q^< z9$74-G!p%Gvd@}YT76xBZqa_eu>m&wQ&E9jHX)@6jcNi?Pd}z0?xfd@-`d(j+uXu> z?zH98F@U^mEyyx?x(bHK1MTna(L*|xS?Z9ysA@nonxj%+=ZgEdy5?enfhW%2zWms66x}gJ9!_ zGkR;j*cI~R{&#d#Cae0%!-IGEt*7V1mk#S+uyV|uu0r>s0omE4a6jD;`eK+eva{zM zPPeyv1_of;bgtu`8LA_JaY!ArR$_yYZmHHhNjWU{$){;X&8}$eKKoA{IBvUn>6V%e z5HL8r8b{tgNa5s-Wn>q-Gf(qq`6rVmHR5KM*ij&vThbLLGe z&ch}GYR3mf*;)8^t!M3e4=$e8wSUVl;1A)~?Zm5n`tdD^z8QF3^!dI%?Av4)_l;3Q zr|=-+QlClMNDcIO?JSf+)eq(ZwquO{$aN0?j+)r#X?gwcH)<(Dv*G0m{1+7&6nue}kqWx1g@L;?R+V=eDi-D6%qz@i+N6DG3(jB0OP-<$6@ zh(7k!01O;6)UUE`HQ+y3_FXhj)^9P<&m zz=BDibRa)m22Tw$1NMegbT5z8>%0pN- zNfnmtfv*?a6k+B2QAJyaM`HYvhX)Z&mNUp2o++G8dZNB(vQtwPxK1K|ZXaY1leY=y|DKyX{;I;itOXv-YQG zUkd|q0A-_4483nOlKan6A?1(xBcfT&27g}D+9D89oh^h(dn-L0_IdvEt@1PdD>F4R zGUn%K-mOq-Sj#5>7Q>_myR>FL)7Vq&f(X}A|O!ow(_!c#_Ecbe4Z3DVXkt!l%BosCv^DvnSiu(McSgaCj_ zR+j>=ba#Y%*)IHtJV#YEBRn<54u)P^0^MVkH#$v2Zh2dnV3iTR<`V=6^x~{p#LI- zByw-JFlG#j+1!mT`B3(u9?l$81o3Bb^KzKQ!RMKTs?)>1n+mg=~c?&5!~2lK;BqZTiZ$@1%pUkO0T1d<|}(kF}4Q zS&}f0G9K4x@7|_&M*)|8$VeuW@4lW8hQau%paJnPZ$6i(@xDJ@aCgBprofj@i@eTj zVIn(&Mn3}l@@1ro>hAYUDi6wTd}vd*2?IPUN$BGq%V~(orc?$5XL!9tu3fvlP{YW* zkSv(g`&y;FBpf|>U;Jt;&AO^?gk7$DBBXGxLsD#3Wux;0s@;NLuTx$VQ52Q4&2zf8B{SS2JS?5Pd+Kh&Wq%PQou>Uw z9=MDW4?dsV05;SIW9NbKb)9dtf@cFMBY&MTVNfFO6a}Lvi57YUy?UB9$qAl!ez*}4 zdSS4CTV=he0TngWd`2+Iiue_W6f#c3(wS2=vQ8Mx9M2ou|JSVugn85}hT>G(rpGX^ zK2>Xfb<+)3GWtznt5kbU&D1Wj3&HjZQhr6b-EwYpZ2^6NTjznyk{Zo3NO9oo0TO9u zI+TCSrUZ#gnhR@|jX}^KNjs^gHXapQ%9Q@vA(F`S3si^Li;~j+j2dsoPU}GiKNTpw z{scjm&Ojk)(;jwJE6=oy>93F@?v%Q5*CtfTnx7a}o<+IoEDHLnk;)m0m{&sUyBj9j zKxzxM-CB9ip$2T370O$3^YsW3XWwI<*^(c$ON5Yok zON~P`G<772??Vw@IG!2E*}Gf59ZWuEXT4%KUD(%?m_oqRI#?sY4R)Jmpl`U6|D0E# z<_~LDZg5QpnZ{!3i2sVebSuq~?D8_+Uua~RD$_P2IMHL2@F&YmNkeiC5J04Bkakp3Q3mAd&U%0W^zLSTbZdKnetu`UP2A^AR%anRXOp&n! zO>8GBC`peEnMJ5ZU_Z{Ic9;4zJOCcG7WIgSSiR@IPvpiumjKs5o3(|@ua%ivNP<~l1MG-?&z&9`53#oyhZcoZiaMPP)uNWG< z7Q873j8d{gxp(_mc&!*1~&L3P>2Y);Wk|o}O4Po3B-G0DHh_$iu-uhBxl{}|| zpW3?~d?t#p>&PZe;%RoprZCLX(bf(rVpPF>ETtJ^|1C|q>xfLuQs;smLB#KidU-E; zQL37HcJz=!yyJ%<*&yizi=HzKF%73@s8Vfpv@wM3 z^JV5T&W0wq!fo{Y<@oAuF*gLh_6zMiM+AlhWXS|4M~CyoG9mwG>5$`Ct6xdiN*I#m zD;-pj`kT{bFW60Q_IQYn@rx`_i={|r1RQa6r=)r>pVU2)4trlI+p2b_!X7XGez3@0 zV&!)|`*X+Kxb8g6WV64Ub^2#oek$UZPyTo2*v?YavtBs;E#%@fcsN2Clz+0;mWGNd zrdP)Gv3oJR1y^{GX<{UBl@{b=buu5ac(%4vAkJ?R+XgQ+euKvQwn5VBDW}y=Vr$<@ zAU8%pvhKmZoAIKpV4URwUD}GSm;L{g;rOZPc0Zr@plXqdklUEBVynqJ{OjhYwW&H=)d?wsM{|l)7I#m(fsxu z>J;A|-;KcVjC~i{8atp3X1gp-8t9jfb&`mEK?5!NYk#pGfphU{%*YcW+roV_TR3#5HokBwmD zHt|Gr^D`g9opBFia3GP_xP&tw%so|~HAWaG<-3BRuyYbT9M2+Ko;jYY{mqRpZ@jQ2 z=cjMn4_{)jiEzYJXA|_9L5m(W&JdwdY$K7A&NgOitvK1@!_5Hdbltr`|M!sc9>LlE zoKx$X6`pAYde545TxMy5_HvZ`G0QFTdYfV`mwJwXe5z-u6gBtNZ@58Po~QB@Vd2GB zaF?V^B2Xl{d?O{({!D{jp&~p~)uq2IZeAOpo4bp&o*3-+S6Oj35L%((@Yy6ga3r1N zN*vl0W;o1Sc9R&|?`bKz1ZZWOWh@kVHv>&J&HJ>HH$Kuf()7`HW9ZhXDg8yhzsjc z$xx~s6t~eylj~Q!VQ0weW$QOD>)+?8yN0_S4k-JCNaaZ%*<)~|0#ZZ`8lq4uD27TF zD^FFeUnI=?cOJ^bCN}xN8@x4Mx(6hyuFs{)hwK^5hruU!hWX#$3d2??-S{HLAVBZTsAFwBrScUoqtL9T9JNfc7Y?k z0Qg}ao-;ANG8(I;AHf};SLuf8;wGL(#SMXdb;+vIe0-blx)aaA?hUBmPB%0((xCcs zZ^_@+1MRb45+-HpeMy?xy%IqMpNl_*9e?;zHod3h@B&!csOONFI$EjWz7R@(eGbWt6U>!AgYt};+aO)fZSnwYgPBU!yx+cOc^_YT_p4Zume(4VAl_6 z_uoCLf$K~mxc~Rj8W7?CK1CZG_1|6JPx=4i2LE%)|BpBLpWpbO7BF_2B3AvmT@pBJ z>d8YIlRgFxKZvgRJe>ejmTSYTrk?Ahq?WdE(97*| zjI}i4Q$)w>O;rF4^5J~dx(rR`H4sXQh+nUZL@JurzOS4E2rMA*d#C8tUwXcqC?)v@hR|*zj!SE88)$)VCi?B#k26j9 zb47uZUS8YsntlL@abYe>%PM8_I*C^cAjU=Byv7b^%jVyEWGZLv&yTCVi!F8^18_?) zJaq~f1(B&<**YUp%Ye@U2K%uH6S~vzOa07#ru!Pu=Ka^FGoZZp#xX7!;4y8v`fZ;0 z!~rgeM~LP3zg(;G|4b7j^6Ifxq5YX_-~s5-qEril@&f(|rd$@yRckN}Fs%g;1VQRR7+ z&6frMWhAN08Xm{c>%wJ>Pg>*+_>pNP5uvOTEdx(UCVXLFo&rc0SLF65x%iAK;=7-t z67l|QvhjwH8q(BvlI%Yqhm7RiM5FF5&Pg4+&&5CSBlUe&u`LK8cGGUBfiT2}*ki7l zsX!?i_A8sMOR*^}(e|pCFtqz~GskcKbkf9f`vxc~G+7>7fOUDw-5xibtuB)=G^y{n z{Jz+fguXjS7{6w(G6y74q1oT{w^#QT+AGL%Rw`k*<+3!;)uFUx+Jnv0Y3tdfG-+m| zT+?s*PMQoy|3{Ix=c{i}_g%20Gb(}An+G+@QSzGqSm4;ywg+QB%B`KDIUnDLQKy9# zRi%_$c)Y#bv6bL&?!+r;%3;5Uoe}@t`|TJ~)n1J4x0mEWzSxaSpT`42U?|ITj0V<7 zQjg>4**O79Nc=LUxAOF?mZ4C8s$K06=NLe>x=7B{LDZ3a!D$Zd50AGe%Ty4;C-u`4 zNQ~9!AEjnE=gfJx)V}sZj}p*R7tX28s_KAS;Q7NDnl}&3@Jl{0{KbA8)+$fp+s~+* zNfj29781xp@op}7UJ>j?aKu4G_66i4`Ze$O4j~2LQDQyNv9k6r{WIq4d5B1H4ew6~lXQdejYreDby^pT)t@o+7tb?)@7ouHkNXPs!uA1G3M|V z4SNQPzKtuGrQ;dn;uUZe_Vs905&|OWP~Ah5_jyM1UUi+?soVIV|0(m%qgaf-6A)tL zI1%hjhza;zttMYJw}C;sn2(rtzZ}KA^lu{o^*yj0V)g5qgi+!7rkW>NJM(!0Qe(cz z&n7iB@DSwGWWA#1K_gnWeojZ{n-U^lJ3!X48B^ux=f8HB$zWyXL<|i%2)zi);U!w;5QFq0tZu(Q-9=+&Q< zhe>zavT!5#I_`|2Wwy3^qbuNnMk%n@{HAxJ<7Q4zX5}x|0>xa~n13R)ZX{b_qBb~2 z@bWX)Y5UVD@|Cv+4tnM9!_qcT$S#(#0F)RIIQn{3OGKch3BbYiG;3ZsGfqO{^Y*=ih!HT_wPHr1&9c< z@8)Ga3My%jds{kZq_F#V&keZKRJw#&jbEe5` zT_I?oDdH&!raWj1&_3jcI94IVy0Al007ZqF;kK@zCZUT3LPu?Vv{`U8kAL0WD$; zvJwqGqt_Gmqool_AiB~wR_9t%a>LDO>q>P38C(OX*)1?Ixko1be$SLrTz|QmI{~t| ztw&Ph00dSpWv7)(iQ6oZ%Sa9@siwd6fe(Za;08aD%iY9&(jTj%Cs9b|*&whs6gQ)m zLc|#$#eaZeM^MuIC$dyQH?cZ}Ny*X7xk)B=63$RLs3iSwo7T!y{>X_S?pV^VihW5g zjQP`IxfcOO>s(o;+RW4_r2HwGjp&|j&z1s~EoB{_h?v(RpxZVUf<7FySZliO7=&o( z=J>+2Q!~3-i1EICoT6u{q~qbjSI7)X|8u_;!Ed`6gsUkh`EE9OzWlg^(t8S)Bh?fQ zFga}=n$kB;1D8>*`eH}v8kY{A7ZX%nqLhN%;L_lQd{74v_a$yIL^EBWX^ahz4JCe} zC(=&kq*tC9rN!foqsv1XRl`Go(qjWbO6HW@)m2AFP-6Js4CX+Cc$F;Q> zW%RZukEypSyj_?6zjz?Q8L0V^`Wrv^@O<1fah=)@+7Gu{{dwK?wy0jRv3*{ zchJO8f$q}nluzE+!rsCW*2FyhD(h$Rfm+K}Y zlkWj7 zFu-4R^*Q>Lw_QGdm5O>u`8fM)P`q2?Y8nd?Y&zc&{Bx}*3#Uew-)^CL?5~dU-&o<^ zK(*xXV=_iLVX=d@nZK25B7V~Sy;R7$)P#C!4}N;ER5mL zTHOWu9;0lGmbYG0X8_*9IT<8&Ux}4M5M2Q#gGsoD=M2FG-_f&vRF4!wx6amKZsmjf z5t`~J!hW}!C4xlin?KdZlakSMXQUf7F+vp61RvAwf72z8j)Ym+lkHLzt9bx_bd*v3cP=M-G(_TEnmuCUrC2=YBI zPl(Tt@{{Kp8=XcdGZmx&>j3EF17r48MM1ZK$d?Z-Vc?J@%SNB<>%GUj$q3!9P02IP z3qnDpN8~GM@>Y;XaJ{z6lKg<0A$|?ZkKdjo|rmcCWDG2)jnE&~r(fWS~%)aA) zeUW6#+KN#_#o8BBnyEPXwqQ>l#00hQtNK-vfSdXepoFFNah`YhJL2@1_$4aG)S!Os z#xpK>mEruC?hAo2kZ|qyS{J5L%Su?Y=-pmfZVSTf(3(aoa1q4t?cv?RmGYr1A7nfA zBdu)^R z{dh(Gl1(3M{d1t^G{1=R^QgQIr9(u>SJN0UW0Q6Ospn4YJFnyhC<#C80J#w%`^cEP zLUbq2w*3}$ zZnYGR9eP#wfm}ZRB%ZH+(IWi<%6-8Y)@N_5E{sz8YKC;bc9?nlE+k98nuOg8+t5?|d4o>@Nw#)|60N9o3qVR5jUg1@P zsC59can;28M3A9%=#R+E>juY~j&X@i4OAUbRFuGr`krHa`)1Mpa(qJH&%0pVT_Jyn zVg1N@$D|WUtp6~{tTJbh_x}W?F>dVRtEwcx4nGq<~X zo>>Wg@V~Qr@v+z3aO~{5@@QFA`(w1gX{W%_Gw*xx1W4<844@Bk{@ktoI7Tyy{2^Gt ztD^Pg+iV)-^KP=?dmvnhKo!0>5)Wa*A;-*H#uV%6Hf3Dz5kq9UuJV0}NCGXVxsBL9 znpG7%0xKA=H_qUrg(1f;zi0zV{u{N1 z!7MF17=OfpaQUU7o=B5;|Uf^IHbaqK|`fTJ6cWk<%rC^p%oCJA&ZCZw!hNH4a^d zS~UeO>`6x^QcIvNI!D(Vlvs$Ha#r(0#QwwMukwd842E?tr$@tYvl=!Bo9}AIthq-N z*PN9UI84yQ6V=wD{=@5ugD>GUHNE zp2_cn!ey(xsA^F{1DaFYZ>F8W;-i9BBZp|ta1{h03bC`i&O3u~JOY6k-%j5-2+Y-I z#?_Pc<8?EG<(9W0El}mk8&Z`ycckSPzTkrQN2f!m&pyFXY5@s!?s4p_V65FZu3TP|Zha-8D zD*ElnA`x~J-;54^FBtd|i51L<5$UA;lwwRISpl$1mel^+)m=zcNvw>GDnQWJoDh}F z{c*oDU*+;qV+%`wW-LOp6vvsFJzgKq9s%S@%4LIPoBcP6yn!c}qSpdQ-wD^Y;O!17F&NYK-%%qZ!yOH#}Ir5TcM1$Dy+Sn zbM+kWi0(}7W-uYn4*)QW^#2JbP@l>qSVQ~=dn z*Y9+~_@5WP@{R!vP=>OSdTo{IlyX!Y6lvT*yNjC*g$XCYsmar-KmD$f210PJt+AhkF#8lY)Q3Rz<0^k&+YbQlN> ze6`*)+Vq2o!i>4U3EYY~P|C2`cj-jwi#U0*XAuhM;sbgosgm_oH5rw{tr+K6tkj24 zx@)f;)jk`mHbpT1{>;>m$H9%r+P)r_{s<^2eNzR$%~W!=t2BI9CT+rQ*_b+k9AE3B zUoE*9x?&KwW9Y9_+#Ile`=^$HMrl#Gq1-f$t8+%)vIII#V3sKja#%fQ3^xz9vxKSQ zM&aOomHFsnv1;a{q0RVnrSuUY3;uQJEQY=4pasy#R4#*5by6Yq21tFq_$}G{Q)&#s zIn9*#Dx-mC@9Qfhm`Z#pze_a^rQjGhy$GYxx@ezarl#st>2ld#e>RsqR<8#tIv?7aFBjvkUn!*i z`2drDfKdTAoFj(7s47t-oQj-T9~!|lGerN6EOc{z=)H&GKPa!3ueci(jZ3mL7>KJo zbO+A?_l^x{DM^N{8ffg*oay*2r@S&k7z>`s4~l4FrX!)Jgi;AF*tzGT?_{ih#qS`h+gm9f*z%;azJ6w3kC@4_s)&Z4aE zr6?D-XG4(X3WR>YP7$(O7fd3Yn4OD#G4k>!wH?1M_$F#-Zdw&qtJ@AtMj|W0v+dJg z_R%{8DiyUT@$L|!T(+*iM62ccB(e3^8-gY8;8+`O_EStzpvP#pN@x&SYbI21bL(m& z02E#5^!u>P(76JU`PoD%Xk0@Q%Wj~UuWwpKoxn-Sni*3p1uI3~YL&M$FQ4$Yo^uNW z2QL|81eK=`#N{*=-(eJ6VG$gwYXB(TJm0NWp*ew#zBB*BES6D{hxPbQW%WGfH=H3Y z`zlafa;%~m;v>+@fG}H$biCyjn7>)rvgD79k@gwVewPD#V7#TO8y8jx79}4{t7Z9tpdso zd)cA&gqr}m@=P6!Yv8eIg+x1t_pNHHkN9aVep-GvD)b+WjUi^2oW46&vwarOl=d{x zw${YjjlR6)ZV5cj^tYs6@*0P&?*U9L{&#&M3zvXg2&;=VqqnX2|fn zB>*xCDT0rNS=}mtGR{nLVhgVUsHH9-+yf~6k$2SQJ{Li?Ga{t)M(gMbeNK+#(H@_V>N$7FDT11j#CTc+4G6SU4-iC5O zPXEIJNN!em>}+#OWZuk~6Y*s`Q01N4Fay{M_YoX<0}{%`|EkqOb6Mt;^bJ z^zcn^F`$Dj2Ar#ivS!K3lgVnONxeBckeN0mF#_y^9cadVd&oY{ptP9pfAQKY*1F=S zBuo<+qOTR4eK;GtUpY_PhD)M3*W2J4vSXPXQGPaHlZ=qv2BMJMbvEzGT74z0i52G8CK(17gPuB+<1z zeq~ixun}$J(+kzQA3!@{DODujo!*IS*=*szsu?6>c^3e2@`O;$U)k-D--~AuICJk+ zwL)ab|M`FEV`n$P3I?FPq@Y|%bP>E4+v-KZL0rwABS7_GP)hY?;9V|roKILFSP?gp zTLmgoC%|(S^P!~U)$QCn`No6w^mk$fm?U%f+Mi&=+hp3Xx zw2W>EE0w)UFL{p%y@66kCLr)02bE{$$W_B*5E?Q!E|?sUyAixYN;Z(iGz!T9kgTm8 z@Pij<1n<+m8@REg3L>4T?&%VcbF$}T)=XoB_$6woIF|H}hYb9H%F(ae{-R4PJ;u5N z_P6|4@dw0W5fta)IVIN*+%S6`MH$Yrjrx)6KLNh6PyXVT^QZ0)9JuIZm1QQ(}0BGyYN`z6iWPSPNIVUB6^_c7L^$PCuZ2R8_R;d7W4URxgB`q*N1cMYK z{79?yG$D@q=Y0|77$1%IyOBqr&!5@=N}WWexlQr@33M>4da|*tqh6}pk~Kg}>70Wa zPe2VRU)mRl=yZiCkatz}d_909-N{Qpf5NyZjwteUT*t;X22>gI>VS)iOaxvnlYVSx zzdYXLjRVU9d&WJ1`jL3X!u>)B5#afAJSG6j9zB7Ig*>%m zQODcslg&`wyulB)y%m@7lZvM(wpGeb6M3t1EnpESz?{+W$kg`#LP&kA_LiqoaoMu* zn7H06ukFAZ#z~lK4E_Y>Dwwvdmg-a74NOH|(S2c{Y=q2%ktF!xX#q1T^3^zpo5<#U zHLVgSi_rI*S*;_hL0~BYk^Y6v3P4w~FFLbHKSMki>{{_BtlPPY(3C5H)b{`e0FRy$ zn7rt=Zn(fnJ&a^Jzru3fb^wftzIflv;@-cZnFrXaq?O)+lkG}dKciG>ZP}j7*zCOA zt#=qFFp~52Hn8uR#VbfDjr=lC(g}tZgOO2lLgD}SYd1;H9;jmW8R?oQYE%M?FMFxY#a9klRFHez6An8s*FXA z<{p$a6NZ+*gD14~j?LNHA8RDu3!ri=wg8tb1V9rYq=-(b&SHjn1LBBWSPo^JvlS3m zPS-m`e)}(#aLCa0Wl4n-5o3z!|^?tk`=mAnzGG%L}s+Gq;_K`Ph?Ce4E{-NjfjYfZasrlf9(}{7U_wWLKtUS}hV<%1mmYK#Ul5C9)0@Sw<7y{~ z{jKU`_s>eA+8R9o7FBZ_F#RY6#Vx0gb3+^8pXho&c4DRb4g%SA#2(wt6E{aSqz%^jp^CBQ#l$p` z)lC;BYa!$dFf(tk<#)jq85rM#bbJu|%=@l`-Uil)t@JM%R6wZzs3Eav(ct_}$)Pa* zVIUw#ki(080tbHft0WW6o=Ai`Pd(fJq1`CtvX{ZP_tN2e3_T`rmgQ|RPE>dM{r0N- zX; z-!$H=&ktuA1`r`5O|on=>$HnP;CORPg?sa zR?8rEry%f4i&!U?8S!S8M?Hb|WkS+g4$V{wqY+W-mf z7MuxgK|>%oNpN=vHn;>2u7kU~-_Gy9d-lb>dv@#1oa*WB^6ILm>ia2NFW~#-1*SZc z|8A&&A@V1EPpiW%A=!l_cA6lnfN|O4?do@5t(N-Nk=J zonb8h64=Xcr0ycLp>L@@Q=BC|BOAAXOGGTm9cEdvBA1L0jbwgbU8R{h-^73hxUxQ} zK&|IXbR_l%T;$!TO@FB9p(1i{U}s1!`S|=8iFjTfJ29pgwiCV&|j(30h007sNxri{ES?=pxb@Y zq!JDe$k|-Jybq_P7LIV&y^AF_;E-EsakUvZ>~yoZmWwQu-fJHxl6Gk$f4ebMIRB|? z6%Uig;`ph1TK!E6n zWo{ARedqPm$xBs=lgk4G7U1)@Pq10KG~+fnAB9swrivzh`E!->Qz~^~&6~cKl%`_w z1aY;^+mjO2chN6!JbHi{L5qNz;QF7gMe=xegUv*~ulNhE;{99>7_{`y=uj1BKB4|r<^ z9q*(0tn)_<*1tOSNuqB|>=n&q=VgalpS9K$=~4&@CrgeC{1|a%~Yj>R2=Bl z1k>JBLlIM6RvlcY>vdD4J^z^qfk(d658}}j<+>Q79dZ@t-`D3mf6ul?L`~y!5-M<& z)L(@}>VAcNJ9N-=v2yjn<5-r7&RkSaCeQyKh&XKcUHj|k%hwnWl8 z(Ija%eDB$IV{3iLQODu0gS^G-cE3y(J`Ap!j3&b2*7iW!y{ueP*7 z!-x5`1E;hSUkfg^$z98vo!3H-_``U~`R(<0lo>6UXndf6b3`^y?wA*yF)P}p!R*Q# z|H(O^e>&mfyanaz{w_~j?HZI~UuU2j{H|o*Td%3;=iQk=ss~6+N`H;xGr8=a_MHOZ zlR@PP`VTF6Min80;XB#*qK(i{CjJ@qlj6Py}@Jr@g}T>hYm&FAMFB zKuDRyu7{~R3`X)Up4Q&s#bM9WOcP4DZXGXdZA;ramy3}?SsEfEt&A^?55auP$cc;} zPW$W`;pcG0XY$>ziTj`F$xOT^(9$y6*~qvezx=*rPL(R@b2k0 zB4sZvFP92ltBgX!bjtfbjGswRY3;aqyScqzB6yCp57xbZ9L{d9BOMEPf}tV7hmg`< z%yiI;x!|AyQgK_HN5U}&UL>U5gM%UeAYf(p0u2QTQsEWUDTe(>_<{@&nd3aSvxdaH z4FVy7MLq>}n#c)&|J{;-)+7M7MMA<{d)i(?c(&*Y#iDo%L|G@0wndK&+V$hg`P?n^FyIH*$5+9_$l2jxGAZ-Ym z7c)>SH9&;V3vn|3FUk;FcsrT_R>ch;FA#_vEnI3wCXEtcxga4;bar-{Yi}D^0q=oX z!(4@DX3hUgWfc-u+J9GpY+I3vln35dL4^Rc*YDW{rKF_9#haR&_q{TG{gAN{>MkxW z{DOi>{U2T+WMCV$A|fKX+S+-(mAa}o{tvg4v$I~lzV|!g;^K*I8p{X!zyd8|q`Ic& z*JFNVr3PvB%8Ka*2NxFrD*G#KisI|-{XDiei6>r>lA3zpQSY^B5}?lY1F%$}Z{?z* zqIwz{Imkl7!iyNZ6;)ML6&2aC^p2H)D=y}sl629TU0kFhC)WU7TwKiYZIS{ib#Bi) z8wZEYvOpO$-N(_TrLrm#Qc@{jA0HofsJZ!?Kyh*LpCKd^K)VhQxd57)81`wx-p-DO zvc0|iPC-JwuaZ*4ACOR+6CmP#y0M^NZ^DFB@Zud04n||fnIrI)FD~3ae%xq_+6H)5 zBPD>E9UTR`&-d@>X!ci34mc4Jk+PgP{6|sIzzI^CNkd(oP?F$_7r#Cuqv^J)zt`gz z^Zlo;zXBqBd0AFg=8qW$JYHPZ)MOA5huqxK!qpoLZeT^W^IzfS=1%yBklVYyZb&b& z&W3>;tgSWl1O)}rq(avXVIVJ2Kz_|Zpb3kOiCI6$27~G-5D+5~d_-OzbCQ;U!QIK? z!9nSk7e8jcCfgYj){Ru3)c4HH$1pzuL;)w}>UE&vTekOdY>|-(&!m-5Um0Nhf@Bxa zGkt!mB*)5@tH=&e0H4J(5^CH*uTDIVWcSrOQzW-qFC-jm8>x8(ohw1O%SGd$~?c zO#w-1P;pK!KCl1Y^k@yiKyc{LP*bOz&CSi3k?ivz-Ctk#g)?&ix^^J4$71N2H^R@q zJl-aH)~H(Y<^%Pkrn0gnX!6H#Rr*KkrvT*7ZK;h3rIH zi{9&UZbHJm{QZZq>>M1-{5>&;qta+^q{f7l*Kjlh%XeSQ7o-Sv;~{vt_cYi(`q;o;%H4OzMnq=n^W6HQIC zUJhCj82}sL&5mJXYpX&4`+U&YC~6PFNc#3|X<-3^)Yjb0y3AZei2+5M=LgUT*V5=P zJY3wO;$lAxAXT1uMLQQ4lP0o`HUMu>y;{{`bd;7F`(>7N@xUjS&>jF3pbOOj zSO{3ZEz@N>pwB5NGD-(WMv`&NKF93bzBe)9kpVJ6vl9S8d_cYtWge{|(_de@y!3cV zc#ak@dg+EsfcR(@*KnL%{9Ix4YmB6gq9D*}DIxHk9n%jVx>l;$BtBVLu>zz+5ug!D z>-Pwk)z?o4)cgd=6t_jwiV6w6=6RcZV=GdIv2eN~bRLg`)B}pdWdkFCC1e;0#|fyR zpr9{RV;4#Fa(ZHd@g9)#j~ho4W7?j4aM48~!yqLktve0%_V%7Q;QA69Yk&l>3zI$$ z4GjS#I}Ip%rS3EjC#O{f(C=_^a8!@~{{0&{BQcv-N{Yra;@ON%7Pb)zD>3$LPghs) zeUyF&vsVuW77sT!36A=kH{*6lu}w`)Aq+@^)O>}slp$Y^vR+6^a=8F`^84k2u7-vw zYF$lDI6Oa}MKy|jL1_)>Hh$fTN=T@p!Qa2{C@d-YRovA#b9q@eaN~l+%v@7fHz&-) z$|`N0@beBSJ(K$F(f)qP#?LQ6bR4`3)huUfr8YUGl6;A*mkdg&NUwduOk66IX)qol`XxaLxxi~ zCFVvZBO~KQ@h1-tPQo?o$W|~X*8p3@i!#wS#Ie0vdhg!7bE5p!OKgoF&v};&-~axd zoJDNrS=xf(HSmdUn{7gQ!_mfxjaa6qr4Oc63}=TB6HAA%ehrqUFO;TbwP<|>!3P19 zy%c(gbQY91^yXx@vgGf4%hjOIaN`VK&;7KI*p;MDc}rFcphG>FP~HpyR1wPj6|_}) zYwv9UzQxYpd=_L}^6QaCGTtPSf=vmZ%jk8U9J#qFWeK7;=^~ZN5>w{4^T$6oJ8^%8 z1;hCC{Onul*EsRbP0R3)Z`Y8-p56;f3x)kY{*IoOA|hoO1G5jkXdc#2S(oT15X*kA z;AbrIKxoG~N21ZjzNIfdqYBI*wPW4hBEPnqbnu|fX!tfsMwdLsn7#`}E~8kMAUFV+ zPP+_JmI=0vlVVQYvRWH~!sMJdTe}QOi(YO34)7Low5dTw)W%xIvbEg@p!DKK4C=|@ zab0kFMKjm=g@>mHqT{WREW83yAEJutP0Ew?3|R@Ul`icLCg+*MZ?FSKL2vdxv+nLH zY^+e&G<6t8>#vu;T{bYadyFrxTO%T>LBj-2wSQu%#I+;7F+yjz;)%2tSyMK@RIl|g zEO4Tsf&NxQ3N5P20Mh~4&BmYPCq=m9a_g5|AHW)L8&2etV1O}c_i(xqwUUzHY?0oR z0o(AHjB#_ts+F(EyC+!F3jtVv!&|n&nhubDxF*87Z^lKc&%63vVo)dLt4mopa-=JkAPYCT_st1hA>znh}=QDZwu*CFT%aLqrvW1CTW&yf_E7z5xQK z7}zZK;z^w~PzT=Bbu6!FO*12ck^DL*a)mg&{(?Ev_!2^g8q?5aD!mP2ekukoD`QAp`_e~ zaeL(?{*uTJF|--!f2E;VU~IIU8!6k%Jhk@nCZDUrsxwK5Za~mfbiIdj&YNN|r?E)x zpQ46bJX@pu>4hyBiWnM2X^&f&o9o3XAN_+D8KUK%gs(A z1g^a%=89*}eFIMK>|mu@dezYv-FA{Ki31M4x7HTfruY@#2yhpRxpdvRHz-w9SrNBu zfSpFJ*uH`Y9Ln@eyrslrfPW#06Y8jk6oV&&rj`h-53GpU7xiJB$Qe!htb_-lzM|LA;$Xw ztgjoSE-soqt*}Lg@``J!;56PZ)^_TxqI)b0Qr+oA3(GENnrFyb`9y8Y3npwa4NJT^ z#!;JBbuF(I7I2Itg&-+rDXDoH`-^P1SUV|wL%Q|WS06;i)rP{Z%0+8Mzw#7rCUdo3 z98MoLxFAIhHBQaH+5Z^9*TscCwJryLTmU-1G!Lb|)Wfwo(Heu^_+k{nczmDu{9Yaz z{f^4LFDQ3OyjHDcxBOA+hEevY7xgI+3#CUdvaj6EI_u`HCfzj+u3K-C>&|OFL%U!r z%cysaaWs#A$Bs}gU&?eiklp{IvnrA_$1O{?AI3Rbq67)5bYL|&sD}4FZAvtWs;cdN zA6p8hN-XL7+->?JzX(sil&t?5g=OyJ5cZiI^E6Bi5V&DQu?!z z8;S>ca->EdviSShmL{PJdhQfxyjuKz;{2Brwe}7 z42-~hj^#j)^9Sol%jo|h_bQN3XyL#V8JQCfm>K>-_po^X^ZdK|p9gZB0ZiHdPk;RH z&;EbiWpF+#juldQqzB@a)jlG)|TNcG~&Ns6gjlEl&>l@$* z7!A`)v4`!Nd_-JAQq|4C=Gs-P4>q<8&P}H8>$jVHyu9H1?TeqeEZ^!377ot}MzHWW zd`}OR>LDV60`4PUBxUQdxdhAJ#~;&2U)OljE!LFOJkdn5b|@;UJH^A6TYa#0V&(*j z=4xzImt2%oMoePF9S;Y^`O0^Gmn)Cs1f*}p!oTX#eM9KvU|dFxi3VER|9!KYw}3_Z6*c{e`)Dr8Hn%4k zlMY#kx8d>ByMH^OBNdN`I`a7A?w{qJr_kfXZFQ#uuytm7y{O0+f66lkOtF0;-geGr zHM-YuG-kB)`0por>z0Rv6+N(W$+k@uxHMkl8+hbwuLbEd5QkXl{xf#49TbLD-=2V?d6#HH5D}RL?jb-k64`@sTN{*0Ln#`~uGK4*T=$U(e zAy=>@Lw*#8;~)RM&SyEwSl^-{JWiVsRwvB*Wtoc}0V5J1bZl)_8oYkMNTL0EFkN5X z+AzRX*UR)_)56%(`<1cf)<@TOBkHp7S2Bn53kKy5R1L1MEVam|xh%EQ_YNmNKO`4yS_(meoS;%hH7rW>0>z@ZuRr<)mp5-6C_UrY*-Ich+NNM0F zHvlIo-NF4z!IbwG=J;STFOcZukM4mi+_KmHqn0;DgUfkq;NG`EojtD8vbnUwOwpBi45bq>E+^R za)!(cHo4aYKi39g=(AjXW3-GVsysC<5(IaGMEm*J#49=9Xu4h*VPRf2t%En_A+(8qWzU#VIQ#f0gq3tg7_^^Fc z=x^FYQ(+BzQ+0Cs8a-9F<^3XLM<)F~X^HY)=ulYM+&=TGcGrN}&%FEf&cqZ4**fg_ zSx7CAEiGo}ZZQkutHn+yJMvmH0X_k7o0aNt@2CY|XV;V&DbV~=0S-21I*fdyH)+|) zzw>~!J~>@iQ=&u!JV@4N*<5v0{8eYU%Rk6zFq3aJByY7~I@MSPF5elM+3;!A50awt zCfMC#qTeTtMdtqZm(3TND(3@d96}hnPvDp?b~C4b>(KB?QmQ77DaXO<@oE)guVK=i(b}RPLSifDQyr$XS$u;MRErHa6?q)a5!{a&bbe%v{<@gw&P42c6Kae8xOk zrWN(v%I=kP!fQ_ljsHaWYr#{o$Nx2yH1n4n_amM;@@7m>^u1nqHVmU-=ROak5F_>T zq?sue9b%Y6i~|&Ak0Gn+r+guSMcpk$h-`6h*&aYi2zv?+}_N}~!qk1x?T zno8TPVgQ2#u~eZvA-XRQZ<)F{WrA{=6PzaLB{@T_3RXvK2oE15E?pUo{hw=xmyyiX z%u2C6$o?3fVmDx%V;Ufas-azCyKd!R65*+0_W&s)J9_4KcusM`1hxE^ELsfD-VLfL z&h5&kUQCeA_xJKMq(8W*jVYB5c4~zU7ob$i@a5S1B|gyF0+CW};pC~G^bu~0TLj}Q zBjR`UuJ`1fN)%GhrR_Ww5$}=!M?5gaMy#maQrwV5$&+-pP9Po*)0&#f4tJwrl_uTh z8eYmD%Z0k-Y)&j`dv9yXcao5rH#?qN8H5SOy~-E5W634b&d^UfE*fxN-xmFi%-sUt z`~J3uJ$hN{CE3{w3)Jwfa?K;g%;PN|?=>%m=id-D8F*XFqZY(-Z=;mn6y7kE10KvK zs1ZQU`<$yd$7P#*gc6O^;?@|KPQV-IW7#v{$^k_6rhuL?<- zBL~@*#rYo|$Gm zm$ra0+N}6Jw7lYOc}VPdoZ2Ybv+vBsp|1aIZuk_kd~Y*w@ZR+AhT7qvlDU7*Um&z-+!ywzrW5IzSYfmTgnbrVL1h{f!hZXsMQ zxTD{iA_u8Uh>YbK*_ymF|I)19H&dDzSn(wKlvR{{zoISL__TRf^+vv?7))-rZ6B`5LgEJoQxZVFe<~OT zxc{Z^;&+`WD?!bT1_fC#5@>t*oD6gFa{jsS z_jx%$ngx@}MAJP}AD#xY%D}#&=)D`I!snf>4$%Fg984Hn>8ED=_KqTZ4c#;IG~Gub zGs5=l*YUOuJfX~K{ezxSVM-eH)u@d%$9Iq8&GuFWQHB<2!z`c%yaOv<_a7DT*G3vA z&_~P?o4Y=c{fib&gS#|ibUOw59U-qM1EcAeW#J`qkO56_)!JN)FU{zHbon4HL4`K+ zwYD05!0jH!49w!WF}Y;FUcdgxkOfeKTA9RJrmv)T;z7d3XM?Y zzjGa3Rb@AtmChHS9lsd++O%0frSbd8Eb5x@81HAm@wE&EGa0f+1k9RqUl^h9U?xhu z8?@kc-z0eO?IrfDCzAWFOMZyl(fCA5`*_EXkUu#GQn?sY#)ieI`}{aE|{B7)O`5oF+AJ|7s7v{eoiXH@vCgG{8+z z(Q@(bEim3sPyc4b#qeB;_v)yfc(nNN5rSU+vPmB!MZ;Q?Np)qcNkQ0X z^u3s=eQUFxIUM-VYa_Ql>|Tn8P$zh|Pk;LQarT`X*3Z1R8~Z^S+HQoR4y-)&)OzuK z?w?T1FTb4F=5!P?78cRWJ32t@pR5GBE=oS_@fU1PbPd~2*G1qb(|-HXOY=*E>*rnS zVdhm39W>R5HOpE-7AK_0J=cDiwLXNb;i7%DM*B3bI|#(irN^jWh-1(<+sS@_6mmb`rgyF^U|zEiEz()1cJt( zB77Vt<=aCHhX@YHb^x218T9_8{fhnq-rR`>k#93v4@r*6LsD+{kMRy-COj&Bt}n^* zy{&oQW@*nSzm99&GS5k|F+tI|7<4Bkwt`Rx7h$PxWhg)287`C@x71&jwbiut&QVWM zOu==ss=aC|F=EWL%qOypvN*n4#)#5G=lAlZ|Fx*Iz7bOsIw)0C43EB(+vk_juM`ff zYisG4J}R2@_*;Km9!TWK`W>MBF1xcXw7tC5e0WTBWxnG=XYcaG)(mCsC%k3J`}vt= zxw0U7rZ#sh-eq8(MnYBQy7%{s8zNZl@6m9aJ`*^J0uE zr!|TSM^l(|3za_y1rERHr+|sRPXu`-;{TE}d-~;hj;u0myQm4lnk`VHjAl7|vRnx$ zkr$W1mq~kx)(TV|lwhOplqj|-0g(i7t(HVuQ5(}ms^#^(!jC_W)LeG7#YGJ_`ZZx<69TFx7| zNY*6kK>+rZ6!Jyj6oG@eoUdU}c$Hr36L2;LupL4gDfGh89-? z!2Sg!2;`U#*n|M=yKq7RHaq}3Cn!O{SpYD=HXs#05ojrX5)bK%{9xO2>mD;K8YwsNX<3v*M{J&C)%l{A=8aNBBG=b%MI$fY z$%cvu;t5*D++NN{9+GgoJ<=#LPK-$D+%);(qvX<>))V>rHJ4s1i;NXi;{dh*VD>99 zE%ju*wK0o|YIFL5<*L%V)_04_c{Rf0Z(f7FphNn*rnjzJ1D09DVKffY#bFe2I!0R6 zi(E$Rm&-I%Ou6<37k|~?Fyl8J8J|Sm-0b$!RA11Fe%bi5;XWO))N&AtbFevdP-e8T zk!-%+X~R-;TdW;%HY}^=YkZ4B{BT=n;_nP>D*`!2flD?=wg$P6TBiHGW)9{~LT$5P zlg(bbg%wxNw@MQTTO<;uP4IBE&bL=C=NnzoF#iTTnopPREgi^{eq4FwLa|%kc5XK8 zFsr%b-_(5P&}6P~A1-5vS)75ti${^ScPHO^8fgx+>V``Q*~W<{>!oG$)2(0+#o_u( zD9-~Th!daJRL^Ga#ak%X@weuao=D@l8s}eKu{HzG3Y1w17Jq;Iu=GsQ=XdADn1Y^X z9A#+g%f&Jilj>~!n()XxTN0a5B#*%3`Tl~Jq^hO*D+waItT*>(r;|F}V+t&y4H^vh zW&Z{50nvSVTOhKI&+_bk&*U^WdE%GS{OD_{_n%Afc|jDOK-qncva!LH&ga1e;-3b|c`1GKj!~Jf- zbsc)qO&at0)ip18Kj^tA;cI#4dGLp^q z+lT$PuQSxrD0%D*Y}4@tEmRv0KIqdJbbBsuaMg>v3^)2TnY59pE{2A-(uvReN?a@d zjpqh7=;;#?Z^>7yWqhY05Vg9ell`>2FTQ0)Zut-W|9Ju4X@UynALVy9HGkbciu8-4 zq0JM5lE2EasK@v}xbLSqu11k)DZn|j86R)|JeQb3yU~(|j}-t1P2HbjJ$^g6CV_aa zy$+EMw0f_FBkEJ9U;Ub>LcaouLf)H;^Y*;`j^rh%Tra5GGxa!0uX>`qZPl^$NlON@ zkY8;#`>halB=GQhZSZ?Vp#u}>=c{{~fG~>twGyK}qB24Pe?hlwU0`c>+qX2mM z3)gSA!tN+pMg)RkvyI5kSGxOC6@+g8^5CL6pEY@5!}(%js`P|Dc=8SF1EE>6(OV*% z4&e?^U|Sm+njQlpA)#;aQ?jtVer7WIY)P(K+RUfrT*Bkk?#i{8sLhR6W=|X^Wk%*| zsk#iWJuzmy4{AO4rXrdpbe_Mc@V=a>{lDn;3!9t;8&gvzuC-=D)GHCa^B9V@G$H7BoXJ> z{Fx2r*Ul$*zRMIN($U6%RgS-J-A)wzDa1$HBp^eRpc>Zv@tjuoP>ui8Fp z5VXpR1*2JL9f#eXsk2bP_33Un9b0#cFghA*Az`}lH{w zfCqWxI%7XUTr-DJ`0Mu@Kjc^Mj)C z!*o|%83}h%sN8)4sx5!1dxUxH#wJaTk}g}f$NbLD3L z^BXCui9cfDaAzAT-GdXfac<;_XecVDZHEm@iT{dwZn9i!N^bU1`R7+85RucJ{Ezx4 zT%7CFPWxL~wbYc7>-dCD_enZ6hiNI|$v*HC*O5|ML{wNnThjd$OYIo?;sTvtoy1?NJ zj8f3EQ3aZi*Gb=CfuT)?X zyYd4ID#QJ0be@b+k{FlpV9ij671OXv{5N%{C%x_M?HCQOU)!y{z9!LH)o1H&+~Usx zx1!am!D#}b%Zi<=1KUH1v(-W;ho`QvLP=22DsTs-Z0;*_cI*}3RYd>Ll4m=~Q5d5f&3JSO@Re`G{2l~-Pd`8JdpUQqURn~N>aF=Qe zZ=H$}XXp9G#V|G(MwRzsRK8f-!RyuMuDlGPr4EZGvyfz14vMHL>=qM)tSN%+yk8gM zY2?jvRdgt~91}vT_ywq!fX`(_a=glr>ALBtp{ z#G*%Hmj5m>VZ~$_mDhJ=Ud~B>9xFoLz8(ye6cQ!)`xti&p-_%-bBvs*$*bi=T8;3p zp8k;=4m9>jW?@vioM^b`>dQ!W(}u&Aa&R^!az4|>1G_fAO}7NFmKd1|6;0I}IPaF( zY!{VwYE0qV-Pq{3WaH;4|5EK#QKuTd=+XIUkmDCVqe!tmvi~Z^CGG+50W}T>^cA_b zxWOz>bpP9^6Vn|d56r>4<36nOM++*n9t@5;=qpw8gSl2LsLau&JC(QeQjt`quW=Qco+2ox>I58WH3k;dwE+3%R~t z%iu*CK1<8~POHQc_}0AlHj%#yS%{X3rb19LDV#b*Hz7ZxbuvF|JcQj9`LZ!r`tc;T zG>6D3)8KK=w(&LGt)oMAXdlYE=JQGG9cA>1+h+`sdxFkO@IXE5%>8gGhWGBoZc8zA zAEP+K>2^cNX|1OfXASAdamp0h5%;srpEHyM{oHec00sYu3s$8qfqW{nG}X{eNdv0}iPrFu8U4jtO}4=q z1W@N&+hZ|!GrDTp*XxNDa~Q=Yhv;XC9U|zS0oAy`#Fjz`{%C0Y_ATx>6)&xj2dC<& zHH1vJNyq~ZVuW%zZ+lddVUSfU`|vDP&|#1vCv)(5R;a*94H1OA2@o{tx5(7I*}&ch z>4A^l^)9aQ@iO5;re1T9_i{8<$d5GqAPVHAX7WqRgXU0;ZY6ErS6i$g6VDuolHPGa2WKM+IS(CJ4oYi1Hk0g0xT}TvUBH(H6U0K;SK5wp zB<&&r!K3GCpuM2%w9G7Ypfh<3Lz86$mejTJue#nn2=#HXp{F{r5p%60f z=+Zf3;|R6?Ugcu%Jt=uV}u;A7n8x*T_d8sOo&g*Odtc{<#a}9 zcEb!4;&71(HsyWsgS4h$hxwzP(&fVjDVCmis-SG(_IqUin~zc;Sq(+C4q7nd2jokZ zqK{6dSBJlm`ng3a$A`vg=CI5!NIK&t!f3RW;Cs{NLv+IuM3#NOy14ILM~ivdZD8JJtJ(6>b)|en1piBZtb5wbc7vD)m1N;`4mqH|6{0tc1K&(SCx| zIG!TH2@eXEG^+znHM5BqUJNEIFGnJjqt${W=1nqhi@mvsXIompnHbJ^@PMvA?;I`$ zM9BN7ALicVUFgL$pgh^eFk1b7In3t|~{F`$%H<9tS@lJma(J+9}>fk9r1%AO7<1#ZVt8~q71ufUzuk!Dk zYvY?(rOP`yhLZ2HUljTpG6wfL^`6WA61338QtX799ALsf)Vx|=wrhu{Wd9ivktO0q zZKi11{xM|q+X{Iq;d+-t4IVes&%zRlSHC%|25@If-ei!KEx8f(i73JG8w^{nGT}YP zBT@!;2g%YI9tZ0QOq!ilH9R#NL>1*tcTqN2B;hQX2&RJW)!byyU)Zi<{BYPDHL|D- zGxWC|ZT;hTZc2bDxhoO#Gg1~uiymxtVY3lQQxF=?PyQ;gpWteg)E~?EeFZmap!jd*6+qgwjF6x5fBN_2COvx{W+ zvX9#zDZdesEZT2t7Jq4(xeQvuxFg>Bd(O(y=|Iv)_!2xKC9bkaN{qXOYDPnp*E zXmFieFQ9q_Mg_|;u#3X$&!`Rs72N!Y;IYr4FdPukKeJ^In2Oo+n5H?Zk}Fsm^?||H z<}trT9F9a5yefj7k>lg`%K?A;a5m2iYKNq9>_-YYCVE@~!@`hwnq;Z77Sn&Wwx}ar z<0GD;oohY5x%_$-)S+)a_vDX?1okBQXWPVwg3zR4sKAk?fWh;h2MI(1{m=8?)qft~ zt{GVva0V)H*Z=tc-yZ=%@&3=R_}?D+e*%JLP`t5^bS@yjcSHi5lKdOFG8t&#{{rg$ Bok{=z diff --git a/docs/capturing-response.md b/docs/capturing-response.md index ad2ae16fd..e4cf09ce9 100644 --- a/docs/capturing-response.md +++ b/docs/capturing-response.md @@ -2,23 +2,22 @@ ## Captures -Captures are optional values captured from the HTTP response, in a named variable. Captures can be the -response status code, part of or the entire the body, and response headers. +Captures are optional values that are __extracted from the HTTP response__ and stored in a named variable. +These captures may be the response status code, part of or the entire the body, and response headers. -Captured variables are available through a run session; each new value of a given variable overrides the last value. +Captured variables can be accessed through a run session; each new value of a given variable overrides the last value. -Captures allow using data from one request in another request, when working with -[CSRF tokens] for instance. Variables can also be initialized at the start of the -session, by passing [variable values], or can be used in [templates]. +Captures can be useful for using data from one request in another request, such as when working with [CSRF tokens]. +Variables in a Hurl file can be created from captures or [injected into the session]. ```hurl -# An example to show how to pass a CSRF token from one request -# to another: +# An example to show how to pass a CSRF token +# from one request to another: # First GET request to get CSRF token value: GET https://example.org -HTTP/1.1 200 +HTTP 200 # Capture the CSRF token value from html body. [Captures] csrf_token: xpath "normalize-space(//meta[@name='_csrf_token']/@content)" @@ -27,7 +26,7 @@ csrf_token: xpath "normalize-space(//meta[@name='_csrf_token']/@content)" POST https://acmecorp.net/login?user=toto&password=1234 X-CSRF-TOKEN: {{csrf_token}} -HTTP/1.1 302 +HTTP 302 ``` Structure of a capture: @@ -40,13 +39,15 @@ Structure of a capture: -A capture consists of a variable name, followed by `:` and a query. The captures +A capture consists of a variable name, followed by `:` and a query. Captures section starts with `[Captures]`. ### Query -Query can be of the following type: +Queries are used to extract data from an HTTP response. + +A query can be of the following type: - [`status`](#status-capture) - [`header`](#header-capture) @@ -60,6 +61,7 @@ Query can be of the following type: - [`variable`](#variable-capture) - [`duration`](#duration-capture) +Extracted data can then be further refined using [filters]. ### Status capture @@ -69,7 +71,7 @@ keyword `status`. ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 [Captures] my_status: status ``` @@ -85,7 +87,7 @@ POST https://example.org/login user: toto password: 12345678 -HTTP/1.1 302 +HTTP 302 [Captures] next_url: header "Location" ``` @@ -100,7 +102,7 @@ GET https://example.org/redirecting [Options] location: true -HTTP/* 200 +HTTP 200 [Captures] landing_url: url ``` @@ -114,7 +116,7 @@ and a cookie name. ```hurl GET https://example.org/cookies/set -HTTP/1.0 200 +HTTP 200 [Captures] session-id: cookie "LSID" ``` @@ -126,7 +128,7 @@ Cookie attributes value can also be captured by using the following format: ```hurl GET https://example.org/cookies/set -HTTP/1.0 200 +HTTP 200 [Captures] value1: cookie "LSID" value2: cookie "LSID[Value]" # Equivalent to the previous capture @@ -147,7 +149,7 @@ Capture the entire body (decoded as text) from the received HTTP response ```hurl GET https://example.org/home -HTTP/1.1 200 +HTTP 200 [Captures] my_body: body ``` @@ -159,7 +161,7 @@ Capture the entire body (as a raw bytestream) from the received HTTP response ```hurl GET https://example.org/data.bin -HTTP/1.1 200 +HTTP 200 [Captures] my_data: bytes ``` @@ -174,14 +176,14 @@ Currently, only XPath 1.0 expression can be used. GET https://example.org/home # Capture the identifier from the dom node

-
- my_varvariable - : - xpath "string(//h1)"query - regex "(\\d+)"filter (optional) -
- - -### Count filter - -Returns the count of a collection. - -```hurl -GET https://pets.org/cats/cutest - -HTTP/1.0 200 -[Captures] -cats_size: jsonpath "$.cats" count -``` - -### Regex filter - -```hurl -GET https://pets.org/cats/cutest - -HTTP/1.0 200 -# Cat name are structured like this `meow + id`: for instance `meow123456` -[Captures] -id: jsonpath "$.cats[0].name" regex "meow(\\d+)" -``` - -Pattern of the regex filter must have at least one capture group, otherwise the -capture will fail. Metacharacters beginning with a backslash in the pattern -(like `\d`, `\s`) must be escaped: `regex "(\\d+)!"` will capture one or more digit. - [CSRF tokens]: https://en.wikipedia.org/wiki/Cross-site_request_forgery -[variable values]: /docs/manual.md#variable -[templates]: /docs/templates.md +[injected into the session]: /docs/templates.md#injecting-variables [`Set-Cookie`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie [XPath]: https://en.wikipedia.org/wiki/XPath [JSONPath]: https://goessner.net/articles/JsonPath/ [XPath captures]: #xpath-capture [Javascript-like Regular expression syntax]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions [options]: /docs/request.md#options -[`--location` option]: /docs/manual.md#location \ No newline at end of file +[`--location` option]: /docs/manual.md#location +[filters]: /docs/filters.md \ No newline at end of file diff --git a/docs/entry.md b/docs/entry.md index 8c063b62f..96bbe123f 100644 --- a/docs/entry.md +++ b/docs/entry.md @@ -13,22 +13,21 @@ to [capture values] to perform subsequent requests, or [add asserts to HTTP resp # First, test home title. GET https://acmecorp.net -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "normalize-space(//head/title)" == "Hello world!" # Get some news, response description is optional GET https://acmecorp.net/news -# Do a POST request without csrf token and check +# Do a POST request without CSRF token and check # that status code is Forbidden 403 POST https://acmecorp.net/contact [FormParams] default: false email: john.doe@rookie.org number: 33611223344 - -HTTP/1.1 403 +HTTP 403 ``` ## Description @@ -42,24 +41,24 @@ every entry of a given file will follow redirection: $ hurl --location foo.hurl ``` -You can use an [`[Options]` section] to use option only for a specified option. For instance, in this Hurl file: +You can use an [`[Options]` section][options] to use option only for a specified option. For instance, in this Hurl file: ```hurl GET https://google.fr -HTTP/* 301 +HTTP 301 GET https://google.fr [Options] location: true -HTTP/* 200 +HTTP 200 GET https://google.fr -HTTP/* 301 +HTTP 301 ``` -The second entry will follow location (and so we can test the status code to be 200 instead of 301). +The second entry will follow location (so we can test the status code to be 200 instead of 301). -You can use it to logs a specific entry: +You can use it to log a specific entry: ```hurl # ... previous entries @@ -67,8 +66,7 @@ You can use it to logs a specific entry: GET https://api.example.org [Options] very-verbose: true - -HTTP/* 200 +HTTP 200 # ... next entries ``` @@ -83,17 +81,15 @@ By default, Hurl doesn't follow redirection. To effectively run a redirection, e of the redirection, allowing insertion of asserts in each response. ```hurl -# First entry, test the redirection (status code and -# Location header) +# First entry, test the redirection (status code and 'Location' header) GET https://google.fr -HTTP/1.1 301 +HTTP 301 Location: https://www.google.fr/ # Second entry, the 200 OK response GET https://www.google.fr - -HTTP/1.1 200 +HTTP 200 ``` Alternatively, one can use [`--location`] option to force redirection @@ -103,7 +99,7 @@ redirections can be limited with [`--max-redirs`]. ```hurl # Running hurl --location google.hurl GET https://google.fr -HTTP/1.1 200 +HTTP 200 ``` Finally, you can force redirection on a particular request with an [`[Options]` section][options] and the [`--location` option]: @@ -112,7 +108,7 @@ Finally, you can force redirection on a particular request with an [`[Options]` GET https://google.fr [Options] location: true -HTTP/1.1 200 +HTTP 200 ``` ### Retry @@ -129,7 +125,7 @@ For example, in this Hurl file, first we create a new job, then we poll the new # Create a new job POST http://api.example.org/jobs -HTTP/* 201 +HTTP 201 [Captures] job_id: jsonpath "$.id" [Asserts] @@ -141,7 +137,7 @@ GET http://api.example.org/jobs/{{job_id}} [Options] retry: true -HTTP/* 200 +HTTP 200 [Asserts] jsonpath "$.state" == "COMPLETED" ``` @@ -154,7 +150,7 @@ jsonpath "$.state" == "COMPLETED" [`--location`]: /docs/manual.md#location [`--max-redirs`]: /docs/manual.md#max-redirs [Options]: /docs/manual.md#options -[options]: /docs/manual.md#options +[options]: /docs/request.md#options [`--location` option]: /docs/manual.md#location [headers]: /docs/response.md#headers [status code]: /docs/response.md#version-status diff --git a/docs/filters.md b/docs/filters.md new file mode 100644 index 000000000..fa41e9a67 --- /dev/null +++ b/docs/filters.md @@ -0,0 +1,189 @@ +# Filters + +## Definition + +[Captures] and [asserts] share a common structure: query. A query is used to extract data from an HTTP response; this data +can come from the HTTP response body, the HTTP response headers or from the HTTP meta-informations (like `duration` for instance)... + +In this example, the query __`jsonpath "$.books[0].name"`__ is used in a capture to save data and in an assert to test +the HTTP response body. + +__Capture__: + +
+
+ namevariable + : + jsonpath "$.books[0].name"query +
+
+ +__Assert__: + +
+
+ jsonpath "$.books[0].name"query + == "Dune"predicate +
+
+ +In both case, the query is exactly the same: queries are the core structure of asserts and captures. Sometimes, you want +to process data extracted by queries: that's the purpose of __filters__. + +Filters are used to transform value extracted by a query and can be used in asserts and captures to refine data. Filters +__can be chained__, allowing for fine-grained data extraction. + + +
+
+ jsonpath "$.name"query + split "," nth 02 filters + == "Herbert"predicate +
+
+ + +## Example + +```hurl +GET https://example.org/api + +HTTP 200 +[Captures] +name: jsonpath "$user.id" replace /\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 +``` + +## Description + +### count + +Counts the number of items in a collection. + +```hurl +GET https://example.org/api + +HTTP 200 +[Asserts] +jsonpath "$.books" count == 12 +``` + +### htmlEscape + +Converts the characters `&`, `<` and `>` to HTML-safe sequence. + +```hurl +GET https://example.org/api + +HTTP 200 +[Asserts] +jsonpath "$.text" htmlEscape == "a > b" +``` + +### htmlUnescape + +Converts all named and numeric character references (e.g. `>`, `>`, `>`) to the corresponding Unicode characters. + +```hurl +GET https://example.org/api + +HTTP 200 +[Asserts] +jsonpath "$.escaped_html[1]" htmlUnescape == "Foo © bar 𝌆" +``` + +### nth + +Returns the element from a collection at a zero-based index. + +```hurl +GET https://example.org/api + +HTTP 200 +[Asserts] +jsonpath "$.books" nth 2 == "Children of Dune" +``` + +### regex + +Extracts regex capture group. Pattern must have at least one capture group. + +```hurl +GET https://example.org/foo + +HTTP 200 +[Captures] +param1: header "header1" +param2: header "header2" regex "Hello (.*)!" +param3: header "header2" regex /Hello (.*)!/ +``` + +### replace + +Replaces all occurrences of old string with new string. + +```hurl +GET https://example.org/foo + +HTTP 200 +[Captures] +url: jsonpath "$.url" replace "http://" "https://" +[Asserts] +jsonpath "$.ips" replace ", " "|" == "192.168.2.1|10.0.0.20|10.0.0.10" +``` + +### split + +Splits to a list of strings around occurrences of the specified delimiter. + +```hurl +GET https://example.org/foo + +HTTP 200 +[Asserts] +jsonpath "$.ips" split ", " count == 3 +``` + +### toInt + +Converts to integer number. + +```hurl +GET https://example.org/foo + +HTTP 200 +[Asserts] +jsonpath "$.id" toInt == 123 +``` + +### urlDecode + +Replaces %xx escapes with their single-character equivalent. + +```hurl +GET https://example.org/foo + +HTTP 200 +[Asserts] +jsonpath "$.encoded_url" urlDecode == "https://mozilla.org/?x=шеллы" +``` + +### urlEncode + +Percent-encodes all the characters which are not included in unreserved chars (see [RFC3986]) with the exception of forward slash (/). + +```hurl +GET https://example.org/foo + +HTTP 200 +[Asserts] +jsonpath "$.url" urlEncode == "https%3A//mozilla.org/%3Fx%3D%D1%88%D0%B5%D0%BB%D0%BB%D1%8B" +``` + +[Captures]: /docs/capturing-response.md +[asserts]: /docs/asserting-response.md +[RFC3986]: https://www.rfc-editor.org/rfc/rfc3986 \ No newline at end of file diff --git a/docs/home.md b/docs/home.md index 99d05188f..be5ca87b5 100644 --- a/docs/home.md +++ b/docs/home.md @@ -10,21 +10,24 @@ Hurl is a command line tool that runs HTTP requests defined in a simple plain text format. It can chain requests, capture values and evaluate queries on headers and body response. Hurl is very -versatile: it can be used for fetching data, testing HTTP sessions and testing XML / JSON APIs. +versatile: it can be used for both fetching data and testing HTTP sessions. + +Hurl makes it easy to work with HTML content, REST / SOAP / GraphQL APIs, or any other XML / JSON based APIs. ```hurl # Get home: GET https://example.org -HTTP/1.1 200 +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/1.1 302 +HTTP 302 ``` Chaining multiple requests is easy: @@ -53,7 +56,7 @@ POST https://example.org/api/tests "evaluate": true } -HTTP/1.1 200 +HTTP 200 [Asserts] header "X-Frame-Options" == "SAMEORIGIN" jsonpath "$.status" == "RUNNING" # Check the status code @@ -66,12 +69,27 @@ jsonpath "$.id" matches /\d{4}/ # Check the format of the id ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "normalize-space(//head/title)" == "Hello world!" ``` -and even SOAP APIs +GraphQL + +~~~hurl +POST https://example.org/graphql +```graphql +{ + human(id: "1000") { + name + height(unit: FOOT) + } +} +``` +HTTP 200 +~~~ + +and even SOAP APIs ```hurl POST https://example.org/InStock @@ -86,8 +104,7 @@ SOAPAction: "http://www.w3.org/2003/05/soap-envelope" - -HTTP/1.1 200 +HTTP 200 ``` Hurl can also be used to performance test HTTP endpoints: @@ -95,7 +112,7 @@ Hurl can also be used to performance test HTTP endpoints: ```hurl GET https://example.org/api/v1/pets -HTTP/1.0 200 +HTTP 200 [Asserts] duration < 1000 # Duration in ms ``` @@ -105,7 +122,7 @@ And response bytes ```hurl GET https://example.org/data.tar.gz -HTTP/1.0 200 +HTTP 200 [Asserts] sha256 == hex,039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81; ``` @@ -136,7 +153,7 @@ POST https://hurl.dev/api/feedback "name": "John Doe", "feedback": "Hurl is awesome !" } -HTTP/1.1 200 +HTTP 200 ``` # Resources diff --git a/docs/hurl-file.md b/docs/hurl-file.md index d47e5368a..5dcdec915 100644 --- a/docs/hurl-file.md +++ b/docs/hurl-file.md @@ -20,7 +20,7 @@ a documentation for HTTP based workflows so it can be useful to be very descript GET https://www.sample.net x-app: MY_APP # Add a dummy header -HTTP/1.1 302 # Check that we have a redirection +HTTP 302 # Check that we have a redirection [Asserts] header "Location" exists header "Location" contains "login" # Check that we are redirected to the login page @@ -37,8 +37,7 @@ String can include the following special characters: ```hurl GET https://example.org/api -HTTP/1.1 200 - +HTTP 200 # The following assert are equivalent: [Asserts] jsonpath "$.slideshow.title" == "A beautiful ✈!" @@ -51,7 +50,7 @@ In the following example: ```hurl GET https://example.org/api x-token: BEEF \#STEACK # Some comment -HTTP/1.1 200 +HTTP 200 ``` We're sending a header `x-token` with value `BEEF #STEACK` diff --git a/docs/installation.md b/docs/installation.md index 98d0565d5..5ed974d1c 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -4,12 +4,12 @@ ### Linux -Precompiled binary is available at [hurl-1.8.0-x86_64-linux.tar.gz]: +Precompiled binary is available at [hurl-2.0.0-x86_64-linux.tar.gz]: ```shell $ INSTALL_DIR=/tmp -$ curl -sL https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-x86_64-linux.tar.gz | tar xvz -C $INSTALL_DIR -$ export PATH=$INSTALL_DIR/hurl-1.8.0:$PATH +$ curl -sL https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-x86_64-linux.tar.gz | tar xvz -C $INSTALL_DIR +$ export PATH=$INSTALL_DIR/hurl-2.0.0:$PATH ``` #### Debian / Ubuntu @@ -17,8 +17,8 @@ $ export PATH=$INSTALL_DIR/hurl-1.8.0:$PATH For Debian / Ubuntu, Hurl can be installed using a binary .deb file provided in each Hurl release. ```shell -$ curl -LO https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl_1.8.0_amd64.deb -$ sudo apt update && apt install ./hurl_1.8.0_amd64.deb +$ curl -LO https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl_2.0.0_amd64.deb +$ sudo apt update && apt install ./hurl_2.0.0_amd64.deb ``` #### Arch Linux / Manjaro @@ -31,7 +31,7 @@ $ sudo apt update && apt install ./hurl_1.8.0_amd64.deb ### macOS -Precompiled binary is available at [hurl-1.8.0-x86_64-macos.tar.gz] for x86 CPUs and [hurl-1.8.0-arm64-macos.tar.gz] for ARM CPUS. +Precompiled binary is available at [hurl-2.0.0-x86_64-macos.tar.gz] for x86 CPUs and [hurl-2.0.0-arm64-macos.tar.gz] for ARM CPUS. #### Homebrew @@ -55,11 +55,11 @@ $ sudo pkg install hurl #### Zip File -Hurl can be installed from a standalone zip file [hurl-1.8.0-win64.zip]. You will need to update your `PATH` variable. +Hurl can be installed from a standalone zip file [hurl-2.0.0-win64.zip]. You will need to update your `PATH` variable. #### Installer -An installer [hurl-1.8.0-win64-installer.exe] is also available. +An installer [hurl-2.0.0-win64-installer.exe] is also available. #### Chocolatey @@ -156,11 +156,11 @@ $ ./target/release/hurl --version Please follow the [contrib on Windows section]. [GitHub]: https://github.com/Orange-OpenSource/hurl -[hurl-1.8.0-win64.zip]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-win64.zip -[hurl-1.8.0-win64-installer.exe]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-win64-installer.exe -[hurl-1.8.0-x86_64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-x86_64-macos.tar.gz -[hurl-1.8.0-arm64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-arm64-macos.tar.gz -[hurl-1.8.0-x86_64-linux.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-x86_64-linux.tar.gz +[hurl-2.0.0-win64.zip]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-win64.zip +[hurl-2.0.0-win64-installer.exe]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-win64-installer.exe +[hurl-2.0.0-x86_64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-x86_64-macos.tar.gz +[hurl-2.0.0-arm64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-arm64-macos.tar.gz +[hurl-2.0.0-x86_64-linux.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-x86_64-linux.tar.gz [AUR]: https://wiki.archlinux.org/index.php/Arch_User_Repository [`hurl-bin` package]: https://aur.archlinux.org/packages/hurl-bin/ [install]: https://www.rust-lang.org/tools/install diff --git a/docs/manual.md b/docs/manual.md index 976fd82bb..c0154ae14 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -12,9 +12,9 @@ hurl - run and test HTTP requests. ## Description -**Hurl** is an HTTP client that performs HTTP requests defined in a simple plain text format. +**Hurl** is a command line tool that runs HTTP requests defined in a simple plain text format. -Hurl is very versatile. It enables chaining HTTP requests, capturing values from HTTP responses, and making assertions. +It can chain requests, capture values and evaluate queries on headers and body response. Hurl is very versatile, it can be used for fetching data and testing HTTP sessions: HTML content, REST / SOAP / GraphQL APIs, or any other XML / JSON based APIs. ```shell $ hurl session.hurl @@ -71,11 +71,11 @@ GET http:/example.org/endpoint2 A value from an HTTP response can be-reused for successive HTTP requests. -A typical example occurs with csrf tokens. +A typical example occurs with CSRF tokens. ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 # Capture the CSRF token value from html body. [Captures] csrf_token: xpath "normalize-space(//meta[@name='_csrf_token']/@content)" @@ -89,28 +89,28 @@ More information on captures can be found here [https://hurl.dev/docs/capturing- ### Asserts -The HTTP response defined in the Hurl session are used to make asserts. +The HTTP response defined in the Hurl file are used to make asserts. Responses are optional. -At the minimum, the response includes the asserts on the HTTP version and status code. +At the minimum, response includes assert on the HTTP status code. ```hurl -GET http:/google.com -HTTP/1.1 301 +GET http:/example.org +HTTP 301 ``` It can also include asserts on the response headers ```hurl -GET http:/google.com -HTTP/1.1 301 -Location: http://www.google.com +GET http:/example.org +HTTP 301 +Location: http://www.example.org ``` Explicit asserts can be included by combining a query and a predicate ```hurl -GET http:/google.com -HTTP/1.1 301 +GET http:/example.org +HTTP 301 [Asserts] xpath "string(//title)" == "301 Moved" ``` @@ -134,56 +134,61 @@ $ hurl --location foo.hurl will follow redirection for each entry in `foo.hurl`. You can also define an option only for a particular entry with an `[Options]` section. For instance, this Hurl file: ```hurl -GET https://google.com -HTTP/* 301 +GET https://example.org +HTTP 301 -GET https://google.com +GET https://example.org [Options] location: true -HTTP/* 200 +HTTP 200 ``` will follow a redirection only for the second entry. -Option | Description - --- | --- -
--cacert | Specifies the certificate file for peer verification. The file may contain multiple CA certificates and must be in PEM format.
Normally Hurl is built to use a default file for this, so this option is typically used to alter that default file.
---color | Colorize Output.
---compressed | Request a compressed response using one of the algorithms br, gzip, deflate and automatically decompress the content.
---connect-timeout <SECONDS> | Maximum time in seconds that you allow Hurl's connection to take.

See also [`-m, --max-time`](#max-time) option.
--b, --cookie <FILE> | Read cookies from FILE (using the Netscape cookie file format).

Combined with [`-c, --cookie-jar`](#cookie-jar), you can simulate a cookie storage between successive Hurl runs.
--c, --cookie-jar <FILE> | Write cookies to FILE after running the session (only for one session).
The file will be written using the Netscape cookie file format.

Combined with [`-b, --cookie`](#cookie), you can simulate a cookie storage between successive Hurl runs.
---fail-at-end | Continue executing requests to the end of the Hurl file even when an assert error occurs.
By default, Hurl exits after an assert error in the HTTP response.

Note that this option does not affect the behavior with multiple input Hurl files.

All the input files are executed independently. The result of one file does not affect the execution of the other Hurl files.
---file-root <DIR> | Set root file system to import files in Hurl. This is used for both files in multipart form data and request body.
When this is not explicitly defined, the files are relative to the current directory in which Hurl is running.
--L, --location | Follow redirect. To limit the amount of redirects to follow use the [`--max-redirs`](#max-redirs) option
---glob <GLOB> | Specify input files that match the given glob pattern.

Multiple glob flags may be used. This flag supports common Unix glob patterns like *, ? and [].
However, to avoid your shell accidentally expanding glob patterns before Hurl handles them, you must use single quotes or double quotes around each pattern.
--i, --include | Include the HTTP headers in the output (last entry).
---ignore-asserts | Ignore all asserts defined in the Hurl file.
--k, --insecure | This option explicitly allows Hurl to perform "insecure" SSL connections and transfers.
---interactive | Stop between requests.
This is similar to a break point, You can then continue (Press C) or quit (Press Q).
---json | Output each hurl file result to JSON. The format is very closed to HAR format.
---max-redirs <NUM> | Set maximum number of redirection-followings allowed
By default, the limit is set to 50 redirections. Set this option to -1 to make it unlimited.
--m, --max-time <SECONDS> | Maximum time in seconds that you allow a request/response to take. This is the standard timeout.

See also [`--connect-timeout`](#connect-timeout) option.
---no-color | Do not colorize output.
---no-output | Suppress output. By default, Hurl outputs the body of the last response.
---noproxy <HOST(S)> | Comma-separated list of hosts which do not use a proxy.
Override value from Environment variable no_proxy.
--o, --output <FILE> | Write output to FILE instead of stdout.
--x, --proxy [protocol://]host[:port] | Use the specified proxy.
---report-junit <FILE> | Generate JUnit File.

If the FILE report already exists, it will be updated with the new test results.
---report-html <DIR> | Generate HTML report in DIR.

If the HTML report already exists, it will be updated with the new test results.
---retry | Retry requests if any error occurs (asserts, captures, runtimes etc...).
---retry-interval <MILLISECONDS> | Duration in milliseconds between each retry. Default is 1000 ms.
---retry-max-count <NUM> | Maximum number of retries. Set this option to -1 to make it unlimited. Default is 10.
---test | Activate test mode: with this, the HTTP response is not outputted anymore, progress is reported for each Hurl file tested, and a text summary is displayed when all files have been run.
---to-entry <ENTRY_NUMBER> | Execute Hurl file to ENTRY_NUMBER (starting at 1).
Ignore the remaining of the file. It is useful for debugging a session.
--u, --user <USER:PASSWORD> | Add basic Authentication header to each request.
--A, --user-agent <NAME> | Specify the User-Agent string to send to the HTTP server.
---variable <NAME=VALUE> | Define variable (name/value) to be used in Hurl templates.
---variables-file <FILE> | Set properties file in which your define your variables.

Each variable is defined as name=value exactly as with [`--variable`](#variable) option.

Note that defining a variable twice produces an error.
--v, --verbose | Turn on verbose output on standard error stream.
Useful for debugging.

A line starting with '>' means data sent by Hurl.
A line staring with '<' means data received by Hurl.
A line starting with '*' means additional info provided by Hurl.

If you only want HTTP headers in the output, [`-i, --include`](#include) might be the option you're looking for.
---very-verbose | Turn on more verbose output on standard error stream.

In contrast to [`--verbose`](#verbose) option, this option outputs the full HTTP body request and response on standard error. In addition, lines starting with '**' are libcurl debug logs.
--h, --help | Usage help. This lists all current command line options with a short description.
--V, --version | Prints version information
+| Option | Description | +|------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| --cacert <FILE> | Specifies the certificate file for peer verification. The file may contain multiple CA certificates and must be in PEM format.
Normally Hurl is built to use a default file for this, so this option is typically used to alter that default file.
| +| -E, --cert <CERTIFICATE[:PASSWORD]> | Client certificate file and password.

See also [`--key`](#key).
| +| --color | Colorize Output.
| +| --compressed | Request a compressed response using one of the algorithms br, gzip, deflate and automatically decompress the content.
| +| --connect-timeout <SECONDS> | Maximum time in seconds that you allow Hurl's connection to take.

See also [`-m, --max-time`](#max-time).
| +| --connect-to <HOST1:PORT1:HOST2:PORT2> | For a request to the given HOST1:PORT1 pair, connect to HOST2:PORT2 instead. This option can be used several times in a command line.

See also [`--resolve`](#resolve).
| +| -b, --cookie <FILE> | Read cookies from FILE (using the Netscape cookie file format).

Combined with [`-c, --cookie-jar`](#cookie-jar), you can simulate a cookie storage between successive Hurl runs.
| +| -c, --cookie-jar <FILE> | Write cookies to FILE after running the session (only for one session).
The file will be written using the Netscape cookie file format.

Combined with [`-b, --cookie`](#cookie), you can simulate a cookie storage between successive Hurl runs.
| +| --fail-at-end | Continue executing requests to the end of the Hurl file even when an assert error occurs.
By default, Hurl exits after an assert error in the HTTP response.

Note that this option does not affect the behavior with multiple input Hurl files.

All the input files are executed independently. The result of one file does not affect the execution of the other Hurl files.
| +| --file-root <DIR> | Set root file system to import files in Hurl. This is used for both files in multipart form data and request body.
When this is not explicitly defined, the files are relative to the current directory in which Hurl is running.
| +| -L, --location | Follow redirect. To limit the amount of redirects to follow use the [`--max-redirs`](#max-redirs) option
| +| --glob <GLOB> | Specify input files that match the given glob pattern.

Multiple glob flags may be used. This flag supports common Unix glob patterns like *, ? and [].
However, to avoid your shell accidentally expanding glob patterns before Hurl handles them, you must use single quotes or double quotes around each pattern.
| +| -i, --include | Include the HTTP headers in the output (last entry).
| +| --ignore-asserts | Ignore all asserts defined in the Hurl file.
| +| -k, --insecure | This option explicitly allows Hurl to perform "insecure" SSL connections and transfers.
| +| --interactive | Stop between requests.
This is similar to a break point, You can then continue (Press C) or quit (Press Q).
| +| --json | Output each hurl file result to JSON. The format is very closed to HAR format.
| +| --key <KEY> | Private key file name.
| +| --max-redirs <NUM> | Set maximum number of redirection-followings allowed
By default, the limit is set to 50 redirections. Set this option to -1 to make it unlimited.
| +| -m, --max-time <SECONDS> | Maximum time in seconds that you allow a request/response to take. This is the standard timeout.

See also [`--connect-timeout`](#connect-timeout).
| +| --no-color | Do not colorize output.
| +| --no-output | Suppress output. By default, Hurl outputs the body of the last response.
| +| --noproxy <HOST(S)> | Comma-separated list of hosts which do not use a proxy.
Override value from Environment variable no_proxy.
| +| -o, --output <FILE> | Write output to FILE instead of stdout.
| +| -x, --proxy <[PROTOCOL://]HOST[:PORT]> | Use the specified proxy.
| +| --report-junit <FILE> | Generate JUnit File.

If the FILE report already exists, it will be updated with the new test results.
| +| --report-html <DIR> | Generate HTML report in DIR.

If the HTML report already exists, it will be updated with the new test results.
| +| --resolve <HOST:PORT:ADDR> | Provide a custom address for a specific host and port pair. Using this, you can make the Hurl requests(s) use a specified address and prevent the otherwise normally resolved address to be used. Consider it a sort of /etc/hosts alternative provided on the command line.
| +| --retry | Retry requests if any error occurs (asserts, captures, runtimes etc...).
| +| --retry-interval <MILLISECONDS> | Duration in milliseconds between each retry. Default is 1000 ms.
| +| --retry-max-count <NUM> | Maximum number of retries. Set this option to -1 to make it unlimited. Default is 10.
| +| --ssl-no-revoke | (Windows) This option tells Hurl to disable certificate revocation checks. WARNING: this option loosens the SSL security, and by using this flag you ask for exactly that.
| +| --test | Activate test mode: with this, the HTTP response is not outputted anymore, progress is reported for each Hurl file tested, and a text summary is displayed when all files have been run.
| +| --to-entry <ENTRY_NUMBER> | Execute Hurl file to ENTRY_NUMBER (starting at 1).
Ignore the remaining of the file. It is useful for debugging a session.
| +| -u, --user <USER:PASSWORD> | Add basic Authentication header to each request.
| +| -A, --user-agent <NAME> | Specify the User-Agent string to send to the HTTP server.
| +| --variable <NAME=VALUE> | Define variable (name/value) to be used in Hurl templates.
| +| --variables-file <FILE> | Set properties file in which your define your variables.

Each variable is defined as name=value exactly as with [`--variable`](#variable) option.

Note that defining a variable twice produces an error.
| +| -v, --verbose | Turn on verbose output on standard error stream.
Useful for debugging.

A line starting with '>' means data sent by Hurl.
A line staring with '<' means data received by Hurl.
A line starting with '*' means additional info provided by Hurl.

If you only want HTTP headers in the output, [`-i, --include`](#include) might be the option you're looking for.
| +| --very-verbose | Turn on more verbose output on standard error stream.

In contrast to [`--verbose`](#verbose) option, this option outputs the full HTTP body request and response on standard error. In addition, lines starting with '**' are libcurl debug logs.
| +| -h, --help | Usage help. This lists all current command line options with a short description.
| +| -V, --version | Prints version information
| ## Environment @@ -191,23 +196,23 @@ Environment variables can only be specified in lowercase. Using an environment variable to set the proxy has the same effect as using the [`-x, --proxy`](#proxy) option. -Variable | Description - --- | --- -`http_proxy [protocol://][:port]` | Sets the proxy server to use for HTTP.
-`https_proxy [protocol://][:port]` | Sets the proxy server to use for HTTPS.
-`all_proxy [protocol://][:port]` | Sets the proxy server to use if no protocol-specific proxy is set.
-`no_proxy ` | List of host names that shouldn't go through any proxy.
-`HURL_name value` | Define variable (name/value) to be used in Hurl templates. This is similar than [`--variable`](#variable) and [`--variables-file`](#variables-file) options.
-`NO_COLOR` | When set to a non-empty string, do not colorize output (see [`--no-color`](#no-color) option).
+| Variable | Description | +|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `http_proxy [protocol://][:port]` | Sets the proxy server to use for HTTP.
| +| `https_proxy [protocol://][:port]` | Sets the proxy server to use for HTTPS.
| +| `all_proxy [protocol://][:port]` | Sets the proxy server to use if no protocol-specific proxy is set.
| +| `no_proxy ` | List of host names that shouldn't go through any proxy.
| +| `HURL_name value` | Define variable (name/value) to be used in Hurl templates. This is similar than [`--variable`](#variable) and [`--variables-file`](#variables-file) options.
| +| `NO_COLOR` | When set to a non-empty string, do not colorize output (see [`--no-color`](#no-color) option).
| ## Exit Codes -Value | Description - --- | --- -`1` | Failed to parse command-line options.
-`2` | Input File Parsing Error.
-`3` | Runtime error (such as failure to connect to host).
-`4` | Assert Error.
+| Value | Description | +|-------|---------------------------------------------------------| +| `1` | Failed to parse command-line options.
| +| `2` | Input File Parsing Error.
| +| `3` | Runtime error (such as failure to connect to host).
| +| `4` | Assert Error.
| ## WWW diff --git a/docs/manual/hurl.1 b/docs/manual/hurl.1 index f2832efd9..d501a3b4d 100644 --- a/docs/manual/hurl.1 +++ b/docs/manual/hurl.1 @@ -1,4 +1,4 @@ -.TH hurl 1 "07 Nov 2022" "hurl 2.0.0-SNAPSHOT" " Hurl Manual" +.TH hurl 1 "24 Jan 2023" "hurl 2.0.0-SNAPSHOT" " Hurl Manual" .SH NAME hurl - run and test HTTP requests. @@ -13,9 +13,9 @@ hurl - run and test HTTP requests. .SH DESCRIPTION .B Hurl -is an HTTP client that performs HTTP requests defined in a simple plain text format. +is a command line tool that runs HTTP requests defined in a simple plain text format. -Hurl is very versatile. It enables chaining HTTP requests, capturing values from HTTP responses, and making assertions. +It can chain requests, capture values and evaluate queries on headers and body response. Hurl is very versatile, it can be used for fetching data and testing HTTP sessions: HTML content, REST / SOAP / GraphQL APIs, or any other XML / JSON based APIs. $ hurl session.hurl @@ -62,10 +62,10 @@ It consists of one or several HTTP requests A value from an HTTP response can be-reused for successive HTTP requests. -A typical example occurs with csrf tokens. +A typical example occurs with CSRF tokens. GET https://example.org - HTTP/1.1 200 + HTTP 200 # Capture the CSRF token value from html body. [Captures] csrf_token: xpath "normalize-space(//meta[@name='_csrf_token']/@content)" @@ -78,23 +78,23 @@ More information on captures can be found here \fIhttps://hurl.dev/docs/capturin .IP "Asserts" -The HTTP response defined in the Hurl session are used to make asserts. +The HTTP response defined in the Hurl file are used to make asserts. Responses are optional. -At the minimum, the response includes the asserts on the HTTP version and status code. +At the minimum, response includes assert on the HTTP status code. - GET http:/google.com - HTTP/1.1 301 + GET http:/example.org + HTTP 301 It can also include asserts on the response headers - GET http:/google.com - HTTP/1.1 301 - Location: http://www.google.com + GET http:/example.org + HTTP 301 + Location: http://www.example.org Explicit asserts can be included by combining a query and a predicate - GET http:/google.com - HTTP/1.1 301 + GET http:/example.org + HTTP 301 [Asserts] xpath "string(//title)" == "301 Moved" @@ -114,21 +114,27 @@ For instance: will follow redirection for each entry in `foo.hurl`. You can also define an option only for a particular entry with an `[Options]` section. For instance, this Hurl file: - GET https://google.com - HTTP/* 301 + GET https://example.org + HTTP 301 - GET https://google.com + GET https://example.org [Options] location: true - HTTP/* 200 + HTTP 200 will follow a redirection only for the second entry. -.IP "--cacert " +.IP "--cacert " Specifies the certificate file for peer verification. The file may contain multiple CA certificates and must be in PEM format. Normally Hurl is built to use a default file for this, so this option is typically used to alter that default file. +.IP "-E, --cert " + +Client certificate file and password. + +See also \fI--key\fP. + .IP "--color " Colorize Output. @@ -141,7 +147,13 @@ Request a compressed response using one of the algorithms br, gzip, deflate and Maximum time in seconds that you allow Hurl's connection to take. -See also \fI-m, --max-time\fP option. +See also \fI-m, --max-time\fP. + +.IP "--connect-to " + +For a request to the given HOST1:PORT1 pair, connect to HOST2:PORT2 instead. This option can be used several times in a command line. + +See also \fI--resolve\fP. .IP "-b, --cookie " @@ -202,6 +214,10 @@ This is similar to a break point, You can then continue (Press C) or quit (Press Output each hurl file result to JSON. The format is very closed to HAR format. +.IP "--key " + +Private key file name. + .IP "--max-redirs " Set maximum number of redirection-followings allowed @@ -211,7 +227,7 @@ By default, the limit is set to 50 redirections. Set this option to -1 to make i Maximum time in seconds that you allow a request/response to take. This is the standard timeout. -See also \fI--connect-timeout\fP option. +See also \fI--connect-timeout\fP. .IP "--no-color " @@ -230,7 +246,7 @@ Override value from Environment variable no_proxy. Write output to FILE instead of stdout. -.IP "-x, --proxy [protocol://]host[:port] " +.IP "-x, --proxy <[PROTOCOL://]HOST[:PORT]> " Use the specified proxy. @@ -246,6 +262,10 @@ Generate HTML report in DIR. If the HTML report already exists, it will be updated with the new test results. +.IP "--resolve " + +Provide a custom address for a specific host and port pair. Using this, you can make the Hurl requests(s) use a specified address and prevent the otherwise normally resolved address to be used. Consider it a sort of /etc/hosts alternative provided on the command line. + .IP "--retry " Retry requests if any error occurs (asserts, captures, runtimes etc...). @@ -258,6 +278,10 @@ Duration in milliseconds between each retry. Default is 1000 ms. Maximum number of retries. Set this option to -1 to make it unlimited. Default is 10. +.IP "--ssl-no-revoke " + +(Windows) This option tells Hurl to disable certificate revocation checks. WARNING: this option loosens the SSL security, and by using this flag you ask for exactly that. + .IP "--test " Activate test mode: with this, the HTTP response is not outputted anymore, progress is reported for each Hurl file tested, and a text summary is displayed when all files have been run. diff --git a/docs/manual/hurl.md b/docs/manual/hurl.md index 1bcd3230c..8aac6f6f6 100644 --- a/docs/manual/hurl.md +++ b/docs/manual/hurl.md @@ -10,9 +10,9 @@ hurl - run and test HTTP requests. ## DESCRIPTION -**Hurl** is an HTTP client that performs HTTP requests defined in a simple plain text format. +**Hurl** is a command line tool that runs HTTP requests defined in a simple plain text format. -Hurl is very versatile. It enables chaining HTTP requests, capturing values from HTTP responses, and making assertions. +It can chain requests, capture values and evaluate queries on headers and body response. Hurl is very versatile, it can be used for fetching data and testing HTTP sessions: HTML content, REST / SOAP / GraphQL APIs, or any other XML / JSON based APIs. ```shell $ hurl session.hurl @@ -69,11 +69,11 @@ GET http:/example.org/endpoint2 A value from an HTTP response can be-reused for successive HTTP requests. -A typical example occurs with csrf tokens. +A typical example occurs with CSRF tokens. ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 # Capture the CSRF token value from html body. [Captures] csrf_token: xpath "normalize-space(//meta[@name='_csrf_token']/@content)" @@ -87,28 +87,28 @@ More information on captures can be found here [https://hurl.dev/docs/capturing- ### Asserts -The HTTP response defined in the Hurl session are used to make asserts. +The HTTP response defined in the Hurl file are used to make asserts. Responses are optional. -At the minimum, the response includes the asserts on the HTTP version and status code. +At the minimum, response includes assert on the HTTP status code. ```hurl -GET http:/google.com -HTTP/1.1 301 +GET http:/example.org +HTTP 301 ``` It can also include asserts on the response headers ```hurl -GET http:/google.com -HTTP/1.1 301 -Location: http://www.google.com +GET http:/example.org +HTTP 301 +Location: http://www.example.org ``` Explicit asserts can be included by combining a query and a predicate ```hurl -GET http:/google.com -HTTP/1.1 301 +GET http:/example.org +HTTP 301 [Asserts] xpath "string(//title)" == "301 Moved" ``` @@ -132,22 +132,28 @@ $ hurl --location foo.hurl will follow redirection for each entry in `foo.hurl`. You can also define an option only for a particular entry with an `[Options]` section. For instance, this Hurl file: ```hurl -GET https://google.com -HTTP/* 301 +GET https://example.org +HTTP 301 -GET https://google.com +GET https://example.org [Options] location: true -HTTP/* 200 +HTTP 200 ``` will follow a redirection only for the second entry. -### --cacert {#cacert} +### --cacert {#cacert} Specifies the certificate file for peer verification. The file may contain multiple CA certificates and must be in PEM format. Normally Hurl is built to use a default file for this, so this option is typically used to alter that default file. +### -E, --cert {#cert} + +Client certificate file and password. + +See also [`--key`](#key). + ### --color {#color} Colorize Output. @@ -160,7 +166,13 @@ Request a compressed response using one of the algorithms br, gzip, deflate and Maximum time in seconds that you allow Hurl's connection to take. -See also [`-m, --max-time`](#max-time) option. +See also [`-m, --max-time`](#max-time). + +### --connect-to {#connect-to} + +For a request to the given HOST1:PORT1 pair, connect to HOST2:PORT2 instead. This option can be used several times in a command line. + +See also [`--resolve`](#resolve). ### -b, --cookie {#cookie} @@ -221,6 +233,10 @@ This is similar to a break point, You can then continue (Press C) or quit (Press Output each hurl file result to JSON. The format is very closed to HAR format. +### --key {#key} + +Private key file name. + ### --max-redirs {#max-redirs} Set maximum number of redirection-followings allowed @@ -230,7 +246,7 @@ By default, the limit is set to 50 redirections. Set this option to -1 to make i Maximum time in seconds that you allow a request/response to take. This is the standard timeout. -See also [`--connect-timeout`](#connect-timeout) option. +See also [`--connect-timeout`](#connect-timeout). ### --no-color {#no-color} @@ -249,7 +265,7 @@ Override value from Environment variable no_proxy. Write output to FILE instead of stdout. -### -x, --proxy [protocol://]host[:port] {#proxy} +### -x, --proxy <[PROTOCOL://]HOST[:PORT]> {#proxy} Use the specified proxy. @@ -265,6 +281,10 @@ Generate HTML report in DIR. If the HTML report already exists, it will be updated with the new test results. +### --resolve {#resolve} + +Provide a custom address for a specific host and port pair. Using this, you can make the Hurl requests(s) use a specified address and prevent the otherwise normally resolved address to be used. Consider it a sort of /etc/hosts alternative provided on the command line. + ### --retry {#retry} Retry requests if any error occurs (asserts, captures, runtimes etc...). @@ -277,6 +297,10 @@ Duration in milliseconds between each retry. Default is 1000 ms. Maximum number of retries. Set this option to -1 to make it unlimited. Default is 10. +### --ssl-no-revoke {#ssl-no-revoke} + +(Windows) This option tells Hurl to disable certificate revocation checks. WARNING: this option loosens the SSL security, and by using this flag you ask for exactly that. + ### --test {#test} Activate test mode: with this, the HTTP response is not outputted anymore, progress is reported for each Hurl file tested, and a text summary is displayed when all files have been run. diff --git a/docs/manual/hurlfmt.1 b/docs/manual/hurlfmt.1 index db5a9b7e2..79f854322 100644 --- a/docs/manual/hurlfmt.1 +++ b/docs/manual/hurlfmt.1 @@ -1,4 +1,4 @@ -.TH hurl 1 "07 Nov 2022" "hurl 2.0.0-SNAPSHOT" " Hurl Manual" +.TH hurl 1 "24 Jan 2023" "hurl 2.0.0-SNAPSHOT" " Hurl Manual" .SH NAME hurlfmt - format Hurl files diff --git a/docs/request.md b/docs/request.md index 18227df91..d48c55037 100644 --- a/docs/request.md +++ b/docs/request.md @@ -4,8 +4,8 @@ Request describes an HTTP request: a mandatory [method] and [URL], followed by optional [headers]. -Then, [query parameters], [form parameters], [multipart form data], [cookies] and -[basic authentication] can be used to configure the HTTP request. +Then, [query parameters], [form parameters], [multipart form data], [cookies], [basic authentication] and [options] +can be used to configure the HTTP request. Finally, an optional [body] can be used to configure the HTTP request body. @@ -116,7 +116,7 @@ order: newest ``` The last optional part of a request configuration is the request [body]. Request body must be the last parameter of a request -(after [headers] and request sections). Like headers, [body] have no explicit marker: +(after [headers] and request sections). Like headers, body have no explicit marker: ```hurl POST https://example.org/api/dogs?id=4567 @@ -131,7 +131,7 @@ User-Agent: My User Agent ### Method Mandatory HTTP request method, one of `GET`, `HEAD`, `POST`, `PUT`, `DELETE`, `CONNECT`, `OPTIONS`, -`TRACE`, `PATCH`. +`TRACE`, `PATCH`, `LINK`, `UNLINK`, `PURGE`, `LOCK`, `UNLOCK`, `PROPFIND`, `VIEW`. ### URL @@ -173,7 +173,7 @@ Connection: keep-alive > Headers directly follow URL, without any section name, contrary to query parameters, form parameters > or cookies -Note that header usually don't start with double quotes. If the header value starts with double quotes, the double +Note that a header usually doesn't start with double quotes. If a header value starts with double quotes, double quotes will be part of the header value: ```hurl @@ -223,7 +223,7 @@ number: 33611223344 ``` Form parameters section can be seen as syntactic sugar over body section (values in form parameters section -are not URL encoded.). A [multiline string body] could be used instead of a forms parameters section. +are not URL encoded.). A [oneline string body] could be used instead of a forms parameters section. ~~~hurl # Run a POST request with form parameters section: @@ -235,9 +235,7 @@ key1: value1 # Run the same POST request with a body section: POST https://example.org/test Content-Type: application/x-www-form-urlencoded -``` -name=John%20Doe&key1=value1 -``` +`name=John%20Doe&key1=value1` ~~~ When both [body section] and form parameters section are present, only the body section is taken into account. @@ -342,8 +340,9 @@ Optional HTTP body request. If the body of the request is a [JSON] string or a [XML] string, the value can be directly inserted without any modification. For a text based body that is not JSON nor XML, -one can use multiline string that starts with ``` and ends -with ```. +one can use [multiline string body] that starts with ``` and ends +with ```. Multiline string body support "language hint" and can be used +to create [GraphQL queries]. For a precise byte control of the request body, [Base64] encoded string, [hexadecimal string] or [included file] can be used to describe exactly the body byte content. @@ -354,7 +353,7 @@ The body section must be the last section of the request configuration. #### JSON body -JSON body is used to set a literal JSON as the request body. +JSON request body is used to set a literal JSON as the request body. ```hurl # Create a new doggy thing with JSON body: @@ -369,11 +368,43 @@ POST https://example.org/api/dogs } ``` -When using JSON body, the content type `application/json` is automatically set. +JSON request body can be [templatized with variables]: + +```hurl +# Create a new catty thing with JSON body: +POST https://example.org/api/cats +{ + "id": 42, + "lives": {{ lives_count }}, + "name": "{{ name }}" +} +``` + + +When using JSON request body, the content type `application/json` is automatically set. + +JSON request body can be seen as syntactic sugar of [multiline string body] with `json` identifier: + +~~~hurl +# Create a new doggy thing with JSON body: +POST https://example.org/api/dogs +```json +{ + "id": 0, + "name": "Frieda", + "picture": "images/scottish-terrier.jpeg", + "age": 3, + "breed": "Scottish Terrier", + "location": "Lisco, Alabama" +} +``` +~~~ + + #### XML body -XML body is used to set a literal XML as the request body. +XML request body is used to set a literal XML as the request body. ~~~hurl # Create a new soapy thing XML body: @@ -392,9 +423,88 @@ SOAPAction: "http://www.w3.org/2003/05/soap-envelope" ~~~ +XML request body can be seen as syntactic sugar of [multiline string body] with `xml` identifier: + +~~~hurl +# Create a new soapy thing XML body: +POST https://example.org/InStock +Content-Type: application/soap+xml; charset=utf-8 +Content-Length: 299 +SOAPAction: "http://www.w3.org/2003/05/soap-envelope" +```xml + + + + + + GOOG + + + +``` +~~~ + +> Contrary to JSON body, the succint syntax of XML body can not use variables. If you need to use variables in your +> XML body, use a simple [multiline string body] with variables. + +#### GraphQL query + +GraphQL query uses [multiline string body] with `graphql` identifier: + + +~~~hurl +POST https://example.org/starwars/graphql +```graphql +{ + human(id: "1000") { + name + height(unit: FOOT) + } +} +``` +~~~ + +GraphQL query body can use [GraphQL variables]: + +~~~hurl +POST https://example.org/starwars/graphql +```graphql +query Hero($episode: Episode, $withFriends: Boolean!) { + hero(episode: $episode) { + name + friends @include(if: $withFriends) { + name + } + } +} + +variables { + "episode": "JEDI", + "withFriends": false +} +``` +~~~ + +GraphQL query, as every multiline string body, can use Hurl variables. + +~~~hurl +POST https://example.org/starwars/graphql +```graphql +{ + human(id: "{{human_id}}") { + name + height(unit: FOOT) + } +} +``` +~~~ + +> Hurl variables and GraphQL variables can be mixed in the same body. + + #### Multiline string body -For text based body that are not JSON nor XML, one can used multiline string, started and ending with +For text based body that are not JSON nor XML, one can use multiline string, started and ending with ```. ~~~hurl @@ -420,28 +530,28 @@ line3 is evaluated as "line1\nline2\nline3\n". +Multiline string body can use language identifier, like `json`, `xml` or `graphql`. Depending on the language identifier, +an additional 'Content-Type' request header is sent, and the real body (bytes sent over the wire) can be different from the +raw multiline text. -To construct an empty string: - -~~~ -``` +~~~hurl +POST https://example.org/api/dogs +```json +{ + "id": 0, + "name": "Frieda", +} ``` ~~~ -or +#### Oneline string body +For text based body that do not contain newlines, one can use oneline string, started and ending with `. + +~~~hurl +POST https://example.org/helloworld +`Hello world!` ~~~ -`````` -~~~ - - -Finally, multiline string can be used without any newline: - -~~~ -```line``` -~~~ - -is evaluated as "line". #### Base64 body @@ -504,10 +614,15 @@ compressed: true # request a compressed response insecure: true # allows insecure SSL connections and transfers location: true # follow redirection for this request max-redirs: 10 # maximum number of redirections +variable: country=Italy # define variable country +variable: planet=Earth # define variable planet verbose: true # allow verbose output very-verbose: true # allow more verbose output ``` +> Variable defined in an `[Options]` section are defined also for the next entries. This is +> the exception, all other options are defined only for the current request. + [method]: #method [URL]: #url [headers]: #headers @@ -521,6 +636,7 @@ very-verbose: true # allow more verbose output [query parameters section]: #query-parameters [HTML form]: https://developer.mozilla.org/en-US/docs/Learn/Forms [multiline string body]: #multiline-string-body +[oneline string body]: #oneline-string-body [body section]: #body [multipart/form-data on MDN]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST [`--file-root` option]: /docs/manual.md#file-root @@ -536,4 +652,8 @@ very-verbose: true # allow more verbose output [`--location`]: /docs/manual.md#location [`--verbose`]: /docs/manual.md#verbose [`--insecure`]: /docs/manual.md#insecure +[templatized with variables]: /docs/templates.md#templating-body +[GraphQL queries]: #graphql-query +[GraphQL variables]: https://graphql.org/learn/queries/#variables +[options]: #options diff --git a/docs/response.md b/docs/response.md index 7ce6fbd56..b520126f0 100644 --- a/docs/response.md +++ b/docs/response.md @@ -15,7 +15,7 @@ in the following entries. ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT [Asserts] xpath "normalize-space(//head/title)" startsWith "Welcome" @@ -28,7 +28,7 @@ xpath "//li" count == 18
- HTTP/1.1 * + HTTP *
content-length: 206
accept-ranges: bytes
user-agent: Test diff --git a/docs/running-tests.md b/docs/running-tests.md index a78ab358b..e81bf2f68 100644 --- a/docs/running-tests.md +++ b/docs/running-tests.md @@ -63,17 +63,25 @@ You can use [`--glob` option] to test files that match a given pattern: $ hurl --test --glob "test/integration/**/*.hurl" ``` -## Generating an HTML Report +## Generating Report -Hurl can also generate an HTML report by using the [`--report-html HTML_DIR`] option. +### HTML Report + +Hurl can generate an HTML report by using the [`--report-html HTML_DIR`] option. If the HTML report already exists, the test results will be appended to it. -Hurl HTML Report +Hurl HTML Report The input Hurl files (HTML version) are also included and are easily accessed from the main page. -Hurl HTML file +Hurl HTML file + +### JUnit Report + +A JUnit report can be produced by using the [`--report-junit FILE`] option. + +If the JUnit file already exists, it will be updated with the new test results. ## Use Variables in Tests @@ -89,6 +97,7 @@ You will find a detailed description in the [Injecting Variables] section of the [`--output /dev/null`]: /docs/manual.md#output [`--test`]: /docs/manual.md#test [`--report-html HTML_DIR`]: /docs/manual.md#report-html +[`--report-junit FILE`]: /docs/manual.md#report-junit [`--test` option]: /docs/manual.md#test [`--glob` option]: /docs/manual.md#glob [`--variable` option]: /docs/manual.md#variable diff --git a/docs/samples.md b/docs/samples.md index b0dc9f433..359199fd8 100644 --- a/docs/samples.md +++ b/docs/samples.md @@ -137,15 +137,11 @@ file,data.json; [Doc](/docs/request.md#file-body) -### Templating a JSON / XML Body +### Templating a JSON Body -Using templates with [JSON body] or [XML body] is not currently supported in Hurl. -Besides, you can use templates in [multiline string body] with variables to send a JSON or XML body: - -~~~hurl +```hurl PUT https://example.org/api/hits Content-Type: application/json -``` { "key0": "{{a_string}}", "key1": {{a_bool}}, @@ -153,7 +149,6 @@ Content-Type: application/json "key3": {{a_number}} } ``` -~~~ Variables can be initialized via command line: @@ -176,8 +171,67 @@ Resulting in a PUT request with the following JSON body: } ``` +[Doc](/docs/templates.md) + +### Templating a XML Body + +Using templates with [XML body] is not currently supported in Hurl. You can use templates in +[XML multiline string body] with variables to send a variable XML body: + +~~~hurl +POST https://example.org/echo/post/xml +```xml + + + {{login}} + {{password}} + +``` +~~~ + [Doc](/docs/request.md#multiline-string-body) +### Using GraphQL Query + +A simple GraphQL query: + +~~~hurl +POST https://example.org/starwars/graphql +```graphql +{ + human(id: "1000") { + name + height(unit: FOOT) + } +} +``` +~~~ + +A GraphQL query with variables: + +~~~hurl +POST https://example.org/starwars/graphql +```graphql +query Hero($episode: Episode, $withFriends: Boolean!) { + hero(episode: $episode) { + name + friends @include(if: $withFriends) { + name + } + } +} + +variables { + "episode": "JEDI", + "withFriends": false +} +``` +~~~ + +GraphQL queries can also use [Hurl templates]. + +[Doc](/docs/request.md#graphql-body) + ## Testing Response ### Testing Response Headers @@ -187,7 +241,7 @@ Use implicit response asserts to test header values: ```hurl GET https://example.org/index.html -HTTP/1.0 200 +HTTP 200 Set-Cookie: theme=light Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT ``` @@ -200,7 +254,7 @@ Or use explicit response asserts with [predicates]: ```hurl GET https://example.org -HTTP/1.1 302 +HTTP 302 [Asserts] header "Location" contains "www.example.net" ``` @@ -216,7 +270,7 @@ Asserting JSON body response (node values, collection count etc...) with [JSONPa GET https://example.org/order screencapability: low -HTTP/1.1 200 +HTTP 200 [Asserts] jsonpath "$.validated" == true jsonpath "$.userInfo.firstName" == "Franck" @@ -236,7 +290,7 @@ Testing status code: ```hurl GET https://example.org/order/435 -HTTP/1.1 200 +HTTP 200 ``` [Doc](/docs/asserting-response.md#version-status) @@ -245,7 +299,7 @@ HTTP/1.1 200 GET https://example.org/order/435 # Testing status code is in a 200-300 range -HTTP/1.1 * +HTTP * [Asserts] status >= 200 status < 300 @@ -259,7 +313,7 @@ status < 300 ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 Content-Type: text/html; charset=UTF-8 [Asserts] @@ -278,7 +332,7 @@ xpath "string(//div[1])" matches /Hello.*/ ```hurl GET http://myserver.com/home -HTTP/1.0 200 +HTTP 200 [Asserts] cookie "JSESSIONID" == "8400BAFE2F66443613DC38AE3D9D6239" cookie "JSESSIONID[Value]" == "8400BAFE2F66443613DC38AE3D9D6239" @@ -308,6 +362,17 @@ sha256 == hex,039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81; ## Others +### HTTP Version + +Testing HTTP version (1.0, 1.1 or 2): + +```hurl +GET https://example.org/order/435 +HTTP/2 200 +``` + +[Doc](/docs/asserting-response.md#version-status) + ### Polling and Retry Retry request on any errors (asserts, captures, status code, runtime etc...): @@ -316,7 +381,7 @@ Retry request on any errors (asserts, captures, status code, runtime etc...): # Create a new job POST https://api.example.org/jobs -HTTP/* 201 +HTTP 201 [Captures] job_id: jsonpath "$.id" [Asserts] @@ -328,7 +393,7 @@ GET https://api.example.org/jobs/{{job_id}} [Options] retry: true -HTTP/* 200 +HTTP 200 [Asserts] jsonpath "$.state" == "COMPLETED" ``` @@ -342,7 +407,7 @@ jsonpath "$.state" == "COMPLETED" ```hurl GET https://sample.org/helloworld -HTTP/* * +HTTP * [Asserts] duration < 1000 # Check that response time is less than one second ``` @@ -365,7 +430,7 @@ SOAPAction: "http://www.w3.org/2003/05/soap-envelope" -HTTP/1.1 200 +HTTP 200 ``` [Doc](/docs/request.md#xml-body) @@ -375,14 +440,14 @@ HTTP/1.1 200 ```hurl GET https://example.org -HTTP/* 200 +HTTP 200 [Captures] csrf_token: xpath "string(//meta[@name='_csrf_token']/@content)" POST https://example.org/login?user=toto&password=1234 X-CSRF-TOKEN: {{csrf_token}} -HTTP/* 302 +HTTP 302 ``` [Doc](/docs/capturing-response.md#xpath-capture) @@ -392,7 +457,7 @@ HTTP/* 302 ```hurl GET https://example.org/data.bin -HTTP/* 200 +HTTP 200 [Asserts] bytes startsWith hex,efbbbf; ``` @@ -402,7 +467,7 @@ bytes startsWith hex,efbbbf; [JSON body]: /docs/request.md#json-body [XML body]: /docs/request.md#xml-body -[multiline string body]: /docs/request.md#multiline-string-body +[XML multiline string body]: /docs/request.md#multiline-string-body [predicates]: /docs/asserting-response.md#predicates [JSONPath]: https://goessner.net/articles/JsonPath/ [Basic authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#basic_authentication_scheme @@ -413,3 +478,4 @@ bytes startsWith hex,efbbbf; [curl]: https://curl.se [entry]: /docs/entry.md [`--test` option]: /docs/manual.md#test +[Hurl templates]: /docs/templates.md diff --git a/docs/templates.md b/docs/templates.md index 0e7bdc76c..0b2fab7da 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -8,7 +8,7 @@ value from an HTTP response in the next entries, you can capture this value in a ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 [Captures] csrf_token: xpath "string(//meta[@name='_csrf_token']/@content)" @@ -16,7 +16,7 @@ csrf_token: xpath "string(//meta[@name='_csrf_token']/@content)" POST https://acmecorp.net/login?user=toto&password=1234 X-CSRF-TOKEN: {{csrf_token}} -HTTP/1.1 302 +HTTP 302 ``` In this example, we capture the value of the [CSRF token] from the body of the first response, and inject it @@ -24,12 +24,15 @@ as a header in the next POST request. ```hurl GET https://example.org/api/index -HTTP/* 200 + +HTTP 200 [Captures] index: body + GET https://example.org/api/status -HTTP/* 200 + +HTTP 200 [Asserts] jsonpath "$.errors[{{index}}].id" == "error" ``` @@ -45,7 +48,8 @@ templates can be rendered differently. Let's say we have captured an integer val ```hurl GET https://sample/counter -HTTP/* 200 + +HTTP 200 [Captures] count: jsonpath "$.results[0]" ``` @@ -54,7 +58,8 @@ The following entry: ```hurl GET https://sample/counter/{{count}} -HTTP/* 200 + +HTTP 200 [Asserts] jsonpath "$.id" == "{{count}}" ``` @@ -62,8 +67,9 @@ jsonpath "$.id" == "{{count}}" will be rendered at runtime to: ```hurl -GET https://sample/counter/458 -HTTP/* 200 +GET https://sample/counter/458 + +HTTP 200 [Asserts] jsonpath "$.id" == "458" ``` @@ -74,7 +80,8 @@ On the other hand, the following assert: ```hurl GET https://sample/counter/{{count}} -HTTP/* 200 + +HTTP 200 [Asserts] jsonpath "$.index" == {{count}} ``` @@ -83,7 +90,8 @@ will be rendered at runtime to: ```hurl GET https://sample/counter/458 -HTTP/* 200 + +HTTP 200 [Asserts] jsonpath "$.index" == 458 ``` @@ -105,15 +113,16 @@ Variables can also be injected in a Hurl file: - by using [`--variable` option] - by using [`--variables-file` option] - by defining environment variables, for instance `HURL_foo=bar` +- by defining variables in an [`[Options]` section][options] Lets' see how to inject variables, given this `test.hurl`: ```hurl GET https://{{host}}/{{id}}/status -HTTP/1.1 304 +HTTP 304 GET https://{{host}}/health -HTTP/1.1 200 +HTTP 200 ``` ### `variable` option @@ -142,14 +151,28 @@ id=1234 ### Environment variable -Finally, we can use environment variables in the form of `HURL_name=value`: +We can use environment variables in the form of `HURL_name=value`: ```shell $ export HURL_host=example.net $ export HURL_id=1234 $ hurl test.hurl -``` +``` +### Options sections + +We can define variables in `[Options]` section. Variables defined in a section are available for the next requests. + +```hurl +GET https://{{host}}/{{id}}/status +[Options] +variable: host=example.net +variable: id=1234 +HTTP 304 + +GET https://{{host}}/health +HTTP 200 +``` ## Templating Body @@ -194,3 +217,4 @@ Resulting in a PUT request with the following JSON body: [JSON body]: /docs/request.md#json-body [XML body]: /docs/request.md#xml-body [multiline string body]: /docs/request.md#multiline-string-body +[options]: /docs/request.md#options diff --git a/docs/tutorial/adding-asserts.md b/docs/tutorial/adding-asserts.md index c6bc7bb9c..809925730 100644 --- a/docs/tutorial/adding-asserts.md +++ b/docs/tutorial/adding-asserts.md @@ -6,19 +6,13 @@ Our basic Hurl file is now: # Our first Hurl file, just checking # that our server is up and running. GET http://localhost:8080 - -HTTP/1.1 200 +HTTP 200 ``` Currently, we're just checking that our home page is responding with a `200 OK` HTTP status code. But we also want to check the _content_ of our home page, to ensure that everything is ok. To check the response of an HTTP request with Hurl, we have to _describe_ tests that the response content must pass. -> We're already implicitly asserting the response with the line\ -> `HTTP/1.1 200`\ -> On one hand, we are checking that the HTTP protocol version is 1.1; on the other hand, we are checking -> that the HTTP status response code is 200. - To do so, we're going to use [asserts]. As our endpoint is serving HTML content, it makes sense to use [XPath asserts]. @@ -48,7 +42,7 @@ going to use the [XPath expression] `string(//head/title)`. # that our server is up and running. GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quiz!" ``` @@ -75,7 +69,7 @@ There is no error so everything is good! # that our server is up and running. GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quaz!" ``` @@ -123,7 +117,7 @@ with `count`: # Checking our home page: GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quiz!" xpath "//button" count == 2 @@ -135,7 +129,7 @@ xpath "//button" count == 2 # Checking our home page: GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quiz!" xpath "//button" count == 2 @@ -172,7 +166,7 @@ As our endpoint is serving UTF-8 encoded HTML content, we can check the value of # Checking our home page: GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quiz!" xpath "//button" count == 2 @@ -197,7 +191,7 @@ while the explicit one allows you to use other [predicates] (like `contains`, `s # Checking our home page: GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 # Implicitly testing response headers: Content-Type: text/html;charset=UTF-8 [Asserts] @@ -223,7 +217,7 @@ So to test it, we can modify our Hurl file with another header assert. # Checking our home page: GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quiz!" xpath "//button" count == 2 @@ -250,7 +244,7 @@ So to test that our server is responding with a `HttpOnly` session cookie, we ca # Checking our home page: GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quiz!" xpath "//button" count == 2 diff --git a/docs/tutorial/captures.md b/docs/tutorial/captures.md index 15277574d..09f527ecd 100644 --- a/docs/tutorial/captures.md +++ b/docs/tutorial/captures.md @@ -55,7 +55,7 @@ question2: 4edc1fdb question3: 37b9eff3 question4: 0fec576c -HTTP/1.1 302 +HTTP 302 ``` > When sending form data with a Form parameters section, you don't need to set the @@ -67,10 +67,10 @@ HTTP/1.1 302 $ hurl --test create-quiz.hurl create-quiz.hurl: Running [1/1] error: Assert status code - --> create-quiz.hurl:10:10 + --> create-quiz.hurl:6:10 | -10 | HTTP/1.1 302 - | ^^^ actual value is <403> +10 | HTTP 302 + | ^^^ actual value is <403> | create-quiz.hurl: Failure (1 request(s) in 5 ms) @@ -122,7 +122,7 @@ So, let's go! # the CSRF token (see https://en.wikipedia.org/wiki/Cross-site_request_forgery) GET http://localhost:8080/new-quiz -HTTP/1.1 200 +HTTP 200 [Captures] csrf_token: xpath "string(//input[@name='_csrf']/@value)" ``` @@ -146,10 +146,11 @@ Now that we have captured the CSRF token value, we can inject it in the POST req # the CSRF token (see https://en.wikipedia.org/wiki/Cross-site_request_forgery): GET http://localhost:8080/new-quiz -HTTP/1.1 200 +HTTP 200 [Captures] csrf_token: xpath "string(//input[@name='_csrf']/@value)" + # Create a new quiz, using the captured CSRF token: POST http://localhost:8080/new-quiz [FormParams] @@ -160,8 +161,7 @@ question2: 4edc1fdb question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} - -HTTP/1.1 302 +HTTP 302 ``` 3. Run `create-quiz.hurl` and verify everything is ok: @@ -207,7 +207,7 @@ question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} -HTTP/1.1 302 +HTTP 302 [Captures] detail_url: header "Location" ``` @@ -232,7 +232,7 @@ question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} -HTTP/1.1 302 +HTTP 302 [Captures] detail_url: header "Location" [Asserts] @@ -250,7 +250,7 @@ header "Location" matches "/quiz/detail/[a-f0-9]{8}" # Open the newly created quiz detail page: GET {{detail_url}} -HTTP/1.1 200 +HTTP 200 ``` 4. Run `create-quiz.hurl` and verify everything is ok: @@ -267,7 +267,7 @@ Duration: 46 ms ``` -> You can force Hurl to follow redirection by using [`-L / --location` option]. +> You can force Hurl to follow redirection by using [`-L / --location` option] or using an [`[Options]` section][options]. > In this case, asserts and captures will be run against the last redirection step. @@ -280,10 +280,11 @@ So, our test file `create-quiz.hurl` is now: # the CSRF token (see https://en.wikipedia.org/wiki/Cross-site_request_forgery) GET http://localhost:8080/new-quiz -HTTP/1.1 200 +HTTP 200 [Captures] csrf_token: xpath "string(//input[@name='_csrf']/@value)" + # Create a new quiz, using the captured CSRF token. POST http://localhost:8080/new-quiz [FormParams] @@ -295,15 +296,16 @@ question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} -HTTP/1.1 302 +HTTP 302 [Captures] detail_url: header "Location" [Asserts] header "Location" matches "/quiz/detail/[a-f0-9]{8}" + # Open the newly created quiz detail page: GET {{detail_url}} -HTTP/1.1 200 +HTTP 200 ``` We have seen how to [capture response data] in a variable and use it in others request. @@ -326,4 +328,5 @@ of a redirection. [header capture]: /docs/capturing-response.md#header-capture [`Location`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location [`-L / --location` option]: /docs/manual.md#location -[capture response data]: /docs/capturing-response.md \ No newline at end of file +[capture response data]: /docs/capturing-response.md +[options]: /docs/request.md#options \ No newline at end of file diff --git a/docs/tutorial/chaining-requests.md b/docs/tutorial/chaining-requests.md index 664cb0831..196683980 100644 --- a/docs/tutorial/chaining-requests.md +++ b/docs/tutorial/chaining-requests.md @@ -8,7 +8,7 @@ Our basic Hurl file is for the moment: # Checking our home page: GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quiz!" xpath "//button" count == 2 @@ -33,7 +33,7 @@ request following our first request. Let's say we want to test that we have a [4 # Checking our home page: GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quiz!" xpath "//button" count == 2 @@ -48,7 +48,7 @@ cookie "JSESSIONID[HttpOnly]" exists # Check that we have a 404 response for broken links: GET http://localhost:8080/not-found -HTTP/1.1 404 +HTTP 404 [Asserts] header "Content-Type" == "text/html;charset=UTF-8" xpath "string(//h1)" == "Error 404, Page not Found!" @@ -126,7 +126,7 @@ followed by a predicate. A [JsonPath query] is a simple expression to inspect a # Check our health API: GET http://localhost:8080/api/health -HTTP/1.1 200 +HTTP 200 [Asserts] header "Content-Type" == "application/json" jsonpath "$.status" == "RUNNING" @@ -155,7 +155,7 @@ through the API endpoint. # Check question API: GET http://localhost:8080/api/questions?offset=0&size=20&sort=oldest -HTTP/1.1 200 +HTTP 200 [Asserts] header "Content-Type" == "application/json" jsonpath "$" count == 20 @@ -194,7 +194,7 @@ offset: 0 size: 20 sort: oldest -HTTP/1.1 200 +HTTP 200 [Asserts] header "Content-Type" == "application/json" jsonpath "$" count == 20 @@ -208,7 +208,7 @@ Finally, our basic Hurl file, with four requests, looks like: # Checking our home page: GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "string(//head/title)" == "Welcome to Quiz!" xpath "//button" count == 2 @@ -220,24 +220,27 @@ header "Content-Type" == "text/html;charset=UTF-8" cookie "JSESSIONID" exists cookie "JSESSIONID[HttpOnly]" exists + # Check that we have a 404 response for broken links: GET http://localhost:8080/not-found -HTTP/1.1 404 +HTTP 404 [Asserts] header "Content-Type" == "text/html;charset=UTF-8" xpath "string(//h1)" == "Error 404, Page not Found!" + # Check our health API: GET http://localhost:8080/api/health -HTTP/1.1 200 +HTTP 200 [Asserts] header "Content-Type" == "application/json" jsonpath "$.status" == "RUNNING" jsonpath "$.healthy" == true jsonpath "$.operationId" exists + # Check question API: GET http://localhost:8080/api/questions [QueryStringParams] @@ -245,7 +248,7 @@ offset: 0 size: 20 sort: oldest -HTTP/1.1 200 +HTTP 200 [Asserts] header "Content-Type" == "application/json" jsonpath "$" count == 20 diff --git a/docs/tutorial/ci-cd-integration.md b/docs/tutorial/ci-cd-integration.md index 891c0630c..034a3d18d 100644 --- a/docs/tutorial/ci-cd-integration.md +++ b/docs/tutorial/ci-cd-integration.md @@ -77,7 +77,7 @@ really ready to accept incoming HTTP requests. To do so, we can test our health API. With a function `wait_for_url`, we use Hurl to check a given URL to return a `200 OK`. We loop on this function -until the check succeeds. Once the test has succeeded, we stop the container. +until the check succeeds with [`--retry`] Hurl option. Once the test has succeeded, we stop the container. 5. Modify `bin/integration.sh` to wait for the application to be ready: @@ -86,24 +86,13 @@ until the check succeeds. Once the test has succeeded, we stop the container. set -eu wait_for_url () { - echo "Testing $1" - max_in_s=$2 - delay_in_s=1 - total_in_s=0 - while [ $total_in_s -le "$max_in_s" ] - do - echo "Wait ${total_in_s}s" - if (echo -e "GET $1\nHTTP/* 200" | hurl > /dev/null 2>&1;) then - return 0 - fi - total_in_s=$(( total_in_s + delay_in_s)) - sleep $delay_in_s - done - return 1 + echo "Testing $1..." + echo -e "GET $1\nHTTP 200" | hurl --retry --retry-max-count "$2" > /dev/null; + return 0 } echo "Starting Quiz container" -docker run --name quiz --rm --detach --publish 8080:8080 ghcr.io/jcamiel/quiz:latest +docker run --rm --detach --publish 8080:8080 --name quiz ghcr.io/jcamiel/quiz:latest echo "Starting Quiz instance to be ready" wait_for_url 'http://localhost:8080' 60 @@ -275,3 +264,4 @@ Now, we can add more Hurl tests and start developing new features with confidenc [GitLab CI/CD here]: https://about.gitlab.com/blog/2022/12/14/how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd/ [GitLab CI/CD]: https://about.gitlab.com/why-gitlab/ [this detailed tutorial]: https://about.gitlab.com/blog/2022/12/14/how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd/ +[`--retry`]: /docs/manual.md#retry \ No newline at end of file diff --git a/docs/tutorial/debug-tips.md b/docs/tutorial/debug-tips.md index d0822f210..dff1a0dba 100644 --- a/docs/tutorial/debug-tips.md +++ b/docs/tutorial/debug-tips.md @@ -239,7 +239,7 @@ offset: 0 size: 20 sort: oldest -HTTP/1.1 200 +HTTP 200 # ... ``` @@ -357,18 +357,19 @@ In this mode, headers of the last entry are displayed: ```shell $ hurl -i basic.hurl -HTTP/1.1 200 -X-Content-Type-Options: nosniff -X-XSS-Protection: 1; mode=block -Cache-Control: no-cache, no-store, max-age=0, must-revalidate -Pragma: no-cache -Expires: 0 -X-Frame-Options: DENY -Content-Type: application/json -Transfer-Encoding: chunked -Date: Sun, 06 Jun 2021 15:11:31 GMT +HTTP/1.1 200 +Set-Cookie: JSESSIONID=76984131F0D0821C4A8D5CB3FC27CD3B; Path=/; HttpOnly +X-Content-Type-Options: nosniff +X-XSS-Protection: 1; mode=block +Cache-Control: no-cache, no-store, max-age=0, must-revalidate +Pragma: no-cache +Expires: 0 +X-Frame-Options: DENY +Content-Type: application/json +Transfer-Encoding: chunked +Date: Fri, 13 Jan 2023 12:49:47 GMT -[{"id":"c0d80047-4fbe-4d45-a005-91b5c7018b34","created":"1995-12-17T03:24:00Z".... +{"status":"RUNNING","reportedDate":"2023-01-13T13:49:47+01:00","healthy":true,"operationId":3183000623} ``` If you want to inspect any entry other than the last one, you can run your test to a @@ -376,40 +377,50 @@ given entry with the [`--to-entry` option], starting at index 1: ```shell $ hurl -i --to-entry 2 basic.hurl -HTTP/1.1 404 -Vary: Origin -Vary: Access-Control-Request-Method -Vary: Access-Control-Request-Headers -X-Content-Type-Options: nosniff -X-XSS-Protection: 1; mode=block -Cache-Control: no-cache, no-store, max-age=0, must-revalidate -Pragma: no-cache -Expires: 0 -X-Frame-Options: DENY -Content-Type: text/html;charset=UTF-8 -Content-Language: en-US -Transfer-Encoding: chunked -Date: Sun, 06 Jun 2021 15:14:20 GMT +HTTP/1.1 404 +Vary: Origin +Vary: Access-Control-Request-Method +Vary: Access-Control-Request-Headers +X-Content-Type-Options: nosniff +X-XSS-Protection: 1; mode=block +Cache-Control: no-cache, no-store, max-age=0, must-revalidate +Pragma: no-cache +Expires: 0 +X-Frame-Options: DENY +Content-Type: text/html;charset=UTF-8 +Content-Language: en-FR +Transfer-Encoding: chunked +Date: Fri, 13 Jan 2023 12:50:52 GMT - - + + + Error 404 - Quiz
- + Quiz logo
+
+

Error 404, Page not Found!

Quiz Home +
+ + ``` ## Using a Proxy diff --git a/docs/tutorial/security.md b/docs/tutorial/security.md index 440d0b507..5eb15c3f6 100644 --- a/docs/tutorial/security.md +++ b/docs/tutorial/security.md @@ -8,10 +8,11 @@ endpoint. Our test file `create-quiz.hurl` now looks like: # the CSRF token (see https://en.wikipedia.org/wiki/Cross-site_request_forgery) GET http://localhost:8080/new-quiz -HTTP/1.1 200 +HTTP 200 [Captures] csrf_token: xpath "string(//input[@name='_csrf']/@value)" + # Create a new quiz, using the captured CSRF token. POST http://localhost:8080/new-quiz [FormParams] @@ -23,15 +24,16 @@ question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} -HTTP/1.1 302 +HTTP 302 [Captures] detail_url: header "Location" [Asserts] header "Location" matches "/quiz/detail/[a-f0-9]{8}" + # Open the newly created quiz detail page: GET {{detail_url}} -HTTP/1.1 200 +HTTP 200 ``` So far, we have tested a "simple" form creation: every value of the form is valid and sanitized, but what if the user @@ -88,7 +90,7 @@ question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "//label[@for='name'][@class='invalid']" exists ``` @@ -123,7 +125,7 @@ question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "//label[@for='email'][@class='invalid']" exists ``` @@ -156,8 +158,7 @@ question1: dd894cca question2: 4edc1fdb question3: 37b9eff3 question4: 0fec576c - -HTTP/1.1 403 +HTTP 403 ``` > We're using [the exist predicate] to check labels in the DOM @@ -198,7 +199,7 @@ With Hurl, you will be able to check the content of the _real_ network data. # the CSRF token (see https://en.wikipedia.org/wiki/Cross-site_request_forgery) GET http://localhost:8080/new-quiz -HTTP/1.1 200 +HTTP 200 [Captures] csrf_token: xpath "string(//input[@name='_csrf']/@value)" [Asserts] @@ -230,12 +231,13 @@ So, our test file `create-quiz.hurl` is now: # the CSRF token (see https://en.wikipedia.org/wiki/Cross-site_request_forgery) GET http://localhost:8080/new-quiz -HTTP/1.1 200 +HTTP 200 [Captures] csrf_token: xpath "string(//input[@name='_csrf']/@value)" [Asserts] xpath "//comment" count == 0 # Check that we don't leak comments + # Create a new quiz, using the captured CSRF token. POST http://localhost:8080/new-quiz [FormParams] @@ -247,15 +249,16 @@ question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} -HTTP/1.1 302 +HTTP 302 [Captures] detail_url: header "Location" [Asserts] header "Location" matches "/quiz/detail/[a-f0-9]{8}" + # Open the newly created quiz detail page: GET {{detail_url}} -HTTP/1.1 200 +HTTP 200 # Test various server-side validations: @@ -270,10 +273,11 @@ question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "//label[@for='name'][@class='invalid']" exists + # Invalid email parameter: POST http://localhost:8080/new-quiz [FormParams] @@ -286,10 +290,11 @@ question3: 37b9eff3 question4: 0fec576c _csrf: {{csrf_token}} -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "//label[@for='email'][@class='invalid']" exists + # No CSRF token: POST http://localhost:8080/new-quiz [FormParams] @@ -300,8 +305,7 @@ question1: dd894cca question2: 4edc1fdb question3: 37b9eff3 question4: 0fec576c - -HTTP/1.1 403 +HTTP 403 ``` We have seen that Hurl can be used as a security tool, to check you server-side validation. diff --git a/docs/tutorial/your-first-hurl-file.md b/docs/tutorial/your-first-hurl-file.md index 9d99bc158..48a2d952b 100644 --- a/docs/tutorial/your-first-hurl-file.md +++ b/docs/tutorial/your-first-hurl-file.md @@ -127,7 +127,7 @@ the response and, at least, check that the HTTP response status code is [`200 OK ```hurl GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 ``` 4. Execute `basic.hurl`: @@ -173,7 +173,7 @@ Duration: 7 ms ```hurl GET http://localhost:8080 -HTTP/1.1 500 +HTTP 500 ``` 7. Save and execute it: @@ -204,7 +204,7 @@ Duration: 13 ms # Our first Hurl file, just checking # that our server is up and running. GET http://localhost:8080 -HTTP/1.1 200 +HTTP 200 ``` ## Recap diff --git a/packages/hurl/README.md b/packages/hurl/README.md index 59a50d458..f84c0d4fd 100644 --- a/packages/hurl/README.md +++ b/packages/hurl/README.md @@ -12,21 +12,24 @@ Hurl is a command line tool that runs HTTP requests defined in a simple plain text format. It can chain requests, capture values and evaluate queries on headers and body response. Hurl is very -versatile: it can be used for fetching data, testing HTTP sessions and testing XML / JSON APIs. +versatile: it can be used for both fetching data and testing HTTP sessions. + +Hurl makes it easy to work with HTML content, REST / SOAP / GraphQL APIs, or any other XML / JSON based APIs. ```hurl # Get home: GET https://example.org -HTTP/1.1 200 +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/1.1 302 +HTTP 302 ``` Chaining multiple requests is easy: @@ -55,7 +58,7 @@ POST https://example.org/api/tests "evaluate": true } -HTTP/1.1 200 +HTTP 200 [Asserts] header "X-Frame-Options" == "SAMEORIGIN" jsonpath "$.status" == "RUNNING" # Check the status code @@ -68,12 +71,27 @@ jsonpath "$.id" matches /\d{4}/ # Check the format of the id ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 [Asserts] xpath "normalize-space(//head/title)" == "Hello world!" ``` -and even SOAP APIs +GraphQL + +~~~hurl +POST https://example.org/graphql +```graphql +{ + human(id: "1000") { + name + height(unit: FOOT) + } +} +``` +HTTP 200 +~~~ + +and even SOAP APIs ```hurl POST https://example.org/InStock @@ -88,8 +106,7 @@ SOAPAction: "http://www.w3.org/2003/05/soap-envelope" - -HTTP/1.1 200 +HTTP 200 ``` Hurl can also be used to performance test HTTP endpoints: @@ -97,7 +114,7 @@ Hurl can also be used to performance test HTTP endpoints: ```hurl GET https://example.org/api/v1/pets -HTTP/1.0 200 +HTTP 200 [Asserts] duration < 1000 # Duration in ms ``` @@ -107,7 +124,7 @@ And response bytes ```hurl GET https://example.org/data.tar.gz -HTTP/1.0 200 +HTTP 200 [Asserts] sha256 == hex,039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81; ``` @@ -138,7 +155,7 @@ POST https://hurl.dev/api/feedback "name": "John Doe", "feedback": "Hurl is awesome !" } -HTTP/1.1 200 +HTTP 200 ``` # Resources @@ -164,7 +181,9 @@ Table of Contents * [Sending HTML Form Data](#sending-html-form-data) * [Sending Multipart Form Data](#sending-multipart-form-data) * [Posting a JSON Body](#posting-a-json-body) - * [Templating a JSON / XML Body](#templating-a-json--xml-body) + * [Templating a JSON Body](#templating-a-json-body) + * [Templating a XML Body](#templating-a-xml-body) + * [Using GraphQL Query](#using-graphql-query) * [Testing Response](#testing-response) * [Testing Response Headers](#testing-response-headers) * [Testing REST APIs](#testing-rest-apis) @@ -172,6 +191,7 @@ Table of Contents * [Testing Set-Cookie Attributes](#testing-set-cookie-attributes) * [Testing Bytes Content](#testing-bytes-content) * [Others](#others) + * [HTTP Version](#http-version) * [Polling and Retry](#polling-and-retry) * [Testing Endpoint Performance](#testing-endpoint-performance) * [Using SOAP APIs](#using-soap-apis) @@ -354,15 +374,11 @@ file,data.json; [Doc](https://hurl.dev/docs/request.html#file-body) -### Templating a JSON / XML Body +### Templating a JSON Body -Using templates with [JSON body] or [XML body] is not currently supported in Hurl. -Besides, you can use templates in [multiline string body] with variables to send a JSON or XML body: - -~~~hurl +```hurl PUT https://example.org/api/hits Content-Type: application/json -``` { "key0": "{{a_string}}", "key1": {{a_bool}}, @@ -370,7 +386,6 @@ Content-Type: application/json "key3": {{a_number}} } ``` -~~~ Variables can be initialized via command line: @@ -393,8 +408,67 @@ Resulting in a PUT request with the following JSON body: } ``` +[Doc](https://hurl.dev/docs/templates.html) + +### Templating a XML Body + +Using templates with [XML body] is not currently supported in Hurl. You can use templates in +[XML multiline string body] with variables to send a variable XML body: + +~~~hurl +POST https://example.org/echo/post/xml +```xml + + + {{login}} + {{password}} + +``` +~~~ + [Doc](https://hurl.dev/docs/request.html#multiline-string-body) +### Using GraphQL Query + +A simple GraphQL query: + +~~~hurl +POST https://example.org/starwars/graphql +```graphql +{ + human(id: "1000") { + name + height(unit: FOOT) + } +} +``` +~~~ + +A GraphQL query with variables: + +~~~hurl +POST https://example.org/starwars/graphql +```graphql +query Hero($episode: Episode, $withFriends: Boolean!) { + hero(episode: $episode) { + name + friends @include(if: $withFriends) { + name + } + } +} + +variables { + "episode": "JEDI", + "withFriends": false +} +``` +~~~ + +GraphQL queries can also use [Hurl templates]. + +[Doc](https://hurl.dev/docs/request.html#graphql-body) + ## Testing Response ### Testing Response Headers @@ -404,7 +478,7 @@ Use implicit response asserts to test header values: ```hurl GET https://example.org/index.html -HTTP/1.0 200 +HTTP 200 Set-Cookie: theme=light Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT ``` @@ -417,7 +491,7 @@ Or use explicit response asserts with [predicates]: ```hurl GET https://example.org -HTTP/1.1 302 +HTTP 302 [Asserts] header "Location" contains "www.example.net" ``` @@ -433,7 +507,7 @@ Asserting JSON body response (node values, collection count etc...) with [JSONPa GET https://example.org/order screencapability: low -HTTP/1.1 200 +HTTP 200 [Asserts] jsonpath "$.validated" == true jsonpath "$.userInfo.firstName" == "Franck" @@ -453,7 +527,7 @@ Testing status code: ```hurl GET https://example.org/order/435 -HTTP/1.1 200 +HTTP 200 ``` [Doc](https://hurl.dev/docs/asserting-response.html#version-status) @@ -462,7 +536,7 @@ HTTP/1.1 200 GET https://example.org/order/435 # Testing status code is in a 200-300 range -HTTP/1.1 * +HTTP * [Asserts] status >= 200 status < 300 @@ -476,7 +550,7 @@ status < 300 ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 Content-Type: text/html; charset=UTF-8 [Asserts] @@ -495,7 +569,7 @@ xpath "string(//div[1])" matches /Hello.*/ ```hurl GET http://myserver.com/home -HTTP/1.0 200 +HTTP 200 [Asserts] cookie "JSESSIONID" == "8400BAFE2F66443613DC38AE3D9D6239" cookie "JSESSIONID[Value]" == "8400BAFE2F66443613DC38AE3D9D6239" @@ -525,6 +599,17 @@ sha256 == hex,039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81; ## Others +### HTTP Version + +Testing HTTP version (1.0, 1.1 or 2): + +```hurl +GET https://example.org/order/435 +HTTP/2 200 +``` + +[Doc](https://hurl.dev/docs/asserting-response.html#version-status) + ### Polling and Retry Retry request on any errors (asserts, captures, status code, runtime etc...): @@ -533,7 +618,7 @@ Retry request on any errors (asserts, captures, status code, runtime etc...): # Create a new job POST https://api.example.org/jobs -HTTP/* 201 +HTTP 201 [Captures] job_id: jsonpath "$.id" [Asserts] @@ -545,7 +630,7 @@ GET https://api.example.org/jobs/{{job_id}} [Options] retry: true -HTTP/* 200 +HTTP 200 [Asserts] jsonpath "$.state" == "COMPLETED" ``` @@ -559,7 +644,7 @@ jsonpath "$.state" == "COMPLETED" ```hurl GET https://sample.org/helloworld -HTTP/* * +HTTP * [Asserts] duration < 1000 # Check that response time is less than one second ``` @@ -582,7 +667,7 @@ SOAPAction: "http://www.w3.org/2003/05/soap-envelope" -HTTP/1.1 200 +HTTP 200 ``` [Doc](https://hurl.dev/docs/request.html#xml-body) @@ -592,14 +677,14 @@ HTTP/1.1 200 ```hurl GET https://example.org -HTTP/* 200 +HTTP 200 [Captures] csrf_token: xpath "string(//meta[@name='_csrf_token']/@content)" POST https://example.org/login?user=toto&password=1234 X-CSRF-TOKEN: {{csrf_token}} -HTTP/* 302 +HTTP 302 ``` [Doc](https://hurl.dev/docs/capturing-response.html#xpath-capture) @@ -609,7 +694,7 @@ HTTP/* 302 ```hurl GET https://example.org/data.bin -HTTP/* 200 +HTTP 200 [Asserts] bytes startsWith hex,efbbbf; ``` @@ -631,9 +716,9 @@ hurl - run and test HTTP requests. ## Description -**Hurl** is an HTTP client that performs HTTP requests defined in a simple plain text format. +**Hurl** is a command line tool that runs HTTP requests defined in a simple plain text format. -Hurl is very versatile. It enables chaining HTTP requests, capturing values from HTTP responses, and making assertions. +It can chain requests, capture values and evaluate queries on headers and body response. Hurl is very versatile, it can be used for fetching data and testing HTTP sessions: HTML content, REST / SOAP / GraphQL APIs, or any other XML / JSON based APIs. ```shell $ hurl session.hurl @@ -690,11 +775,11 @@ GET http:/example.org/endpoint2 A value from an HTTP response can be-reused for successive HTTP requests. -A typical example occurs with csrf tokens. +A typical example occurs with CSRF tokens. ```hurl GET https://example.org -HTTP/1.1 200 +HTTP 200 # Capture the CSRF token value from html body. [Captures] csrf_token: xpath "normalize-space(//meta[@name='_csrf_token']/@content)" @@ -708,28 +793,28 @@ More information on captures can be found here [https://hurl.dev/docs/capturing- ### Asserts -The HTTP response defined in the Hurl session are used to make asserts. +The HTTP response defined in the Hurl file are used to make asserts. Responses are optional. -At the minimum, the response includes the asserts on the HTTP version and status code. +At the minimum, response includes assert on the HTTP status code. ```hurl -GET http:/google.com -HTTP/1.1 301 +GET http:/example.org +HTTP 301 ``` It can also include asserts on the response headers ```hurl -GET http:/google.com -HTTP/1.1 301 -Location: http://www.google.com +GET http:/example.org +HTTP 301 +Location: http://www.example.org ``` Explicit asserts can be included by combining a query and a predicate ```hurl -GET http:/google.com -HTTP/1.1 301 +GET http:/example.org +HTTP 301 [Asserts] xpath "string(//title)" == "301 Moved" ``` @@ -753,56 +838,61 @@ $ hurl --location foo.hurl will follow redirection for each entry in `foo.hurl`. You can also define an option only for a particular entry with an `[Options]` section. For instance, this Hurl file: ```hurl -GET https://google.com -HTTP/* 301 +GET https://example.org +HTTP 301 -GET https://google.com +GET https://example.org [Options] location: true -HTTP/* 200 +HTTP 200 ``` will follow a redirection only for the second entry. -Option | Description - --- | --- ---cacert | Specifies the certificate file for peer verification. The file may contain multiple CA certificates and must be in PEM format.
Normally Hurl is built to use a default file for this, so this option is typically used to alter that default file.
---color | Colorize Output.
---compressed | Request a compressed response using one of the algorithms br, gzip, deflate and automatically decompress the content.
---connect-timeout <SECONDS> | Maximum time in seconds that you allow Hurl's connection to take.

See also [`-m, --max-time`](#max-time) option.
--b, --cookie <FILE> | Read cookies from FILE (using the Netscape cookie file format).

Combined with [`-c, --cookie-jar`](#cookie-jar), you can simulate a cookie storage between successive Hurl runs.
--c, --cookie-jar <FILE> | Write cookies to FILE after running the session (only for one session).
The file will be written using the Netscape cookie file format.

Combined with [`-b, --cookie`](#cookie), you can simulate a cookie storage between successive Hurl runs.
---fail-at-end | Continue executing requests to the end of the Hurl file even when an assert error occurs.
By default, Hurl exits after an assert error in the HTTP response.

Note that this option does not affect the behavior with multiple input Hurl files.

All the input files are executed independently. The result of one file does not affect the execution of the other Hurl files.
---file-root <DIR> | Set root file system to import files in Hurl. This is used for both files in multipart form data and request body.
When this is not explicitly defined, the files are relative to the current directory in which Hurl is running.
--L, --location | Follow redirect. To limit the amount of redirects to follow use the [`--max-redirs`](#max-redirs) option
---glob <GLOB> | Specify input files that match the given glob pattern.

Multiple glob flags may be used. This flag supports common Unix glob patterns like *, ? and [].
However, to avoid your shell accidentally expanding glob patterns before Hurl handles them, you must use single quotes or double quotes around each pattern.
--i, --include | Include the HTTP headers in the output (last entry).
---ignore-asserts | Ignore all asserts defined in the Hurl file.
--k, --insecure | This option explicitly allows Hurl to perform "insecure" SSL connections and transfers.
---interactive | Stop between requests.
This is similar to a break point, You can then continue (Press C) or quit (Press Q).
---json | Output each hurl file result to JSON. The format is very closed to HAR format.
---max-redirs <NUM> | Set maximum number of redirection-followings allowed
By default, the limit is set to 50 redirections. Set this option to -1 to make it unlimited.
--m, --max-time <SECONDS> | Maximum time in seconds that you allow a request/response to take. This is the standard timeout.

See also [`--connect-timeout`](#connect-timeout) option.
---no-color | Do not colorize output.
---no-output | Suppress output. By default, Hurl outputs the body of the last response.
---noproxy <HOST(S)> | Comma-separated list of hosts which do not use a proxy.
Override value from Environment variable no_proxy.
--o, --output <FILE> | Write output to FILE instead of stdout.
--x, --proxy [protocol://]host[:port] | Use the specified proxy.
---report-junit <FILE> | Generate JUnit File.

If the FILE report already exists, it will be updated with the new test results.
---report-html <DIR> | Generate HTML report in DIR.

If the HTML report already exists, it will be updated with the new test results.
---retry | Retry requests if any error occurs (asserts, captures, runtimes etc...).
---retry-interval <MILLISECONDS> | Duration in milliseconds between each retry. Default is 1000 ms.
---retry-max-count <NUM> | Maximum number of retries. Set this option to -1 to make it unlimited. Default is 10.
---test | Activate test mode: with this, the HTTP response is not outputted anymore, progress is reported for each Hurl file tested, and a text summary is displayed when all files have been run.
---to-entry <ENTRY_NUMBER> | Execute Hurl file to ENTRY_NUMBER (starting at 1).
Ignore the remaining of the file. It is useful for debugging a session.
--u, --user <USER:PASSWORD> | Add basic Authentication header to each request.
--A, --user-agent <NAME> | Specify the User-Agent string to send to the HTTP server.
---variable <NAME=VALUE> | Define variable (name/value) to be used in Hurl templates.
---variables-file <FILE> | Set properties file in which your define your variables.

Each variable is defined as name=value exactly as with [`--variable`](#variable) option.

Note that defining a variable twice produces an error.
--v, --verbose | Turn on verbose output on standard error stream.
Useful for debugging.

A line starting with '>' means data sent by Hurl.
A line staring with '<' means data received by Hurl.
A line starting with '*' means additional info provided by Hurl.

If you only want HTTP headers in the output, [`-i, --include`](#include) might be the option you're looking for.
---very-verbose | Turn on more verbose output on standard error stream.

In contrast to [`--verbose`](#verbose) option, this option outputs the full HTTP body request and response on standard error. In addition, lines starting with '**' are libcurl debug logs.
--h, --help | Usage help. This lists all current command line options with a short description.
--V, --version | Prints version information
+| Option | Description | +|------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| --cacert <FILE> | Specifies the certificate file for peer verification. The file may contain multiple CA certificates and must be in PEM format.
Normally Hurl is built to use a default file for this, so this option is typically used to alter that default file.
| +| -E, --cert <CERTIFICATE[:PASSWORD]> | Client certificate file and password.

See also [`--key`](#key).
| +| --color | Colorize Output.
| +| --compressed | Request a compressed response using one of the algorithms br, gzip, deflate and automatically decompress the content.
| +| --connect-timeout <SECONDS> | Maximum time in seconds that you allow Hurl's connection to take.

See also [`-m, --max-time`](#max-time).
| +| --connect-to <HOST1:PORT1:HOST2:PORT2> | For a request to the given HOST1:PORT1 pair, connect to HOST2:PORT2 instead. This option can be used several times in a command line.

See also [`--resolve`](#resolve).
| +| -b, --cookie <FILE> | Read cookies from FILE (using the Netscape cookie file format).

Combined with [`-c, --cookie-jar`](#cookie-jar), you can simulate a cookie storage between successive Hurl runs.
| +| -c, --cookie-jar <FILE> | Write cookies to FILE after running the session (only for one session).
The file will be written using the Netscape cookie file format.

Combined with [`-b, --cookie`](#cookie), you can simulate a cookie storage between successive Hurl runs.
| +| --fail-at-end | Continue executing requests to the end of the Hurl file even when an assert error occurs.
By default, Hurl exits after an assert error in the HTTP response.

Note that this option does not affect the behavior with multiple input Hurl files.

All the input files are executed independently. The result of one file does not affect the execution of the other Hurl files.
| +| --file-root <DIR> | Set root file system to import files in Hurl. This is used for both files in multipart form data and request body.
When this is not explicitly defined, the files are relative to the current directory in which Hurl is running.
| +| -L, --location | Follow redirect. To limit the amount of redirects to follow use the [`--max-redirs`](#max-redirs) option
| +| --glob <GLOB> | Specify input files that match the given glob pattern.

Multiple glob flags may be used. This flag supports common Unix glob patterns like *, ? and [].
However, to avoid your shell accidentally expanding glob patterns before Hurl handles them, you must use single quotes or double quotes around each pattern.
| +| -i, --include | Include the HTTP headers in the output (last entry).
| +| --ignore-asserts | Ignore all asserts defined in the Hurl file.
| +| -k, --insecure | This option explicitly allows Hurl to perform "insecure" SSL connections and transfers.
| +| --interactive | Stop between requests.
This is similar to a break point, You can then continue (Press C) or quit (Press Q).
| +| --json | Output each hurl file result to JSON. The format is very closed to HAR format.
| +| --key <KEY> | Private key file name.
| +| --max-redirs <NUM> | Set maximum number of redirection-followings allowed
By default, the limit is set to 50 redirections. Set this option to -1 to make it unlimited.
| +| -m, --max-time <SECONDS> | Maximum time in seconds that you allow a request/response to take. This is the standard timeout.

See also [`--connect-timeout`](#connect-timeout).
| +| --no-color | Do not colorize output.
| +| --no-output | Suppress output. By default, Hurl outputs the body of the last response.
| +| --noproxy <HOST(S)> | Comma-separated list of hosts which do not use a proxy.
Override value from Environment variable no_proxy.
| +| -o, --output <FILE> | Write output to FILE instead of stdout.
| +| -x, --proxy <[PROTOCOL://]HOST[:PORT]> | Use the specified proxy.
| +| --report-junit <FILE> | Generate JUnit File.

If the FILE report already exists, it will be updated with the new test results.
| +| --report-html <DIR> | Generate HTML report in DIR.

If the HTML report already exists, it will be updated with the new test results.
| +| --resolve <HOST:PORT:ADDR> | Provide a custom address for a specific host and port pair. Using this, you can make the Hurl requests(s) use a specified address and prevent the otherwise normally resolved address to be used. Consider it a sort of /etc/hosts alternative provided on the command line.
| +| --retry | Retry requests if any error occurs (asserts, captures, runtimes etc...).
| +| --retry-interval <MILLISECONDS> | Duration in milliseconds between each retry. Default is 1000 ms.
| +| --retry-max-count <NUM> | Maximum number of retries. Set this option to -1 to make it unlimited. Default is 10.
| +| --ssl-no-revoke | (Windows) This option tells Hurl to disable certificate revocation checks. WARNING: this option loosens the SSL security, and by using this flag you ask for exactly that.
| +| --test | Activate test mode: with this, the HTTP response is not outputted anymore, progress is reported for each Hurl file tested, and a text summary is displayed when all files have been run.
| +| --to-entry <ENTRY_NUMBER> | Execute Hurl file to ENTRY_NUMBER (starting at 1).
Ignore the remaining of the file. It is useful for debugging a session.
| +| -u, --user <USER:PASSWORD> | Add basic Authentication header to each request.
| +| -A, --user-agent <NAME> | Specify the User-Agent string to send to the HTTP server.
| +| --variable <NAME=VALUE> | Define variable (name/value) to be used in Hurl templates.
| +| --variables-file <FILE> | Set properties file in which your define your variables.

Each variable is defined as name=value exactly as with [`--variable`](#variable) option.

Note that defining a variable twice produces an error.
| +| -v, --verbose | Turn on verbose output on standard error stream.
Useful for debugging.

A line starting with '>' means data sent by Hurl.
A line staring with '<' means data received by Hurl.
A line starting with '*' means additional info provided by Hurl.

If you only want HTTP headers in the output, [`-i, --include`](#include) might be the option you're looking for.
| +| --very-verbose | Turn on more verbose output on standard error stream.

In contrast to [`--verbose`](#verbose) option, this option outputs the full HTTP body request and response on standard error. In addition, lines starting with '**' are libcurl debug logs.
| +| -h, --help | Usage help. This lists all current command line options with a short description.
| +| -V, --version | Prints version information
| ## Environment @@ -810,23 +900,23 @@ Environment variables can only be specified in lowercase. Using an environment variable to set the proxy has the same effect as using the [`-x, --proxy`](#proxy) option. -Variable | Description - --- | --- -`http_proxy [protocol://][:port]` | Sets the proxy server to use for HTTP.
-`https_proxy [protocol://][:port]` | Sets the proxy server to use for HTTPS.
-`all_proxy [protocol://][:port]` | Sets the proxy server to use if no protocol-specific proxy is set.
-`no_proxy ` | List of host names that shouldn't go through any proxy.
-`HURL_name value` | Define variable (name/value) to be used in Hurl templates. This is similar than [`--variable`](#variable) and [`--variables-file`](#variables-file) options.
-`NO_COLOR` | When set to a non-empty string, do not colorize output (see [`--no-color`](#no-color) option).
+| Variable | Description | +|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `http_proxy [protocol://][:port]` | Sets the proxy server to use for HTTP.
| +| `https_proxy [protocol://][:port]` | Sets the proxy server to use for HTTPS.
| +| `all_proxy [protocol://][:port]` | Sets the proxy server to use if no protocol-specific proxy is set.
| +| `no_proxy ` | List of host names that shouldn't go through any proxy.
| +| `HURL_name value` | Define variable (name/value) to be used in Hurl templates. This is similar than [`--variable`](#variable) and [`--variables-file`](#variables-file) options.
| +| `NO_COLOR` | When set to a non-empty string, do not colorize output (see [`--no-color`](#no-color) option).
| ## Exit Codes -Value | Description - --- | --- -`1` | Failed to parse command-line options.
-`2` | Input File Parsing Error.
-`3` | Runtime error (such as failure to connect to host).
-`4` | Assert Error.
+| Value | Description | +|-------|---------------------------------------------------------| +| `1` | Failed to parse command-line options.
| +| `2` | Input File Parsing Error.
| +| `3` | Runtime error (such as failure to connect to host).
| +| `4` | Assert Error.
| ## WWW @@ -843,12 +933,12 @@ curl(1) hurlfmt(1) ### Linux -Precompiled binary is available at [hurl-1.8.0-x86_64-linux.tar.gz]: +Precompiled binary is available at [hurl-2.0.0-x86_64-linux.tar.gz]: ```shell $ INSTALL_DIR=/tmp -$ curl -sL https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-x86_64-linux.tar.gz | tar xvz -C $INSTALL_DIR -$ export PATH=$INSTALL_DIR/hurl-1.8.0:$PATH +$ curl -sL https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-x86_64-linux.tar.gz | tar xvz -C $INSTALL_DIR +$ export PATH=$INSTALL_DIR/hurl-2.0.0:$PATH ``` #### Debian / Ubuntu @@ -856,8 +946,8 @@ $ export PATH=$INSTALL_DIR/hurl-1.8.0:$PATH For Debian / Ubuntu, Hurl can be installed using a binary .deb file provided in each Hurl release. ```shell -$ curl -LO https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl_1.8.0_amd64.deb -$ sudo apt update && apt install ./hurl_1.8.0_amd64.deb +$ curl -LO https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl_2.0.0_amd64.deb +$ sudo apt update && apt install ./hurl_2.0.0_amd64.deb ``` #### Arch Linux / Manjaro @@ -870,7 +960,7 @@ $ sudo apt update && apt install ./hurl_1.8.0_amd64.deb ### macOS -Precompiled binary is available at [hurl-1.8.0-x86_64-macos.tar.gz] for x86 CPUs and [hurl-1.8.0-arm64-macos.tar.gz] for ARM CPUS. +Precompiled binary is available at [hurl-2.0.0-x86_64-macos.tar.gz] for x86 CPUs and [hurl-2.0.0-arm64-macos.tar.gz] for ARM CPUS. #### Homebrew @@ -894,11 +984,11 @@ $ sudo pkg install hurl #### Zip File -Hurl can be installed from a standalone zip file [hurl-1.8.0-win64.zip]. You will need to update your `PATH` variable. +Hurl can be installed from a standalone zip file [hurl-2.0.0-win64.zip]. You will need to update your `PATH` variable. #### Installer -An installer [hurl-1.8.0-win64-installer.exe] is also available. +An installer [hurl-2.0.0-win64-installer.exe] is also available. #### Chocolatey @@ -1011,7 +1101,7 @@ Please follow the [contrib on Windows section]. [libcurl]: https://curl.se/libcurl/ [JSON body]: https://hurl.dev/docs/request.html#json-body [XML body]: https://hurl.dev/docs/request.html#xml-body -[multiline string body]: https://hurl.dev/docs/request.html#multiline-string-body +[XML multiline string body]: https://hurl.dev/docs/request.html#multiline-string-body [predicates]: https://hurl.dev/docs/asserting-response.html#predicates [JSONPath]: https://goessner.net/articles/JsonPath/ [Basic authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#basic_authentication_scheme @@ -1022,12 +1112,13 @@ Please follow the [contrib on Windows section]. [curl]: https://curl.se [entry]: https://hurl.dev/docs/entry.html [`--test` option]: https://hurl.dev/docs/manual.html#test +[Hurl templates]: https://hurl.dev/docs/templates.html [GitHub]: https://github.com/Orange-OpenSource/hurl -[hurl-1.8.0-win64.zip]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-win64.zip -[hurl-1.8.0-win64-installer.exe]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-win64-installer.exe -[hurl-1.8.0-x86_64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-x86_64-macos.tar.gz -[hurl-1.8.0-arm64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-arm64-macos.tar.gz -[hurl-1.8.0-x86_64-linux.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl-1.8.0-x86_64-linux.tar.gz +[hurl-2.0.0-win64.zip]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-win64.zip +[hurl-2.0.0-win64-installer.exe]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-win64-installer.exe +[hurl-2.0.0-x86_64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-x86_64-macos.tar.gz +[hurl-2.0.0-arm64-macos.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-arm64-macos.tar.gz +[hurl-2.0.0-x86_64-linux.tar.gz]: https://github.com/Orange-OpenSource/hurl/releases/download/2.0.0/hurl-2.0.0-x86_64-linux.tar.gz [AUR]: https://wiki.archlinux.org/index.php/Arch_User_Repository [`hurl-bin` package]: https://aur.archlinux.org/packages/hurl-bin/ [install]: https://www.rust-lang.org/tools/install diff --git a/packages/hurl/src/cli/options.rs b/packages/hurl/src/cli/options.rs index 5a3005e6e..a59fbf3a6 100644 --- a/packages/hurl/src/cli/options.rs +++ b/packages/hurl/src/cli/options.rs @@ -112,16 +112,16 @@ pub fn app(version: &str) -> Command { ) .arg( clap::Arg::new("client_cert_file") + .short('E') .long("cert") - .value_name("FILE") + .value_name("CERTIFICATE[:PASSWORD]") .help("Client certificate file and password") .num_args(1) - .short('E') ) .arg( clap::Arg::new("client_key_file") .long("key") - .value_name("FILE") + .value_name("KEY") .help("Private key file name") .num_args(1) ) @@ -343,7 +343,7 @@ pub fn app(version: &str) -> Command { .arg( clap::Arg::new("ssl_no_revoke") .long("ssl-no-revoke") - .help("(Schannel) This option tells curl to disable certificate revocation checks. WARNING: this option loosens the SSL security, and by using this flag you ask for exactly that.") + .help("(Windows) This option tells Hurl to disable certificate revocation checks. WARNING: this option loosens the SSL security, and by using this flag you ask for exactly that.") .action(ArgAction::SetTrue) ) .arg(