Changelog

Technical changes shipped to Quickmock — features, fixes, security hardening. Source-of-truth is the git history; this page is the curated developer-facing view.

2026-10-17 — Abuse hardening

Security

  • Header values with control characters are rejected. A mock header value containing a line break or another control character (an attempt to smuggle an extra header) now fails validation with a clear error everywhere headers are set — response headers, variants, routes, sequence steps and the error response. Such values were already neutralised on the wire.
  • Mocks that impersonate an LLM API to make an AI agent run shell commands are blocked. The anti-spam filter now rejects tool calls to shell-execution tools (OpenAI tool_calls / function_call, Anthropic tool_use) and sandbox network reconnaissance. Ordinary tool-call mocks such as get_weather keep working.

2026-10-02 — Leaner internals; clearing logs resets the counter

Changed

  • robots.txt is one rule group instead of the same rules repeated for 23 named crawlers — every bot, AI crawlers included, still gets exactly the same access. The guide and template lists in llms.txt are now generated from the same registry as the pages and the sitemap, so they can no longer drift out of date.
  • The cross-site guard on mock creation now uses Go’s built-in CSRF protection. Browser requests from another site — including a sibling subdomain — are rejected; curl, CI and other non-browser clients are unaffected. The language switcher endpoint accepts only its own form, no longer a JSON body.
  • Internal clean-up: about 700 lines of hand-rolled code were replaced by the Go standard library and the database driver — no change to the API or to how mocks behave.

Fixed

  • Clearing a mock’s logs now also resets its request counter. Before, the log list emptied but the summary kept showing the old request count and last-request time.
  • GET /api/mocks/:id/logs returns "logs": [] for a mock with no captured requests, instead of null.
  • The live request inspector streams from the first visit. On a private mock the page opened its live connection before the inspector session existed, got refused and quietly fell back to re-asking the server every 2 seconds; it now connects once the session is ready, and a locked inspector no longer polls at all. “Clear logs” also refreshes the list at once, and the page no longer logs an htmx error on every load.

2026-09-26 — No payment requests; inspector polling fix

Security

  • Quickmock no longer hosts x402 payment requests on real networks. A mock can't verify a payment, so a 402 reply asking for real stablecoins was a trap for any agent that paid it — and someone had started listing such mocks in an x402 discovery catalog. Creating or editing a mock that carries an x402 payment requirement on a mainnet (Base, Ethereum, Solana…) now fails with 422 payment_blocked. x402 on testnets such as base-sepolia stays allowed, and so does a plain 402 status.

Fixed

  • An inspector tab left open on a deleted or expired mock no longer polls forever. The request list and the summary counter re-requested the server every 2–5 seconds and got a 404 that the page silently ignored — one forgotten tab made over two thousand requests in a few days. The server now tells the page to stop polling, and the page says the mock is gone.

2026-09-20 — Trustworthy client IPs

Security

  • The origin now accepts web traffic from Cloudflare only, at two independent layers: a firewall allow-list of Cloudflare's published ranges, refreshed weekly by a timer, and Authenticated Origin Pulls, where the web server demands Cloudflare's TLS client certificate. This is what makes the visitor's address trustworthy — Cloudflare overwrites the header carrying it, but only for traffic that actually goes through Cloudflare. Until the direct path was closed, anyone who found the origin could connect to it and claim to be any IP at all.

Fixed

  • The per-IP cap on active mocks, the rate limit and the operator blocklist were all keying on an internal address rather than the visitor's, which collapsed three per-IP controls into a single global bucket: a blocklist that matched nobody, and one caller able to spend everyone's quota. Request logs showed the same useless address. All of it now resolves to the real client IP.
  • Commands inside a guide's long-form sections rendered as plain paragraph text — no code styling, no copy button — even though they are exactly the lines a reader is meant to type. They now look like every other code block on the page and carry the same one-click copy.

Added

  • The scripts and the full write-up for this are in the repository under deploy/cloudflare/ — why each layer is needed, the order that avoids taking a site down, how the weekly sync fails safe, and the pitfalls worth knowing if you run something behind a CDN yourself.

