--- name: mock-response description: >- Build a shareable mock HTTP response URL using the Secutils.dev echo tool — given a status code, headers, body, and optional description, encode the state and emit https://x.secutils.dev/echo#{encoded} (configurator) or https://x.secutils.dev/echo?c={encoded} (served mock). Trigger when the user asks for a "mock response", "echo URL", "fake HTTP response", "test response URL", or anything that names secutils.dev/echo. --- # Mock response (Secutils.dev echo) Produce a URL that opens (or serves, with `?c=`) a mock HTTP response on the Secutils.dev echo responder. State is round-tripped through the URL itself; no account or API call is involved. ## Inputs | Field | Type | Default | Notes | |---------------|----------------------------|------------------------|--------------------------------------------------------------------------------------| | `description` | string | `""` | Free-text label, kept in URL, **not** sent to clients. | | `status` | int 100–599 | `200` | Clamp out-of-range values. | | `headers` | array of `[name, value]` | `[]` | Drop entries with empty `name`. Responder auto-adds `Content-Type: text/plain; charset=utf-8` if no Content-Type is set. | | `body` | string | `""` | Pass-through. Do **not** JSON-stringify the user's body — they want literal bytes. | State object shape (keys are exactly `d`, `s`, `h`, `b`, in that order): ```json {"d":"","s":,"h":[["Header","Value"], ...],"b":""} ``` ## Wire format After URL-safe base64 decoding: ``` | 4 bytes uncompressed-length (LE u32) | N bytes raw DEFLATE of UTF-8 JSON | ``` Pipeline: `JSON.stringify(state)` → UTF-8 bytes → `deflate-raw` → prepend the 4-byte LE u32 of the **uncompressed** length → base64url (`+`→`-`, `/`→`_`, strip `=`). ## How to produce the URL Run this on any machine with Node ≥ 18 (no deps): ```bash node -e ' const zlib = require("node:zlib"); const state = JSON.parse(process.argv[1]); const utf8 = Buffer.from(JSON.stringify(state), "utf8"); const out = Buffer.concat([Buffer.alloc(4), zlib.deflateRawSync(utf8)]); out.writeUInt32LE(utf8.length, 0); const enc = out.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,""); console.log("https://x.secutils.dev/echo#" + enc); ' '{"d":"my desc","s":200,"h":[["Content-Type","text/html; charset=utf-8"]],"b":"Hello!"}' ``` Pass the state as the first argv (single-quoted JSON) so embedded quotes, newlines, and shell metacharacters survive untouched. **Always print the full URL** — the fragment is opaque and dropping a single character breaks decoding. For the served-mock URL (responder inflates and replays), swap `#` for `?c=` — same encoded blob. ## Producing the URL inline (no Node available) The encoding is small enough to do in any language with a deflate library — Python (`zlib.compress(..., wbits=-15)`), Rust (`flate2::write::DeflateEncoder`), etc. Identical wire format. The byte-exact compressed output varies across deflate implementations; that's fine — the responder uses tiny-inflate, which accepts any valid raw-deflate stream. ## After producing Hand the URL back verbatim in a fenced block or inline code so the user can copy it cleanly. One sentence summary at most. Don't paraphrase the body or abbreviate the fragment. ## Caveats - `description` is for humans reading the share link — never include secrets; the fragment is visible to anyone with the URL (though never sent to the server when used with `#`, only with `?c=`). - For HTML/JSON bodies, **set Content-Type explicitly** — the auto-injected default is `text/plain; charset=utf-8`. - `?c=` shape is for the served mock and the fragment is browser-side only; use `#` when the user wants to land on the configurator UI with state pre-filled.