Skip to main content

Post-Request Hooks

A post-request hook is a lightweight script written in Rhai that Rumour runs immediately after receiving the HTTP response — but before assertions are checked, variables are extracted, or execution moves to the next step. It lets you inspect response metadata and payload content to perform complex validations or inject downstream variables dynamically.

Common Use Cases

  • Downstream Variable Injection: Parsing tokens or values from responses and formatting them for upcoming API calls.
  • Response Customization & Audits: Validating payload structure or inspecting headers programmatically.
  • Logging & Observability: Printing response statistics or fields to the terminal for debugging purposes.
  • Custom Control Flow: Halting the test workflow programmatically using throw if critical business logic invariants are violated.

How It Works

To associate a post-request hook with your HTTP request, configure the post_request key inside your .toml request file. Rumour supports two placements for this key:

Option A: At the Root Level

You can define post_request directly at the root of the file:

name = "get_user_profile"
post_request = "my_script.rhai"

[request]
method = "GET"
url = "{{base_url}}/users/1"

Option B: Within the [request] Block

Alternatively, you can place it inside the [request] table alongside request properties like method and url:

name = "get_user_profile"

[request]
method = "GET"
url = "{{base_url}}/users/1"
post_request = "my_script.rhai"
tip

Rumour checks for the hook at the root level first. If not defined there, it falls back to checking inside the [request] block.

File Location & Path Resolution

Rumour resolves the script path relative to the directory containing the request TOML file. This means you can keep scripts in sub-folders or parent folders by using relative paths:

  • In the same folder: post_request = "my_script.rhai"
  • In a sub-folder: post_request = "scripts/my_script.rhai"
  • In a parent/sibling folder: post_request = "../shared/logger.rhai"

This allows you to organize and reuse scripts across multiple requests in your collection:

scripting_examples/
├── shared/
│ └── logger.rhai
└── users/
├── workspace.env.toml
└── get_user.toml # Configured with: post_request = "../shared/logger.rhai"

Available Variables in the Script

When your post-request script runs, Rumour exposes the following objects to the script scope:

ObjectTypeAccessDescription
varsMapRead/WriteAll runtime variables — modifications persist for downstream requests
statusIntegerRead-OnlyHTTP response status code (e.g. 200, 201, 404)
res_headersMapRead-OnlyKey/value map of all headers received in the response
res_bodyStringRead-OnlyThe raw response body payload
note

Unlike the pre-request hook, you cannot modify res_headers or res_body here — these are the actual server response and are already captured. Only the vars object is writable.

Logging

You can call log("message") from any script to print a labeled message to the terminal during the run:

[SCRIPT] your message here

Example 1: Basic Response Verification & Extraction

Goal

After fetching a user, inspect the HTTP status code and store a flag variable (user_fetched) for downstream request steps to consume.

File Layout

scripting_examples/post_request/
├── workspace.env.toml
├── get_user.toml
└── check_status.rhai

File Contents

workspace.env.toml

# workspace.env.toml
base_url = "http://localhost:4000/api/v2"

get_user.toml

# get_user.toml
name = "post_hook_get_user"

[request]
method = "GET"
url = "{{base_url}}/users/1"
post_request = "check_status.rhai"

[assert]
status = 200

check_status.rhai

// check_status.rhai
log("Post-request: checking response status");

if status == 200 {
log("Response OK - storing custom derived variable");
vars["user_fetched"] = "true";
} else {
log("Unexpected status: " + status.to_string());
vars["user_fetched"] = "false";
}

Running the Example

Execute the request in verbose mode:

rumour run ./scripting_examples/post_request/get_user.toml -tv

Output Trace

GET http://localhost:4000/api/v2/users/1
URL: http://localhost:4000/api/v2/users/1
[SCRIPT] Post-request: checking response status
[SCRIPT] Response OK - storing custom derived variable
✓ SUCCESS: /home/bugsfounder/workspace/testing/scripting_examples/post_request/get_user.toml (2ms)
✓ ./scripting_examples/post_request/get_user.toml → PASS (1 Pass, 0 Fail, 0 Skip)
╭──────────────────────────────────────────────────────────────────────────╮
│ RUMOUR EXECUTION REPORT │
├──────────────────────────────────────────────────────────────────────────┤
│ Total Requests: 1
│ Successful: 1
│ Failed: 0
│ Skipped: 0
│ Success Rate: 100.0% │
│ Total Time: 6ms │
╰──────────────────────────────────────────────────────────────────────────╯