2026-09-19 — Status filtering and new locales

Added

  • Status Filter: The request inspector now captures the actually-served HTTP status for each request, and allows filtering the log view by status code. Log exports include the new field.
  • Locales: Added full translations for Spanish, Portuguese, and Simplified Chinese, making Quickmock accessible to a broader global audience based on traffic trends.
  • Public API and CLI: go install .../cmd/quickmock@latest gives you a quickmock create command that prints a mock's public URL and its one-time admin token, so a CI job can get a throwaway endpoint without a browser. The new Public API and CLI guide covers installation, the flags, and the curl equivalent for pipelines that would rather not install anything.

Fixed

  • Status filtering shipped with three rough edges, now sanded down: the status badge had no colours defined, so a 500 looked exactly like a 200; a status outside the dropdown's shortlist left the control reading all statuses above a list that was in fact filtered; and ?status= on the log export silently ignored garbage instead of answering 422 the way ?method= already did.
  • Self-hosting: the response_status column added for this release was nullable, which made every log read fail on requests captured before the upgrade. It is now NOT NULL DEFAULT 0, and a follow-up migration repairs an instance that already applied the first version.

2026-09-18 — Response bodies that can reference themselves

Added

  • New {{mock.url}} token expands to the mock's own base URL — https://quickmock.dev/m/<slug> — so a response body can point at itself. That was impossible before: the slug only exists once the mock is created, and a template author has no way to write it in advance.
  • New {{request.host}} echo token returns the Host the request was addressed to. Go keeps that value outside the header map, so {{request.header.host}} could never stand in for it.

Changed

2026-09-08 — Long-form guides and template depth

Added

  • Three guides — mock a REST API endpoint, test a webhook receiver and test retry and back-off logic — are now full write-ups instead of a code snippet with a caption: a direct answer up front, headings that ask the question you arrived with, a section on what usually goes wrong, and an FAQ.
  • Every template page now opens with a plain answer to what the template is for and what it deliberately does not do, and ends with links to the vendor documentation or RFC it reproduces — Stripe, Slack, GitHub, Shopify, Telegram, RFC 6749, RFC 7517, RFC 9457 — instead of naming them in passing.
  • Guide and template pages carry FAQPage markup, and a template's markup cites the sources it is built from.

Changed

  • Guide and template pages now show when they were last updated, and publish the same date as dateModified.
  • The guides on retry logic and webhook receivers gained sections on when to stop retrying and on building an idempotency key from a delivery ID.

2026-09-08 — Internal linking and hub metadata

Added

  • Every guide and template page now ends with links to related pages, and a guide links back to the templates built on it — the two sections are cross-linked in both directions instead of hanging off their index alone.
  • The home page links straight into five guides and five templates instead of pointing at the index alone.
  • The guides, docs, and changelog pages now carry schema.org markup — an ItemList, a TechArticle, and a SoftwareApplication with release notes and version.

Changed

  • The guides and templates index pages lead their titles with what they actually list, instead of a generic section name.
  • /llms.txt gained a Documentation section, so the API reference, the OpenAPI contract, and the changelog are grouped where an AI assistant looks for them instead of sitting in the middle of a facts list.

2026-09-05 — Trusted client IP and relative-only redirects

Security

  • The client IP behind the per-IP mock limit, the IP blocklist, and the spam-filter allowlist is no longer read from a self-reported X-Forwarded-For header. It now comes from the immediate reverse proxy's own header (CF-Connecting-IP in production), and only when that peer is trusted — comma-separated forgeries are ignored outright.
  • Breaking change: a mock's Location response header must now be a plain relative path (e.g. /m/abc123) — checked on the main response, named variants, routes, sequence steps, and the error response alike. Absolute URLs, protocol-relative //host, and backslash variants are rejected with 422 validation_failed on create and update; an existing row that still carries one has the header dropped on serve instead.
  • Mock responses served from /m/:slug now send Cross-Origin-Resource-Policy: same-origin, so a mock can no longer be loaded as a script, image, or iframe from another origin. A mock cannot override this header itself.
  • The built-in anti-spam filter gained patterns for flag-file reads, secret-bearing environment lookups, loader and reverse-shell one-liners, cloud metadata paths, and two browser-hijacking idioms.

