Assertion DSL

Assertions are lines starting with ?? placed after a request. They replace scripting blocks: nothing is evaluated except this small grammar, so a .http file from a pull request cannot run code.

?? <subject> <operator> [value]

A request passes when it got a response and every assertion holds. A 4xx or 5xx status is not a failure by itself; assert on status if you care. A transport error (connection refused, timeout) fails the request. Assertions are checked in order and all are reported, not just the first failure.

Subjects

Subject Value
status HTTP status code (number).
duration Elapsed milliseconds for the final attempt (number).
size Body size in bytes (number).
header NAME Header value, case-insensitive name. Repeated headers are joined with ,. headers.NAME also works.
body Body as text.
body.$.path JSONPath into the parsed body (see the subset in file-format.md). Wildcard and .. paths yield a list.
body schema ./file.json Validate the JSON body against a JSON Schema (draft 2020-12). Path is relative to the .http file.

Operators

Operator Meaning
== != Equality. Numbers compare numerically, also against numeric strings (header content-length == 12).
< <= > >= Numeric comparison; a non-numeric operand fails with an explanation.
contains / !contains Substring for strings; membership for arrays; key for objects. not contains is accepted too.
startswith endswith String prefix and suffix.
matches /re/flags / !matches Python regex search. Flags: i m s x.
exists / !exists Whether the header or JSON path is present. A JSON null exists.

Values

A value is a JSON literal (200, true, null, "quoted"), a single- or double-quoted string, or the rest of the line as a bare string (?? body.$.name == Ada). Everything after the operator is the value, so bare strings may contain spaces. {{variables}} and response references are interpolated before the assertion is parsed, which allows ?? body.$.id == {{create.response.body.$.id}}.

Examples

?? status == 200
?? duration < 500
?? header content-type contains json
?? body.$.items.length > 0
?? body.$.items[*].id contains 3
?? body.$..title contains "Seed note 1"
?? body.$.token matches /^[0-9a-f]{32}$/
?? body.$.error !exists
?? body matches /"ok":\s*true/i
?? body schema ./schemas/user.json

Errors

Syntax errors are reported at parse time with the file and line (file.http:12: expected an operator ...), before any request is sent. A failed assertion reports what was found: fail status == 201 (line 4) (got 200); a schema failure reports the first violating location: schema violation at $['n']: 5 is not of type 'string'.