Testing a gateway¶
api-test is built for the loop: change one thing on the gateway, hit api-test through it, observe the diff. This page documents the patterns each endpoint group makes possible.
The examples assume Plexara is reachable at
https://plexara.example.com, api-test is registered as a connection
named api-test, and the operator calls Plexara via an MCP client
(Claude Code, the SDK, raw JSON-RPC).
Identity forwarding¶
Question: did the gateway forward the right credential under the right transport?
api_invoke_endpoint(connection="api-test", method="GET", path="/v1/whoami")
→ { "subject": "...", "auth_type": "...", "key_name": "..." }
Assertion:
auth_typematches the connection's registeredauth_mode(apikey,bearer,oauth2).subjectis the credential name api-test recognizes (thenamefield of the matchingapi_keys.file/bearer.tokens/ the OIDCsubclaim).
Falsifies:
- Mis-registered connection (auth_mode doesn't match what the gateway is actually sending).
- Stale credential (gateway is still using a rotated value).
- Auth-mode confusion (a misconfigured
oauth2flow that falls back to a stale static token).
Header pass-through¶
Question: which headers did the gateway forward, and which did it strip or rewrite?
api_invoke_endpoint(connection="api-test", method="GET", path="/v1/headers",
headers={"X-Trace-Id": "abc", "X-Custom": "vendor"})
Assertion — open the api-test audit row:
request_headers["X-Trace-Id"] = ["abc"]if the gateway forwards.request_headers["X-Custom"] = ["vendor"]if the gateway forwards.request_headers["Authorization"]is not present in the row (the gateway should setAuthorizationfrom the connection's registered credential, not pass through caller-supplied headers that override it).
Falsifies:
- Header injection (gateway lets caller-supplied
Authorizationthrough and api-test sees it instead of the registered credential). - Header stripping (gateway drops a custom header you expected to forward).
Status code surfacing¶
Question: does the gateway pass through upstream HTTP statuses verbatim, or collapse them into tool-level errors?
api_invoke_endpoint(connection="api-test", method="GET", path="/v1/status/503")
api_invoke_endpoint(connection="api-test", method="GET", path="/v1/status/418")
api_invoke_endpoint(connection="api-test", method="GET", path="/v1/status/401")
Assertion:
- The gateway response envelope's
statusfield carries the upstream status (503, 418, 401). - The gateway does not mark the call as a tool-level error for upstream 4xx/5xx; that's an upstream HTTP response, not a transport failure.
Falsifies:
- Gateway collapses non-2xx to a tool error (loses information).
- Gateway maps 401 from upstream into "auth failed" at the gateway layer (misleading; the gateway's own auth is still fine).
Timeout enforcement¶
Question: does the gateway respect its own connect_timeout,
call_timeout, and per-call timeout_seconds?
api_invoke_endpoint(connection="api-test", method="GET", path="/v1/slow?ms=8000",
timeout_seconds=2)
Assertion:
- The gateway returns
error: "timeout"(or equivalent) within ~2s. - api-test's audit row shows status 499 with
cancelled: true(the gateway propagated the cancellation).
Falsifies:
- Gateway ignores
timeout_seconds(waits the full 8s). - Gateway times out but doesn't propagate cancellation (api-test finishes its 8s sleep and writes a 200 row anyway).
Retry policy¶
Question: when does the gateway retry, and how many times?
api_invoke_endpoint(connection="api-test", method="GET",
path="/v1/flaky?fail_rate=1&seed=demo&call_id=1")
Assertion — count audit rows for path = "/v1/flaky":
- One row → no retry (gateway surfaces the failure immediately).
- N rows → gateway retried N-1 times.
Falsifies:
- Gateway retries on 503 when policy says it shouldn't.
- Gateway gives up after the wrong number of attempts.
Redaction¶
Question: did the gateway log the credential anywhere?
Open the api-test audit drawer for a recent call. Confirm:
request_headers["Authorization"](or the gateway's chosen header) shows[redacted], not the real value.response_bodydoesn't accidentally echo the credential back from somewhere upstream.
Then check Plexara's own audit log for the same call. The credential
should be [redacted] there too. If it's plaintext on either side,
the redaction policy isn't covering that key.
Pagination detection¶
Question: did the gateway recognize the upstream's pagination cursor?
api-test exposes one endpoint per cursor style the gateway's pagination detector recognizes:
/v1/pagination/link— RFC 5988Link: <…>; rel="next"(alsofirst,prev,last). Paged with?page=&per_page=./v1/pagination/odata— OData v4 body field@odata.nextLinkplus@odata.count. Paged with?$top=&$skip=./v1/pagination/cursor— opaque base64 cursor in body fieldnext_cursor. Paged with?cursor=&limit=.
All three slice the same deterministic synthetic dataset
(hex(sha256(id)[:8])), so the items returned for page 2 of the Link
endpoint should bit-match the items returned by walking the OData or
cursor endpoint to the same offset. See the
Pagination endpoint reference for the
full parameter table.
Assertion: gateway response envelope's pagination field:
- For each style, the cursor / next-page value should match what api-test put on the wire (no host rewrite, no re-encoding).
- Item bodies for the same
idare byte-equal across all three styles. - Requesting past the last page returns 400 from api-test; the gateway should surface that, not collapse it into a tool-level error.
Snapshot fixtures¶
For deterministic regression suites, use the data group:
api_invoke_endpoint(connection="api-test", method="GET", path="/v1/fixed/regression-key-42")
api_invoke_endpoint(connection="api-test", method="GET", path="/v1/lorem?words=20&seed=test")
api_invoke_endpoint(connection="api-test", method="GET", path="/v1/sized?bytes=1024")
These bodies never change. Snapshot once; assert byte-equal forever.
What lives where¶
| Concern | Where to look |
|---|---|
| What the client called Plexara with | Plexara's MCP audit log. |
| What Plexara forwarded to api-test | api-test's audit_events + audit_payloads rows. |
| What api-test sent back | Same payload row, response side. |
| What the client got back from Plexara | Plexara's MCP audit log, response section. |
The diff between "what the client sent" and "what api-test received" is the gateway's contribution to the call. The diff between "what api-test sent back" and "what the client got" is the gateway's contribution to the response. Both directions are observable.