Changed

  • The admin token is now required on every mutating call — edit, delete, extend, and log export or clear — with no exception left for mocks created before tokens existed.

2026-08-22 — Go 1.27 and CI refresh

Changed

  • The backend and production image now build with Go 1.27.0; the full race-tested suite continues to pass on the new toolchain.
  • GitHub Actions now uses Node.js 24-compatible checkout and setup-go releases, with the Go version sourced directly from go.mod to keep CI and production aligned.

2026-08-19 — Deterministic scenarios, API workspaces and private logs

Added

  • Named response variants can now be selected explicitly with X-Quickmock-Variant or __quickmock_variant, making exact edge cases reproducible on demand.
  • Ordered conditional rules select variants from the request method, path, query, headers, or JSON body using equals, not_equals, contains, and exists operators.
  • One mock can now expose up to 50 method-and-path routes. Paste an OpenAPI 3.x JSON or YAML document into the builder to generate the workspace routes and example responses.
  • New API documentation and a machine-readable OpenAPI 3.1 contract cover creation, variants, rules, workspaces, and inspector privacy.

Security

  • Request logs are private by default for new mocks. The admin token unlocks a path-scoped HttpOnly inspector session; creators can also disable storage of request bodies or sender IPs.

Changed

  • SEO/GEO metadata now publishes reciprocal language sitemap entries, includes the documentation page and updated freshness signals, and marks mock, workspace, sharing, and inspector URLs as non-indexable.

2026-08-15 — Abuse resistance and safer mock responses

Security

  • The request inspector's fallback polling endpoints now have their own per-IP budget, limiting automated bursts without affecting normal live updates.
  • Mock responses can no longer widen a service worker's scope, and redirect responses accept only relative, HTTP, or HTTPS destinations.
  • The built-in abuse filter now rejects common SSRF primitives, executable handler configurations, and known backlink-page fingerprints. Self-hosters can also configure an IP/CIDR denylist.

Fixed

  • Container logs now rotate by default, and graceful shutdown no longer attempts to persist empty request-log records while draining a closed queue.

2026-08-10 — Hardened mock creation from the browser

Security

  • Creating a mock from the site — the form on the home page and the one-click button on a template page — is now rejected when another site triggered it in your browser. Scripted access is unaffected: curl, CI jobs, and the public API send no browser origin headers and keep working exactly as before.
  • Those same two actions now have their own rate-limit budget, separate from the one that serves mock traffic, so a runaway script can't spend your quota of active mocks.

Changed

  • The header no longer overflows on a phone: the Templates section made six links too many for one line, so the GitHub link moved down to the footer next to the other author links, and the remaining navigation wraps onto its own row instead of running off the screen.
  • Running your own instance: the server now warns at startup about environment variables left over from the old MOCKAPI_ prefix. Nothing has read them since the rename, so until now a stale key silently left the default in place — including QUICKMOCK_BASE_URL, which the new origin check depends on.

2026-08-09 — Mock template gallery

Added

  • New /templates section: ten ready-made mock configurations across four categories (payments, developer tools, auth & identity, general purpose) — Stripe and Shopify webhooks, GitHub push events, Slack's url_verification handshake, OAuth2/OIDC discovery and JWKS, RFC 9457 error bodies, and more.
  • Every template's "Create this mock" button creates it in one click, and the "Open it in the mock builder to tweak first" link opens the same config pre-filled in the regular mock form so you can adjust fields, headers, or status codes before saving.
  • Each template page breaks down the payload's key fields and lists exactly how the mock differs from the real service it imitates — no pretending a static mock is the genuine API.

Fixed

  • The home page's "you've hit the active-mock limit" banner used to show the request-body size limit instead of the actual mock-count limit, plus a stray %!(EXTRA int=…) tail. It now shows the correct number with nothing extra appended.

2026-07-26 — TTL cap, mock extension, log export

