{# What came back — the panel the console swaps after a call. It renders empty when there is no result, because the operation page includes it as the placeholder the reply replaces. An `{% if %}` here rather than two templates: the id has to exist in the document before the first call, and an empty div carrying it is cheaper than a second file that renders one. #} {% from "apidocs/macros.html" import facts %} {% from "ui/data.html" import badge, card, code_block %} {% from "ui/icon.html" import icon %} {% from "ui/layout.html" import stack %}
{% if result %} {# The badge follows the status, not the error, because the two are not alternatives. Starlette's ServerErrorMiddleware sends its 500 and then re-raises, so a handler that blew up leaves both a real response and an escaped exception. Reading `result.error` first printed "no response" over a reply that was sitting right there — the worst thing a debugging tool can do, which is to assert something false about what happened. "no response" now means what it says: a timeout, or an exception that escaped before a single byte was sent. #} {%- set status %} {% if result.status %} {{ badge(result.status ~ (" " ~ result.reason if result.reason else ""), result.tone) }} {% else %} {{ badge("no response", "destructive") }} {% endif %} {%- endset %} {# `aria-live="polite"` on the wrapper, not on the panel: the panel is what gets replaced, and a screen reader stops watching a live region that is itself swapped out. Polite rather than assertive because the person pressed the button — they are waiting for this, not being interrupted by it. #}
{% call card("Response", result.method ~ " " ~ result.url, actions=status) %} {% call stack(gap=4) %} {% if result.error %} {# Where the rest of it is. An in-process replay has no server above it to log what escaped, so the console logs it itself, and saying so here is the difference between a one-line error and knowing there is a stack to go and read. Without this line the indirection is the liability it looks like. #}

The traceback is in this app's log, under fjkit_apidocs.console.

{% endif %} {% if result.status %} {{ facts([ ("time", "%.0f ms" | format(result.elapsed_ms)), ("content type", result.media_type or "—"), ]) }} {% if result.body %} {{ code_block(result.pretty, label="Response body") }} {% if result.truncated %}

Truncated. The body was larger than this console will hold — call it with curl for the rest.

{% endif %} {% else %}

Empty body.

{% endif %} {% if result.headers %} {{ code_block(result.headers | map("join", ": ") | join("\n"), label="Response headers") }} {% endif %} {% endif %} {% if curl %} {# The same call as a command. Credentials are placeholders, not values: a snippet built for copying ends up in a bug report, and the point of this plugin is that the session cookie is not readable from the page. #} {{ code_block(curl, label="The same call with curl", wrap=true) }} {% endif %} {% endcall %} {% endcall %}
{% endif %}