Request inspector
The inspector records recent requests so you can see what actually reached the
upstream after the gateway rewrote, enriched or stripped it. It captures every
request except the control plane (/_rustybin/*), the web console (/ui/*), the
landing page (/) and /favicon.ico.
Each entry has: an inspector id, the request_id (X-Request-Id), timestamp,
method, URI, path, query, HTTP version, every header, client IP, the
X-Rustybin-Session value, the body (up to 64 KiB; UTF-8 as body, anything else
as body_base64, with body_size and body_truncated), the response status and the
time to response headers in latency_ms.
Entries live in a ring buffer of RUSTYBIN_INSPECTOR_CAPACITY entries (default 500,
at most 10000); the oldest entry is evicted first.
Tag, list, fetch
Tag your traffic with X-Rustybin-Session (1 to 128 characters of A-Z a-z 0-9 . _ : -)
to find it again among everyone else's:
POST {{base_url}}/anything/checkout?step=1
X-Rustybin-Session: docs-inspector
X-Request-Id: docs-inspector-0001
Content-Type: application/json
{"cart": 42}
HTTP 200
GET /_rustybin/requests lists entries newest first. Filters: ?session=,
?path_prefix=, ?limit= (default 100, capped at the capacity).
GET {{base_url}}/_rustybin/requests?session=docs-inspector&limit=10
HTTP 200
[Captures]
entry_id: jsonpath "$.requests[0].id"
[Asserts]
jsonpath "$.public_mode" == false
jsonpath "$.requests[0].method" == "POST"
jsonpath "$.requests[0].path" == "/anything/checkout"
jsonpath "$.requests[0].query" == "step=1"
jsonpath "$.requests[0].request_id" == "docs-inspector-0001"
jsonpath "$.requests[0].session" == "docs-inspector"
jsonpath "$.requests[0].body" == "{\"cart\": 42}"
jsonpath "$.requests[0].status" == 200
jsonpath "$.requests[0].latency_ms" exists
GET {{base_url}}/_rustybin/requests/{{entry_id}}
HTTP 200
[Asserts]
jsonpath "$.id" == "{{entry_id}}"
jsonpath "$.headers[?(@.name == 'x-rustybin-session')].value" nth 0 == "docs-inspector"
GET {{base_url}}/_rustybin/requests?path_prefix=/anything/checkout&limit=1
HTTP 200
[Asserts]
jsonpath "$.count" == 1
Live feed
GET /_rustybin/requests/stream is a Server-Sent Events feed with one request
event per captured request (the event id is the inspector id, the data the full
entry as JSON). It accepts the same filters as the list and sends keep-alive
comments while idle:
curl -sN --max-time 2 "$BASE/_rustybin/requests/stream?session=docs-feed"
The feed never ends on its own (the example stops reading after two seconds); the web console uses it for its live traffic view.
Clearing
DELETE /_rustybin/requests?session=<id> removes one session's entries and needs
no credentials. Without ?session= it clears everything, which is an
instance-global mutation guarded by the admin token:
DELETE {{base_url}}/_rustybin/requests?session=docs-inspector
HTTP 200
[Asserts]
jsonpath "$.session" == "docs-inspector"
jsonpath "$.cleared" >= 1
# Clearing everything is a global mutation: it needs the admin token when one is configured.
DELETE {{base_url}}/_rustybin/requests
HTTP 401
DELETE {{base_url}}/_rustybin/requests
X-Rustybin-Admin-Token: {{admin_token}}
HTTP 200
[Asserts]
jsonpath "$.cleared" exists
Public mode
With RUSTYBIN_PUBLIC_MODE=true only requests carrying X-Rustybin-Session are
captured, the list and the live feed require ?session= (400 otherwise) and only
return that session's entries, and GET /_rustybin/requests/{id} only answers when
?session= names the session the entry belongs to.
Related
- The AI request inspector
(
/ai/requests/{id}) shows what the mock LLM made of a request (normalised prompt, token counts, redacted credentials) and links to the inspector entry. - A request bin gives a webhook sender or a logging plugin its own URL and history.