Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions sites/build_rss.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

Examples:
$ python3 build_rss.py hurl.dev/_posts/2023-06-30-announcing-hurl-4.0.0.md

Note: reference links that contains backtick, like `[`location`]: {% link _docs/filters.md %}#location` are
not well-supported and should be inlined.
"""

from _datetime import datetime
import re
import sys
Expand Down
3 changes: 2 additions & 1 deletion sites/generate/get_artifacts_hash.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#!/usr/bin/env/python3
#!/usr/bin/env python3
"""Create SHASUM from GitHub release artifacts for a given version

Example:
$ python3 get_artifacts_hash.py 1.7.0

"""

import argparse
import hashlib
import json
Expand Down
18 changes: 17 additions & 1 deletion sites/hurl.dev/_data/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@
- title: Testing Bytes Content
- title: SSL Certificate
- title: Checking Full Body
- title: Testing Redirections
- title: Debug Tips
items:
- title: Verbose Mode
- title: Error Format
- title: Output Response Body
- title: Export curl Commands
- title: Using Proxy
- title: Reports
items:
- title: HTML Report
Expand Down Expand Up @@ -208,6 +216,7 @@
- title: SHA-256 capture
- title: MD5 capture
- title: URL capture
- title: Redirects capture
- title: IP address capture
- title: Variable capture
- title: Duration capture
Expand Down Expand Up @@ -246,6 +255,7 @@
- title: SHA-256 assert
- title: MD5 assert
- title: URL assert
- title: URL redirect
- title: IP address assert
- title: Variable assert
- title: Duration assert
Expand All @@ -259,24 +269,31 @@
items:
- title: base64Decode
- title: base64Encode
- title: base64UrlSafeDecode
- title: base64UrlSafeEncode
- title: count
- title: daysAfterNow
- title: daysBeforeNow
- title: decode
- title: first
- title: format
- title: htmlEscape
- title: htmlUnescape
- title: jsonpath
- title: last
- title: location
- title: nth
- title: regex
- title: replace
- title: replaceRegex
- title: split
- title: toDate
- title: toFloat
- title: toInt
- title: toString
- title: urlDecode
- title: urlEncode
- title: urlQueryParam
- title: xpath
- title: Templates
path: /docs/templates.html
Expand Down Expand Up @@ -338,7 +355,6 @@
- title: Debugging a specific entry
- title: Use Error Format
- title: Get Response Body
- title: Interactive Mode
- title: Include Headers Like curl
- title: Export curl Commands
- title: Using a Proxy
Expand Down
46 changes: 36 additions & 10 deletions sites/hurl.dev/_docs/asserting-response.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ The asserts order in a Hurl file is:
</div>
</div>


## Implicit asserts

### Version - Status
Expand Down Expand Up @@ -383,6 +382,7 @@ can extract data from
- [`md5`](#md5-assert)
- others:
- [`url`](#url-assert)
- [`redirects`](#redirects-assert)
- [`ip`](#ip-address-assert)
- [`variable`](#variable-assert)
- [`duration`](#duration-assert)
Expand All @@ -399,14 +399,14 @@ Predicates consist of a predicate function and a predicate value. Predicate func
|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| __`==`__ | Query and predicate value are equal | `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` |
| __{% raw %}`>`__ | Query number or date is greater than predicate value | `jsonpath "$.year" > 1978`<br><br>`jsonpath "$.createdAt" toDate "%+" > {{ a_date }}`{% endraw %} |
| __`>=`__ | Query number or date is greater than or equal to the predicate value | `jsonpath "$.year" >= 1978` |
| __`<`__ | Query number or date is less than that predicate value | `jsonpath "$.year" < 1978` |
| __`<=`__ | Query number or date is less than or equal to the predicate value | `jsonpath "$.year" <= 1978` |
| __`startsWith`__ | Query starts with the predicate value<br>Value is string or a binary content | `jsonpath "$.movie" startsWith "The"`<br><br>`bytes startsWith hex,efbbbf;` |
| __`endsWith`__ | Query ends with the predicate value<br>Value is string or a binary content | `jsonpath "$.movie" endsWith "Back"`<br><br>`bytes endsWith hex,ab23456;` |
| __`contains`__ | If query returns a collection of string or numbers, query collection includes the predicate value (string or number)<br>If query returns a string or a binary content, query contains the predicate value (string or bytes) | `jsonpath "$.movie" contains "Empire"`<br><br>`bytes contains hex,beef;`<br><br>`jsonpath "$.numbers" contains 42` |
| __`matches`__ | Part of the query string matches the regex pattern described by the predicate value | `jsonpath "$.release" matches "\\d{4}"`<br><br>`jsonpath "$.release" matches /\d{4}/` |
| __`matches`__ | Part of the query string matches the regex pattern described by the predicate value (see [regex syntax](https://docs.rs/regex/latest/regex/#syntax)) | `jsonpath "$.release" matches "\\d{4}"`<br><br>`jsonpath "$.release" matches /\d{4}/` |
| __`exists`__ | Query returns a value | `jsonpath "$.book" exists` |
| __`isBoolean`__ | Query returns a boolean | `jsonpath "$.succeeded" isBoolean` |
| __`isCollection`__ | Query returns a collection | `jsonpath "$.books" isCollection` |
Expand All @@ -418,10 +418,7 @@ Predicates consist of a predicate function and a predicate value. Predicate func
| __`isString`__ | Query returns a string | `jsonpath "$.name" isString` |
| __`isIpv4`__ | Query returns an IPv4 address | `ip isIpv4` |
| __`isIpv6`__ | Query returns an IPv6 address | `ip isIpv6` |

Query contains the predicate value if query returns a collection of string or numbers<br>
Query

| __`isUuid`__ | Query returns a UUID | `ip isUuid` |


Each predicate can be negated by prefixing it with `not` (for instance, `not contains` or `not exists`)
Expand Down Expand Up @@ -843,6 +840,16 @@ captured group value. When the regex pattern is a double-quoted string, metachar
pattern (like `\d`, `\s`) must be escaped; literal pattern enclosed by `/` can also be used to avoid metacharacters
escaping.

The regex syntax is documented at <https://docs.rs/regex/latest/regex/#syntax>. For instance, once can use [flags](https://docs.rs/regex/latest/regex/#grouping-and-flags)
to enable case-insensitive match:

```hurl
GET https://example.org/hello
HTTP 200
[Asserts]
regex /(?i)hello (\w+)!/ == "World"
```

### SHA-256 assert

Check response body [SHA-256] hash.
Expand Down Expand Up @@ -902,6 +909,24 @@ HTTP 200
url == "https://example.org/redirected"
```

### Redirects assert

Check each step of redirection. This is most meaningful if you have told Hurl to follow redirection (see [`[Options]`section][options] or
[`--location` option]). Redirects assert consists of the keyword `redirects` followed by a predicate function and value. The `redirects`
query returns a collection of redirections that can be tested with a [`location` filter]:

```hurl
GET https://example.org/redirecting/1
[Options]
location: true
HTTP 200
[Asserts]
redirects count == 3
redirects nth 0 location == "https://example.org/redirecting/2"
redirects nth 1 location == "https://example.org/redirecting/3"
redirects nth 2 location == "https://example.org/redirected"
```

### IP address assert

Check the IP address of the last connection. The value of the `ip` query is a string.
Expand Down Expand Up @@ -985,3 +1010,4 @@ certificate "Serial-Number" matches "[0-9af]+"
[`Content-Encoding` HTTP header]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding
[`Content-Type` header]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
[`body` assert]: #body-assert
[`location` filter]: {% link _docs/filters.md %}#location
32 changes: 31 additions & 1 deletion sites/hurl.dev/_docs/capturing-response.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ A query can extract data from
- [`md5`](#md5-capture)
- others:
- [`url`](#url-capture)
- [`redirects`](#redirects-capture)
- [`ip`](#ip-address-capture)
- [`variable`](#variable-capture)
- [`duration`](#duration-capture)
Expand Down Expand Up @@ -299,7 +300,17 @@ name: regex "Hello ([a-zA-Z]+)"

The regex pattern must have at least one capture group, otherwise the
capture will fail. When the 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.
(like `\d`, `\s`) must be escaped; literal pattern enclosed by `/` can also be used to avoid metacharacters escaping.

The regex syntax is documented at <https://docs.rs/regex/latest/regex/#syntax>. For instance, one can use [flags](https://docs.rs/regex/latest/regex/#grouping-and-flags)
to enable case-insensitive match:

```hurl
GET https://example.org/hello
HTTP 200
[Captures]
word: regex /(?i)hello (\w+)!/
```

### SHA-256 capture

Expand Down Expand Up @@ -343,6 +354,25 @@ HTTP 200
landing_url: url
```

### Redirects capture

Capture each step of redirection. This is most meaningful if you have told Hurl to follow redirection (see [`[Options]`section][options] or
[`--location` option]). Redirects capture consists of a variable name, followed by a `:`, and the keyword `redirects`.
Redirects query returns a collection so each step of the redirection can be capture.

```hurl
GET https://example.org/redirecting/1
[Options]
location: true
HTTP 200
[Asserts]
redirects count == 3
[Captures]
step1: redirects nth 0 location
step2: redirects nth 1 location
step3: redirects nth 2 location
```

### IP address capture

Capture the IP address of the last connection. The value of the `ip` query is a string.
Expand Down
62 changes: 54 additions & 8 deletions sites/hurl.dev/_docs/entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ of the redirection, allowing insertion of asserts in each response.

```hurl
# First entry, test the redirection (status code and 'Location' header)
GET https://google.fr
GET https://example.org
HTTP 301
Location: https://www.google.fr/
Location: https://www.example.org

# Second entry, the 200 OK response
GET https://www.google.fr
GET https://www.example.org
HTTP 200
```

Expand All @@ -100,21 +100,66 @@ to be followed. In this case, asserts are executed on the last received response
redirections can be limited with [`--max-redirs`].

```hurl
# Running hurl --location google.hurl
GET https://google.fr
# Running hurl --location foo.hurl
GET https://example.org
HTTP 200
```

Finally, you can force redirection on a particular request with an [`[Options]` section][options] and the[`--location`]
Finally, you can force redirection on a particular request with an [`[Options]` section][options] and the [`--location`]
/ [`--location-trusted`] options:

```hurl
GET https://google.fr
GET https://example.org
[Options]
location-trusted: true
HTTP 200
```

Redirections can be tested either by:

- running and asserting each step of redirection:

```hurl
GET https://example.org/step1
HTTP 301
[Asserts]
header "Location" == "https://example.org/step2"


GET https://example.org/step2
HTTP 301
[Asserts]
header "Location" == "https://example.org/step3"


GET https://example.org/step3
HTTP 200
```

- using [`--location`] / [`--location-trusted`], testing each step with [`redirects` query]:

```hurl
GET https://example.org/step1
[Options]
location: true
HTTP 200
[Asserts]
redirects count == 2
redirects nth 0 location == "https://example.org/step2"
redirects nth 1 location == "https://example.org/step3"
```

[`url` query] can also be used to get the final effective URL:

```hurl
GET https://example.org/step1
[Options]
location: true
HTTP 200
[Asserts]
url == "https://example.org/step3"
```

### Retry

Every entry can be retried upon asserts, captures or runtime errors. Retries allow polling scenarios and effective runs
Expand Down Expand Up @@ -195,7 +240,6 @@ For complete reference, below is a diagram for the executed entries.
</div>



[request]: {% link _docs/request.md %}
[response]: {% link _docs/response.md %}
[capture values]: {% link _docs/capturing-response.md %}
Expand All @@ -214,3 +258,5 @@ For complete reference, below is a diagram for the executed entries.
[`--retry-interval`]: {% link _docs/manual.md %}#retry-interval
[`delay`]: {% link _docs/manual.md %}#retry
[`repeat`]: {% link _docs/manual.md %}#repeat
[`redirects` query]: {% link _docs/asserting-response.md %}#redirects-assert
[`url` query]: {% link _docs/asserting-response.md %}#url-assert
Loading