Skip to content

API Reference

Three names are defined in every script, with no imports needed:

NameWhat it is
requestThe request being sent. A pre-request script may change it.
responseThe response, in post-request scripts. None in pre-request scripts.
chaparThe environment, tests, logging and skipping. import chapar works too.

The Python standard library is available (json, hashlib, hmac, base64, datetime, uuid, re, …), as is the requests package.

request

AttributeHTTPgRPCGraphQL
request.protocol"http""grpc""graphql"
request.urlThe URLThe server address, host:portThe endpoint URL
request.methodGET, POST, …The full method, package.Service/MethodPOST
request.headersHeaders, as PairsThe metadata, as Pairs (also request.metadata)Headers
request.bodyThe body, as textThe JSON message, as text—
request.queryQuery params, as Pairs (case-sensitive)——
request.path_paramsThe {name} path params, as a dict——
request.graphqlNoneNone.query (the document) and .variables (a dict when valid JSON)
request.resolvedThe same request with {{variables}} filled in, read-only
MethodDoes
request.json()Parses the body as JSON. For GraphQL, returns {"query": …, "variables": …}.
request.set_json(obj)Replaces the body with obj encoded as JSON (HTTP and gRPC).

The fields keep their {{variables}}: Chapar fills them in after the pre-request script runs, so a value you set can itself contain {{variables}}. Read request.resolved (.url, .headers, .body, .query, .graphql, .json()) when you need the final values, for example to sign exactly what will be sent.

In a pre-request script, every change to url, method, headers, body, query, path_params and graphql is applied to the request that is sent. The saved request doesn’t change. In a post-request script, request is read-only information about what was sent.

request.headers["X-Request-Id"] = chapar.env.get("requestId", "")
request.query["page"] = "2"
body = request.json()
body["sentAt"] = "{{timeNow}}"        # filled in after the script
request.set_json(body)

response

Available in post-request scripts.

AttributeMeaning
response.protocol"http", "grpc" or "graphql"
response.status_codeThe HTTP status code. For gRPC, the gRPC status code (0 is OK, 5 is NOT_FOUND, …).
response.statusThe status text, for example "200 OK", or the gRPC code name, for example "OK".
response.okTrue for a 2xx status, or gRPC code 0, when the request didn’t fail.
response.headersThe response headers, as Pairs.
response.text, response.bodyThe body as text. For gRPC, the JSON response message.
response.elapsed_msHow long the request took, in milliseconds.
response.sizeThe body size in bytes.
response.errorWhy the request failed, or None.
response.cookiesThe cookies the response set: a list of objects with name, value, domain, path, expires, secure and http_only.
response.metadatagRPC: the response metadata (headers), as Pairs.
response.trailersgRPC: the trailers, as Pairs.
response.dataGraphQL: the data field of the body.
response.errorsGraphQL: the errors field of the body, or None.
MethodDoes
response.json()Parses the body as JSON. Raises ValueError with a clear message when the body is empty or not JSON.
response.cookie(name, default=None)The value of the cookie name that the response set.

chapar

Environment

chapar.env is the active environment.

CallDoes
chapar.env.get(key, default=None)The value of a variable, as a string, or default.
chapar.env.set(key, value)Sets a variable. Strings are stored as they are; numbers, booleans, lists and dicts are stored as JSON text.
chapar.env.unset(key)Removes a variable.
chapar.env.all()Every variable, as a dict.
chapar.env.nameThe environment’s name.
chapar.env[key], chapar.env[key] = v, del chapar.env[key], key in chapar.envDict-style access.
chapar.get_env(k, d), chapar.set_env(k, v), chapar.unset_env(k)Shorthands.

Changes are saved to the environment after the script finishes, in pre-request and post-request scripts alike. The request that is being sent already sees values a pre-request script set.

Select an environment before sending. With No Environment, there is nowhere to save values, and chapar.env.set has no lasting effect.

Tests

chapar.test(name, fn) runs fn and records whether it passed. A test fails when fn raises, typically through assert. It returns True or False. Use it as a decorator to write the test inline:

@chapar.test("status is 201")
def _():
    assert response.status_code == 201, response.status

@chapar.test("returns the new id")
def _():
    assert response.json()["data"]["id"]

chapar.test("is fast", lambda: response.elapsed_ms < 500)

A failing test doesn’t stop the script. Results appear in the timeline as ✓ name or ✗ name: reason, and the step is marked failed when any test fails.

Logging

chapar.log(*args, sep=" ") and print(...) write to the script’s output, shown in the timeline. Output is capped at 256 KB per run.

Skipping a request

chapar.skip(reason=""), in a pre-request script, stops the script and cancels the send. The response pane shows the pre-request script skipped this request: reason. Calling it in a post-request script raises an error.

if not chapar.env.get("token"):
    chapar.skip("log in first: send the Login request")

Context

NameValue
chapar.phase"pre" or "post"
chapar.protocol"http", "grpc" or "graphql"
chapar.request, chapar.responseThe same objects as request and response
chapar.on_responseIn a post-request script, set it to a function; it is called with response after the script’s body runs.

Pairs

Headers, gRPC metadata and trailers, and query params are Pairs: ordered key/value lists that read like a dict but can hold a key more than once. Header and metadata keys match case-insensitively; query keys are case-sensitive.

CallDoes
p[key]The first value; KeyError if missing.
p.get(key, default=None)The first value, or default.
p.get_all(key)Every value of key, as a list.
p[key] = value, p.set(key, value)Replaces every value of key with one value.
p.add(key, value)Appends another value for key.
del p[key], p.remove(key)Removes every value of key (remove ignores a missing key).
key in p, len(p), for key in pMembership, count and iteration over the keys.
p.keys(), p.values(), p.items(), p.pairs()Lists; pairs() includes duplicates in order.
p.to_dict()A plain dict.
request.headers.add("Accept", "application/json")
request.headers.add("Accept", "text/plain")
request.headers.get_all("accept")      # ['application/json', 'text/plain']
request.headers.remove("X-Debug")

Limits

LimitValue
Run time per script10 seconds
Output per run256 KB
Memory for the executor512 MB
Writable disk/tmp, 64 MB
Python version3.11

Each run happens in a new process: variables, imports and files from one run are gone in the next. Keep state in the environment.