Sonde

Hurl Compatibility

Hurl 8.0.1 compatibility: queries, filters, predicates, functions, options, CLI flags, env vars, config, differences

Sonde targets Hurl 8.0.1 files and CLI behavior. This page lists every known difference: syntax, runtime and command line.

Syntax (sonde check, sonde fmt, all commands that read files)

Measured against the vendored Hurl 8.0.1 test tree (testdata/conformance/hurl):

  • All 272 valid .hurl files outside tests_error_parser parse and print back byte for byte (also with CRLF line endings); the two intentionally invalid ones (invalid UTF-8, bad method) are rejected with Hurl's message.
  • All 46 invalid files of tests_error_parser are rejected (its 3 valid companions parse); for the 44 with an .err oracle, the error position and the rendered message match exactly.

Differences on inputs outside the test tree:

InputHurl 8.0.1Sonde
Regex literal errors other than an invalid {…} repetitionRust regex messageGo regexp message (same position)
Regexes valid in only one engine, e.g. a{,3}, \d{2}{2}, a{1001}, []-Z]acceptedrejected
… and the reverse, e.g. [0-9[Query]rejectedaccepted
XML body with DTD-declared entitiesaccepted (libxml2)rejected: invalid XML
XML body with text or a comment before the root elementrejectedaccepted
XML error positioncharacter where libxml2 failedlast character read by Go's encoding/xml (same in all test files)
JSON nested deeper than 1000 levelsstack overflowrejected: nesting is deeper than 1000 levels
File larger than 64 MiBacceptedrejected: Issue reading from FILE: file is larger than 64 MiB

Accepted as Hurl does: text after a placeholder's variable inside a string, e.g. {{a b}} or {{a}b}}, is ignored (and kept by sonde fmt); XML declarations with any encoding or version.

sonde fmt is not hurlfmt: it only normalizes horizontal whitespace and line endings (see docs/architecture.md, CLI commands) and never reorders sections. Files already formatted by hurlfmt are left unchanged.

Evaluation (queries, filters, predicates, templates)

Checked against Hurl 8.0.1 by internal/evaldiff: 300 asserts over the fixtures in testdata/eval/diff (124 of them failing on purpose, so their error messages are compared too) give the same result and the same message, except the rows below (testdata/eval/diff/known-differences.txt). Every JSONPath, XPath, regex and date format literal of the conformance tests is also accepted or rejected as Hurl does.

InputHurl 8.0.1Sonde
Integers beyond 64 bits in comparisons, e.g. 123456789012345678901234567890 > 9223372036854775807compared as digit strings: falsecompared numerically: true
Rendering of a float whose fraction is negative or below 2.2e-16, e.g. toString of -1.5 or 1e-300-1.5.0, 0.000…1.0-1.5, 0.000…1
Negative JSONPath number literal with a fraction, e.g. $[?@ == -1.5]read as -0.5read as -1.5
NaN (e.g. from XPath number() on text) compared with a numberequal to every numberequal to nothing, never less or greater
Unprefixed XPath name on an XML document with a default namespace, e.g. count(//title)matches nothing (use _:title)also matches the namespaced elements
Malformed XML response body for xpath, or XML using entities declared in a DTDlibxml2 recovers what it can, expands the entitiesInvalid XML error
HTML response for xpathlibxml2 HTML parserHTML5 parser: html, head and body always exist
\b in regexes, and \W/\S inside a bracket classUnicodeASCII
Response with several content codings, e.g. Content-Encoding: gzip, brdecoded in listed orderdecoded in reverse order (last applied first)
Content-Encoding: zstdcompression zstd is not supporteddecoded
Decoded (decompressed) body larger than 512 MiBdecodedDecompression error
JSON response nested deeper than 128 levels, or with a lone surrogate escape (\ud800)Invalid JSONaccepted (the surrogate reads as U+FFFD)
urlQueryParam on a malformed or unusual URL, e.g. http:///xparsed by the Rust url crate (WHATWG rules)parsed by Go's net/url: http:///x is empty host, other messages differ
Nested numbers compared by JSONPath ==, e.g. $[?@.a == [1]] on {"a": [1.0]}compared as written: not equalcompared by value: equal
Date string with a leap second, e.g. toDate of 23:59:60keeps the instant at 23:59:59.999999999rolls over to the next minute
Regex syntax outside the common subset: (?x), \u{…}, repetitions over 1000, class set operations && --; \Q…\Efirst group accepted, \Q…\E rejectedfirst group rejected (Invalid regex), \Q…\E accepted

Regexes (matches, regex, replaceRegex, JSONPath match/search) run on Go's RE2 engine with \d, \w and \s translated to their Unicode meaning, as in Hurl.

HTTP and command line (sonde FILE..., sonde run)

Measured with the conformance harness (make conformance, see docs/conformance.md). Differences:

InputHurl 8.0.1Sonde
http2 option on an http:// URLtries an h2c upgradeHTTP/1.1
http3 option or --http3HTTP/3 when libcurl supports itUnsupported HTTP version error
Order of response headers with different namesas receivedgrouped by name, names sorted (values of one name keep their order)
Default User-Agenthurl/<version>sonde/<version> (SONDE_DEFAULT_USER_AGENT replaces it)
--version outputHurl and libcurl versions and featuressonde version, commit, build date, Go version
Request-file path escaping the file root through a symbolic linkallowed (lexical check)denied
cacert, cert, key, pinnedpubkey, netrc-file in [Options]any path, relative to the working directoryrelative to the working directory, confined to the file root (command line values are not confined)
unix-socket in [Options]any pathconfined to the file root
A failing repeat iteration followed by a passing one (--continue-on-error)file reported as successfulfile fails; only retried attempts are discounted
Proxy environment variableshttp_proxy, https_proxy, no_proxy, ALL_PROXY (libcurl)http_proxy, https_proxy, no_proxy (and uppercase forms); ALL_PROXY ignored; netrc credentials are not sent through an environment proxy unless --netrc-allow-reroute
Response body size without --max-filesizeunlimited512 MiB (raw and decoded)
Cookie domain matchingsuffix match (evilexample.com matches a cookie of example.com)dot-boundary match
--very-verbose and verbose connection lines (* Connected to…, ** …)libcurl debug linesnot printed
--cookie-jar file header# This file was generated by Hurl# This file was generated by sonde
Secrets in --json outputprinted as isredacted (***), as in every other output
HTML report (--report-html)per-file pages with source, timeline and waterfallsame directory layout; per-file pages with source, calls and bodies, no timeline; no JavaScript, strict CSP

Queries

QueryStatusDescription
bodysupportedthe response body, decoded per Content-Encoding
bytessupportedthe decoded response body as raw bytes
certificatesupporteda field of the peer TLS certificate (Subject, Issuer, dates, serial, SAN, or the raw value)
cookiesupporteda Set-Cookie value or one of its attributes by name[Attribute]
durationsupportedtotal request duration in milliseconds
headersupportedthe value of a named response header
ipsupportedthe remote IP address the request connected to
jsonpathsupporteda JSONPath expression evaluated against a JSON body
md5supportedthe MD5 digest of the response body
rawbytessupportedthe response body as raw, undecoded bytes
redirectssupportedthe list of intermediate responses in a redirect chain
regexsupportedthe first capture group of a regex matched against the body
sha256supportedthe SHA-256 digest of the response body
statussupportedHTTP response status code, as an integer
urlsupportedthe final URL after following redirects
variablesupportedthe current value of a named variable
versionsupportedHTTP version of the response (HTTP/1.0, HTTP/1.1, HTTP/2, HTTP/3)
xpathsupportedan XPath expression evaluated against an HTML or XML body

Filters

FilterStatusDescription
base64Decodesupporteddecodes a base64 string into bytes
base64Encodesupportedencodes bytes as a base64 string
base64UrlSafeDecodesupporteddecodes a URL-safe base64 string into bytes
base64UrlSafeEncodesupportedencodes bytes as a URL-safe base64 string
charsetDecodesupporteddecodes bytes to a string using the named charset
countsupportedthe number of elements in a collection
dateFormatsupportedformats a date using a strftime-style pattern
daysAfterNowsupporteddays between now and a date value, positive if in the future
daysBeforeNowsupporteddays between a date value and now, positive if in the past
decodesupporteddeprecated alias of charsetDecode
firstsupportedthe first element of a collection
formatsupporteddeprecated alias of dateFormat
htmlEscapesupportedescapes HTML special characters in a string
htmlUnescapesupportedunescapes HTML entities in a string
jsonpathsupportedevaluates a JSONPath expression against a JSON value
lastsupportedthe last element of a collection
locationsupportedthe Location header value of an HTTP response value
nthsupportedthe nth element (0-based) of a collection
regexsupportedthe first capture group of a regex matched against a string
replacesupportedreplaces every occurrence of a substring
replaceRegexsupportedreplaces every regex match with a replacement string
splitsupportedsplits a string on a separator into a list
toDatesupportedparses a string into a date using a strftime-style pattern
toFloatsupportedconverts a value to a floating-point number
toHexsupportedencodes bytes as a lowercase hex string
toIntsupportedconverts a value to an integer
toStringsupportedconverts a value to its string representation
urlDecodesupportedpercent-decodes a URL-encoded string
urlEncodesupportedpercent-encodes a string for use in a URL
urlQueryParamsupportedextracts a named query parameter from a URL string
utf8Decodesupporteddecodes bytes as UTF-8 into a string
utf8Encodesupportedencodes a string as UTF-8 bytes
xpathsupportedevaluates an XPath expression against an HTML or XML value

Predicates

PredicateStatusDescription
!=supportedthe value differs from the expected value
<supportedthe value is less than the expected number or date
<=supportedthe value is less than or equal to the expected number or date
==supportedthe value equals the expected value
>supportedthe value is greater than the expected number or date
>=supportedthe value is greater than or equal to the expected number or date
containssupporteda string, bytes or list value contains the expected element
endsWithsupporteda string or bytes value ends with the expected suffix
existssupportedthe query produced a value
includessupporteda list contains the expected element (deprecated alias of contains)
isBooleansupportedthe value is a boolean
isCollectionsupportedthe value is a list or object
isDatesupportedthe value is a date
isEmptysupporteda string, bytes, list or object value is empty
isFloatsupportedthe value is a floating-point number
isIntegersupportedthe value is an integer
isIpv4supportedthe value is a valid IPv4 address string
isIpv6supportedthe value is a valid IPv6 address string
isIsoDatesupportedthe value is a string in ISO 8601 date-time format
isListsupportedthe value is a list
isNumbersupportedthe value is an integer or a float
isObjectsupportedthe value is a JSON object
isStringsupportedthe value is a string
isUuidsupportedthe value is a string in UUID format
matchessupporteda string matches the expected regex
startsWithsupporteda string or bytes value starts with the expected prefix

Template functions

FunctionStatusDescription
newDatesupportedreturns the current date-time
newUuidsupportedreturns a freshly generated UUID v4

Request options

Request [Options] section keys.

OptionStatusPhaseDescription
aws-sigv4unsupportedsigns the request with AWS Signature Version 4 (stretch goal; not scheduled (low conformance weight))
cacertsupportedCA certificate bundle used to verify the server (PEM)
certsupportedclient certificate file, optionally with :PASSWORD
compressedsupportedrequests a compressed response and decodes it
connect-timeoutsupportedmaximum time allowed to establish the connection
connect-tosupportedredirects connections for HOST1:PORT1 to HOST2:PORT2
delaysupportedsleep before sending this entry's request
digestunsupporteduses HTTP Digest authentication (HTTP Digest authentication not implemented (low conformance weight))
headersupportedadds a custom header to the request
http1.0unsupportedforces HTTP/1.0 (Go's net/http cannot send a literal HTTP/1.0 request (Request.Proto is ignored))
http1.1supportedforces HTTP/1.1
http2supportedforces HTTP/2
http3unsupportedforces HTTP/3 (HTTP/3 transport not implemented yet)
insecuresupportedskips TLS certificate verification
ipv4supportedresolves hostnames to IPv4 addresses only
ipv6supportedresolves hostnames to IPv6 addresses only
keysupportedprivate key file matching --cert
limit-ratesupportedcaps the transfer rate in bytes per second
locationsupportedfollows HTTP redirects
location-trustedsupportedfollows redirects and forwards credentials to every host
max-redirssupportedmaximum number of redirects to follow, -1 for unlimited
max-timesupportedmaximum time allowed for the whole transfer
negotiateunsupporteduses SPNEGO (Negotiate) authentication (SPNEGO authentication not implemented (low conformance weight))
netrcsupportedreads credentials from ~/.netrc, failing if absent
netrc-filesupportedreads credentials from the given netrc-format file
netrc-optionalsupportedreads credentials from ~/.netrc if present, else the URL
ntlmunsupporteduses NTLM authentication (NTLM authentication not implemented (low conformance weight))
outputsupportedwrites the response body to a file instead of stdout
path-as-issupportedsends the URL path without normalizing /../ or /./
pinnedpubkeysupportedverifies the server's public key against pinned hashes
proxysupportedroutes the request through the given proxy
repeatsupportedrepeats this entry's request N times, -1 for infinite
resolvesupportedprovides a custom address for a HOST:PORT pair
retrysupportedmaximum retries on entry error, -1 for unlimited
retry-intervalsupporteddelay between retries
skipsupportedskips this entry without executing it
unix-socketsupportedconnects through a Unix domain socket instead of the network
usersupportedadds Basic authentication with USER:PASSWORD
variablesupporteddefines a variable local to this entry
verbosesupportedturns on verbose output for this entry
verbositysupportedsets the verbosity level (brief, verbose, debug) for this entry
very-verbosesupportedturns on very verbose output, including libcurl-style logs

Sonde extensions

Valid only in .sonde files (a .hurl file using one fails to parse). An entry with a sonde-stream-* option reads its body as Server-Sent Events. See guides/streaming.md, guides/grpc.md, decisions/0004-streaming-protocols.md and decisions/0005-grpc.md.

ConstructKindDescription
[SondeMessages]sectionmakes the entry a WebSocket exchange: ordered send, receive and close steps
[SondeGrpc]sectionmakes the entry a gRPC call of the method its URL path names (POST http://host/package.Service/Method), with a JSON request body; empty, the descriptors come from server reflection
proto[SondeGrpc] keya .proto file compiled at run time (repeatable)
import-path[SondeGrpc] keya directory where imports of proto files resolve (repeatable; default: each proto file's directory)
protoset[SondeGrpc] keya binary FileDescriptorSet, as written by protoc --descriptor_set_out --include_imports or buf build -o (repeatable)
send[SondeMessages] stepsends one message: JSON, a backtick or multiline string or XML as a text frame; base64, hex or file as a binary frame
receive[SondeMessages] stepwaits for the next message, or the next N with receive: N
close[SondeMessages] stepsends a close frame (1000, or close: CODE) and waits for the server's
sonde-stream-countoptionstops an event stream after N events
sonde-stream-max-bytesoptionstops a stream after N bytes (default 10485760); a WebSocket fails beyond it
sonde-stream-timeoutoptionstops an event stream after this time (default 10s); a WebSocket receive still waiting then fails
sondeStreamquerythe data of each event or message received, as a list; sondeStream "event", "id", "retry" (SSE) or "type" (WebSocket) select another field
sondeGrpcquerythe status name of a gRPC call (OK, NOT_FOUND…); sondeGrpc "code" is the status code and sondeGrpc "message" the status message. A status other than OK fails the entry unless the entry uses this query

CLI flags

Occurrence counts are measured across the vendored Hurl 8.0.1 conformance test scripts (testdata/conformance/hurl/**/*.sh).

FlagShortStatusPhaseHurl test usageDescription
--aws-sigv4unsupported4signs the request with AWS Signature Version 4 (stretch goal; not scheduled (low conformance weight))
--cacertsupported8CA certificate bundle used to verify the server (PEM)
--cert-Esupported1client certificate file, optionally with :PASSWORD
--colorsupported12forces colorized output
--compressedsupported3requests a compressed response and decodes it
--connect-timeoutsupported1maximum time allowed to establish the connection
--connect-tosupported3redirects connections for HOST1:PORT1 to HOST2:PORT2
--continue-on-errorsupported18keeps running remaining files after a failure
--cookie-bsupported1reads cookies from a Netscape-format FILE
--cookie-jar-csupported5writes cookies to FILE after the run
--curlsupported85exports each request as a list of curl commands
--delaysupported2sleep before each request
--digestunsupported1uses HTTP Digest authentication (HTTP Digest authentication not implemented (low conformance weight))
--error-formatsupported3controls how error messages are rendered (short or long)
--file-rootsupported5sets the root directory used to resolve file paths
--from-entrysupported2starts execution at the given entry number
--globsupported56adds input files matching the given glob pattern
--header-Hsupported7adds a custom header to every request
--http1.0-0unsupported1forces HTTP/1.0 (Go's net/http cannot send a literal HTTP/1.0 request (Request.Proto is ignored))
--http1.1supported1forces HTTP/1.1
--http2supported0forces HTTP/2
--http3unsupported1forces HTTP/3 (HTTP/3 transport not implemented yet)
--include-isupported6includes the response headers in the output
--insecure-ksupported1skips TLS certificate verification
--ipv4-4supported7resolves hostnames to IPv4 addresses only
--ipv6-6supported1resolves hostnames to IPv6 addresses only
--jobssupported513maximum number of parallel jobs, 1 disables parallelism
--jsonsupported15outputs each file's result as JSON
--keysupported1private key file matching --cert
--limit-ratesupported1caps the transfer rate in bytes per second
--location-Lsupported8follows HTTP redirects
--location-trustedsupported0follows redirects and forwards credentials to every host
--max-filesizesupported1caps the size of a downloaded file
--max-redirssupported3maximum number of redirects to follow, -1 for unlimited
--max-time-msupported4maximum time allowed for the whole transfer
--negotiateunsupported0uses SPNEGO (Negotiate) authentication (SPNEGO authentication not implemented (low conformance weight))
--netrc-nsupported0reads credentials from ~/.netrc, failing if absent
--netrc-filesupported1reads credentials from the given netrc-format file
--netrc-optionalsupported0reads credentials from ~/.netrc if present, else the URL
--no-assertsupported1ignores asserts defined in the file
--no-colorsupported8disables colorized output
--no-cookie-storesupported2disables the cookie store between requests
--no-outputsupported18suppresses the default last-response-body output
--no-prettysupported1disables pretty-printing of response output
--no-proxysupported0lists hosts that bypass the proxy
--ntlmunsupported1uses NTLM authentication (NTLM authentication not implemented (low conformance weight))
--output-osupported14writes to FILE instead of stdout
--parallelsupported512runs files in parallel (default in test mode)
--path-as-issupported1sends the URL path without normalizing /../ or /./
--pinnedpubkeysupported2verifies the server's public key against pinned hashes
--prettysupported4pretty-prints JSON response output
--progress-barsupported52shows a progress bar in test mode
--proxy-xsupported4routes the request through the given proxy
--repeatsupported4repeats the input file sequence N times, -1 for infinite
--report-htmlsupported56writes an HTML report to DIR
--report-jsonsupported55writes a JSON report to DIR
--report-junitsupported54writes a JUnit XML report to FILE
--report-tapsupported56writes a TAP report to FILE
--resolvesupported3provides a custom address for a HOST:PORT pair
--retrysupported2maximum retries on entry error, -1 for unlimited
--retry-intervalsupported2delay between retries
--secretsupported11defines a variable whose value is treated as a secret
--secrets-filesupported1defines secrets from a file
--ssl-no-revokeunsupported4(Windows) disables certificate revocation checks (Windows-specific certificate revocation control; no equivalent in Go's crypto/tls)
--testsupported520activates test mode (parallel execution, test-style output)
--to-entrysupported2stops execution at the given entry number
--unix-socketsupported1connects through a Unix domain socket instead of the network
--user-usupported4adds Basic authentication with USER:PASSWORD
--user-agent-Asupported1sets the User-Agent header sent to the server
--variablesupported16defines a variable
--variables-filesupported2defines variables from a properties file
--verbose-vsupported43turns on verbose output (alias of --verbosity verbose)
--verbositysupported2sets the verbosity level for debug logging
--very-verbosesupported6turns on very verbose output, including HTTP and libcurl-style logs

Environment variables

Occurrence counts are measured across the vendored Hurl 8.0.1 conformance test scripts (testdata/conformance/hurl/**/*.sh).

VariableStatusPhaseHurl test usageDescription
CIsupported4presence signals a CI environment (affects color/progress defaults)
HURL_COLORsupported5same as --color when set truthy, --no-color when falsy
HURL_COMPRESSEDsupported1same as --compressed
HURL_CONNECT_TIMEOUTsupported1same as --connect-timeout
HURL_CONTINUE_ON_ERRORsupported1same as --continue-on-error
HURL_DELAYsupported2same as --delay
HURL_ERROR_FORMATsupported1same as --error-format
HURL_HEADERsupported1adds one or more `
HURL_HTTP10unsupported1same as --http1.0 (mirrors --http1.0; Go's net/http cannot send a literal HTTP/1.0 request)
HURL_HTTP11supported1same as --http1.1
HURL_HTTP2supported0same as --http2
HURL_HTTP3unsupported0same as --http3 (HTTP/3 transport not implemented yet)
HURL_INSECUREsupported1same as --insecure
HURL_IPV4supported1same as --ipv4
HURL_IPV6supported1same as --ipv6
HURL_JOBSsupported51same as --jobs
HURL_LIMIT_RATEsupported1same as --limit-rate
HURL_LOCATIONsupported1same as --location
HURL_LOCATION_TRUSTEDsupported1same as --location-trusted
HURL_MAX_FILESIZEsupported1same as --max-filesize
HURL_MAX_REDIRSsupported2same as --max-redirs
HURL_MAX_TIMEsupported3same as --max-time
HURL_NO_ASSERTsupported1same as --no-assert
HURL_NO_COLORsupported6same as --no-color
HURL_NO_COOKIE_STOREsupported1same as --no-cookie-store
HURL_NO_OUTPUTsupported1same as --no-output
HURL_NO_PRETTYsupported0same as --no-pretty
HURL_PRETTYsupported1same as --pretty
HURL_RETRYsupported1same as --retry
HURL_RETRY_INTERVALsupported1same as --retry-interval
HURL_SECRET_namesupported3defines a secret variable named name from its value
HURL_TESTsupported51same as --test
HURL_USERsupported1same as --user
HURL_USER_AGENTsupported1same as --user-agent
HURL_VARIABLE_namesupported1defines a variable named name from its value
HURL_VERBOSEsupported4same as --verbose
HURL_VERBOSITYsupported4same as --verbosity
HURL_VERY_VERBOSEsupported2same as --very-verbose
NO_COLORsupported3disables colorized output when set to any value
TF_BUILDsupported0presence signals an Azure Pipelines CI environment
XDG_CONFIG_HOMEsupported16base directory used to locate the config file at $XDG_CONFIG_HOME/hurl/config

Config file

Hurl 8.0.1 reads $XDG_CONFIG_HOME/hurl/config (or $HOME/config/hurl/config as a fallback), a plain-text file of one --option[ value] per line.

KeyStatusPhaseDescription
headersupportedadds a custom header to every request
max-redirssupportedmaximum number of redirects to follow, -1 for unlimited
user-agentsupportedsets the User-Agent header sent to the server
verbosesupportedsame as --verbose
Edit on GitHubLast updated