Skip to main content

Module capture

Module capture 

Source
Expand description

Values a request pulls out of its response and hands to the requests after it.

A request file may carry a capture block: variable names mapped to a source to read from the response once it arrives. The default source, and originally the only one, is a JSON path evaluated against the response body — a bare string still means exactly that, for every file already written against it. Two more sources are read from a response’s envelope rather than its body: a named header, and the status code itself.

name: Log in
method: POST
url: https://api.example.com/login
capture:
  auth_token: $.token          # JSON path (default, bare string)
  user_id: $.user.id
  session_id:
    header: Set-Cookie          # a response header
  request_status:
    status: true                # the numeric status, as a string

§Header capture and repeated headers

Header names are matched case-insensitively, the way assertions matches them. A header that does not repeat captures its one value. A header that repeats (Set-Cookie is the common case) is ambiguous rather than resolved by taking the first or the last: this mirrors the JSON-path rule that a path selecting more than one value is a failure rather than a silent pick (see CaptureFailure::Ambiguous). An assertion checking headers: { set-cookie: ... } passes if any repeated value matches, because it is testing a predicate; a capture binds a name to one value that later requests will substitute, and guessing which repeat that should be would make the same file behave differently depending on header order a server happens to send in. A file that wants one specific cookie out of several should be more specific than header: Set-Cookie can be today — see the module-level non-goal note below.

§Only the final response’s headers

With follow_redirects on, header capture reads the headers of the response evaluate is called with — the final response in the chain. Response::redirects records each intermediate hop’s status and the Location it pointed at, but deliberately does not carry that hop’s full header set (see the type’s own docs), so there is no intermediate Set-Cookie or other header for this to reach even if the schema grew a way to ask for one. Capturing the final hop’s Location is possible today (a response that redirected already exposes its own Location if it is itself 3xx and redirects were disabled or exhausted), but reaching into an earlier hop is out of scope here: it would need RedirectHop extended to carry headers, which is a bigger, separate change. Documented as a non-goal rather than a partial hop: key that could only ever address the one field RedirectHop already has.

Every name captured this way becomes usable as {{auth_token}} in every request after this one, in file order, through the same substitution pass an environment file feeds. Nothing is written anywhere: a capture lives for the rest of one sendra run or sendra test invocation and no longer. A fresh process starts with nothing captured, which is the same non-goal environments shipped with.

§A capture is not a check

Captures::evaluate returns a CaptureReport and no Result, exactly as Assertions::evaluate does, and for the same reason: the response has already arrived, so there is nothing left to abort, and the only useful thing to do with a capture that did not work is to say precisely how it did not work, next to the ones that did.

But it is not an assertion either, and the difference decides how a front-end counts it. An assertion is an expectation about the response; a capture is a dependency of the rest of the run. So a capture that succeeds says nothing about whether the response was correct — a request that captured a token and asserted nothing was still not checked — while a capture that fails is a genuine failure, because a value the file promised to the requests downstream is not there. See CaptureReport::passed and the Summary type in sendra-cli for where that lands.

§Why the failures are typed rather than [SendraError]s

A [SendraError] means “this request could not be completed”, and every variant of it is raised on a path where there is no response: a file that does not parse, a {{var}} with nothing behind it, a refused connection, a pre_request script that threw. A capture failure is the opposite shape — the response arrived, was read, and did not contain what the file said it would — and folding it into that enum would have put it in the one category it is definitely not in.

Typing it as CaptureFailure instead also keeps the block’s entries independent: three captures against one response produce three results, the way three assertions do, rather than the first failure discarding whatever the other two would have found.

Structs§

CaptureReport
Every entry of one request’s capture block, evaluated against its response, in sorted-name order.
CaptureResult
One entry of a capture block, evaluated.
Captures
The capture block of a request, exactly as it appears on disk: variable name to CaptureSource.

Enums§

CaptureFailure
Why one entry of a capture block did not produce a value.
CaptureSource
Where one capture entry reads its value from.