✓ Successful Requests:
- /home/bugsfounder/workspace/testing/scripting_examples/post_request/get_user.toml [200] [6ms]

Understanding the Output

The [SCRIPT] log lines show that the post-request script executed after the server responded. Because the status code was 200, the script set the variable user_fetched to "true". Subsequent requests in this workflow can now access this value using {{user_fetched}}.

Example 2: Advanced Response Inspection & Dynamic Extraction

Goal

Assert the response status programmatically, inspect response header keys, scan the raw response body for content, and inject downstream variables dynamically.

File Layout

scripting_examples/post_request/
├── workspace.env.toml
├── advanced_validation.toml
└── advanced_validation.rhai

File Contents

advanced_validation.toml

# advanced_validation.toml
name = "post_hook_advanced_validation"

[request]
method = "GET"
url = "{{base_url}}/users"
post_request = "advanced_validation.rhai"

[assert]
status = 200

advanced_validation.rhai

// advanced_validation.rhai
log("Advanced Post-request hook execution started.");

// 1. Assert status code programmatically
if status != 200 {
throw "Request failed with status code: " + status.to_string();
}

// 2. Inspect response headers (keys are normalized to lowercase)
let contentType = res_headers["content-type"];
log("Response Content-Type: " + contentType);

// 3. Inspect body content
if res_body.contains("dev_lead") {
log("Verified: Target user dev_lead found in response body.");
vars["extracted_username"] = "dev_lead";
vars["extracted_role"] = "lead";
} else {
log("Target user dev_lead not found in response.");
vars["extracted_username"] = "unknown";
}

log("Derived downstream variables: extracted_username=" + vars["extracted_username"]);

Running the Example

Execute the request in verbose mode:

rumour run ./scripting_examples/post_request/advanced_validation.toml -tv

Output Trace

GET http://localhost:4000/api/v2/users
URL: http://localhost:4000/api/v2/users
[SCRIPT] Advanced Post-request hook execution started.
[SCRIPT] Response Content-Type: application/json; charset=utf-8
[SCRIPT] Verified: Target user dev_lead found in response body.
[SCRIPT] Derived downstream variables: extracted_username=dev_lead
✓ SUCCESS: /home/bugsfounder/workspace/testing/scripting_examples/post_request/advanced_validation.toml (2ms)
✓ ./scripting_examples/post_request/advanced_validation.toml → PASS (1 Pass, 0 Fail, 0 Skip)
╭──────────────────────────────────────────────────────────────────────────╮
│ RUMOUR EXECUTION REPORT │
├──────────────────────────────────────────────────────────────────────────┤
│ Total Requests: 1
│ Successful: 1
│ Failed: 0
│ Skipped: 0
│ Success Rate: 100.0% │
│ Total Time: 9ms │
╰──────────────────────────────────────────────────────────────────────────╯

✓ Successful Requests:
- /home/bugsfounder/workspace/testing/scripting_examples/post_request/advanced_validation.toml [200] [9ms]

Understanding the Output

  1. The script started immediately after receiving response data.
  2. It extracted res_headers["content-type"] (which resolved to application/json; charset=utf-8).
  3. It scanned the payload res_body for the substring "dev_lead". Finding it, the script successfully stored extracted_username = "dev_lead" and extracted_role = "lead" in vars for use in subsequent requests.

Script Errors

If your script contains a syntax error or a runtime exception, Rumour halts execution of that request, marks the request result as failed, and skips any downstream dependent requests. The failure reason is printed in the execution report:

Reason: Script error: Script error in /absolute/path/to/check_status.rhai: Variable not found: typo_var (line 5, position 1)

Understanding the Error Output

When a script error occurs:

  1. Request Marked as Failed: Rumour halts and marks the request status as failed, even if the HTTP status code matched assertions.
  2. Error Details: It pinpoints the absolute path of the script, the exact error message (Variable not found: typo_var), and the precise line/column number (line 5, position 1) where the problem occurred to help you debug quickly.