Added

  • A mock's lifetime is now capped: ttl_seconds can't exceed 30 days (server-configurable), whether set at creation or later.
  • The mock page grows an "Extend" button that pushes the expiry further out, up to that same 30-day cap from the mock's creation date — it requires the admin token, same as editing or deleting the mock.
  • Response body templates gained four tokens: {{random.pick:a|b|c}} picks one option per hit, {{seq}} counts hits, plus {{faker.price}} and {{faker.lorem}}.
  • The request inspector can filter by HTTP method, and its "Download JSON" link now exports the full captured request/response history (including sender IPs) — requires the admin token, unlike the config export.

2026-07-17 — Admin token per mock

Added

  • Creating a mock now returns a one-time admin token, shown once in a copyable banner on the mock page — save it, because it can't be shown again.
  • Editing a mock, deleting it, or clearing its logs now needs that token: send it as Authorization: Bearer <token>. Reading a mock, its logs, and the live inspector still work by slug alone, no token required.
  • Mocks created before this release keep working without a token until they expire. New guide: Manage mocks from any device.

2026-07-05 — Live inspector, export & import, anti-spam

Added

  • The request inspector streams over Server-Sent Events: new requests appear instantly, with no polling, and the page falls back to polling automatically where SSE is unavailable.
  • Export a mock's config as JSON from its page (no logs, no IPs) and import it on the create form — from a file or pasted text, entirely in your browser. The format matches POST /api/mocks, so exports are replayable via the API.
  • An anti-spam content filter blocks abusive mock creation. Operators can replace the built-in pattern list (QUICKMOCK_SPAM_PATTERNS_FILE), disable it, or allowlist IPs (QUICKMOCK_SPAM_ALLOW_IPS).

2026-06-19 — CORS toggle

Added

  • One checkbox on the create form turns on a permissive, credential-free CORS preset (Access-Control-Allow-Origin: * and friends) and answers OPTIONS preflight with 204 — call a mock from browser JS on any origin, no proxy.
  • New use-case guide: Mock an API with CORS.

2026-06-13 — Use-case guides

Added

  • New /guide section: scenario-first landing pages for common tasks — mock a REST API, test retry logic, simulate flaky or slow APIs, inspect webhooks, return fake data, echo the request. Each page has a ready-to-run curl example; all are listed in the sitemap.
  • Each guide now has a copy button on its curl examples and a one-click Create a mock CTA that opens the home form pre-filled with that recipe's config — method, body, delay, error rate, sequence — ready to submit.

2026-06-11 — Flaky-API simulation

Added

  • Response sequences: a mock can now hold an ordered list of up to 10 extra responses (status + body + headers each) cycled per hit — 1st call → main response, 2nd → step 2, … then loop. Classic retry-logic testing. The position is a shared per-mock counter (Redis, with an in-process fallback), so every caller advances the same sequence.
  • Error rate & delay jitter: a configurable share of requests (0–100%, rolled per request) can answer with an alternate status/body, and the response delay can be a min–max range for random latency jitter instead of a fixed value. All three settings combine, and a new X-Mockapi-Variant response header (default, error, or seq-i/n) shows which branch served each hit. Configurable from the create form (new “Flaky simulation” section) and the API.
  • The “Who built this” section on the home page now links to the maintainer's personal site (deadsquirrel.dev), language-matched per locale.

2026-06-10 — Request echo tokens

Added

  • New request.* dynamic tokens echo the incoming request back into the response body: {{request.method}}, {{request.path}}, {{request.ip}}, {{request.query.id}}, {{request.header.x-request-id}}, {{request.body}}, and JSON dot paths like {{request.body.user.name}}. Values are inserted verbatim and nothing extra is stored — a static mock can now answer with data from the request itself.

Fixed

  • The 2026-05-20 entry below used to display Go-template escaping ({{`…`}}) around every token instead of the token itself — leftover from copying the markup out of an HTML template. Now it shows plain {{faker.uuid}} and friends.

2026-06-08 — Author link

Added

  • Footer credit now links the author name to the maintainer's personal site (deadsquirrel.dev), language-matched per locale, with rel="me" as an identity signal.

2026-05-25 — Site content pass

Added

  • This /changelog page itself, in EN and RU, with hreflang and an entry in sitemap.xml.
  • Home page: a Quick glossary section (Mock API, Endpoint, TTL, Faker token, Content-Type) for readers landing here without context.
  • Home page: a Who built this block with author bio and direct links to GitHub, LinkedIn, Telegram — and a Why I built Quickmock personal-story section, so the page isn't a faceless tool landing.
  • Visible Last updated stamp at the bottom of the home page; dateModified mirrored into the WebApplication JSON-LD so AI crawlers see freshness.

Fixed

  • ?lang=<code> in the URL now actually serves that language. Previously the canonical / hreflang links pointed at ?lang=ru but the resolver only read the cookie and Accept-Language, so a bot following the hreflang link saw English content — the multilingual signal was a lie.

2026-05-23

Security

  • Origin hardening for /m/*: the public mock router now strips request-altering headers a malicious caller could use to confuse downstream proxies, slugs were lengthened (more entropy), and internal error messages are redacted before they reach the wire — no DSN fragments, no stack frames.
  • Language switcher (POST /language) now accepts same-origin absolute Referers, so the redirect-back path works behind reverse proxies that rewrite the Referer header. Cross-origin Referers are still rejected.

Fixed

  • RealIP middleware now trusts X-Forwarded-For / X-Real-IP when the immediate peer is loopback or a private/link-local address. Previously XFF was honored only for loopback peers, so behind Docker Compose every request was attributed to the bridge gateway (e.g. 172.18.0.1) — making creator_ip and request_ip useless and turning the per-IP mock limit into a global one.
  • Mock router now stores incoming request headers with lowercased keys, so request_headers->>'user-agent' works regardless of wire casing.
  • UI: slug examples updated to the new 12-char format; Copy-URL button restored on the mock detail page.

2026-05-21 — UGC disclaimer

Added

  • Footer disclaimer and Terms-of-use modal: mocks are user-generated content, prohibited categories (malware, phishing, CSAM, attack infrastructure) are spelled out, and an abuse-report channel is published.
  • Footer modal stays usable on small viewports — close button is no longer clipped on mobile.

2026-05-20 — Dynamic tokens

Added

  • Faker / now token substitution in response bodies: {{faker.uuid}}, {{faker.email}}, {{faker.name}}, {{now.iso8601}}, plus 18 more (people, IDs, network, text, time). The mock stores the template as-is and renders fresh random values on every hit, so one mock can serve different data per call. Full list lives under Dynamic tokens on the create form.

2026-05-18 — Hardening & quality of life

Fixed

  • Docker Compose deploy now waits for the --wait healthcheck instead of polling /healthz in a shell loop, so deploys no longer print the cosmetic curl: (52) Empty reply while the proxy and Go process finish racing.
  • POSTGRES_PASSWORD example in .env.example now warns against base64-encoded values — pgx's DSN parser chokes on + / = in the password.

2026-05-17 — Initial public release

Added

  • Core mock engine: create, view, edit, delete; all HTTP methods including ANY.
  • Public /m/:slug router with configurable status, body, headers, response delay (0–30 s), and TTL.
  • Live request inspector: HTMX 2-second poll, per-mock counter, clear-logs.
  • cURL import — paste a curl … command to pre-fill the create form.
  • Code snippets on the mock detail page for JavaScript, Python, Go, and PHP.
  • Read-only share preview at /share/:slug with Open Graph tags.
  • Per-IP rate limit (5000 hits / 8 hours) and per-IP active-mock cap (50).
  • 512 KB max response body, enforced by handler and a DB CHECK constraint.
  • Docker Compose stack (app + Postgres + Redis + one-shot migration container) and a bare-metal systemd path.
  • EN + RU localization, language switcher (cookie + Accept-Language).
  • Privacy by design: no third-party JS, no analytics, no fonts CDN; CI enforces this on every build.

Full git history on GitHub →

← Back to home