{"id":31287278,"url":"https://github.com/bl4cky99/mocker","last_synced_at":"2025-09-29T17:04:07.281Z","repository":{"id":316303097,"uuid":"1062826641","full_name":"Bl4cky99/mocker","owner":"Bl4cky99","description":"A file-driven mock HTTP API server with templated responses, schema validation, and pluggable auth for local development and integration tests. ","archived":false,"fork":false,"pushed_at":"2025-09-23T19:50:34.000Z","size":304,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-23T21:24:15.593Z","etag":null,"topics":["api","development","golang","mock-api","mock-server","web"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Bl4cky99.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-23T19:34:03.000Z","updated_at":"2025-09-23T21:13:25.000Z","dependencies_parsed_at":"2025-09-23T21:24:20.313Z","dependency_job_id":"fbafe9ff-98e9-41a6-9e66-b4f7acd0200b","html_url":"https://github.com/Bl4cky99/mocker","commit_stats":null,"previous_names":["bl4cky99/mocker"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Bl4cky99/mocker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bl4cky99%2Fmocker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bl4cky99%2Fmocker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bl4cky99%2Fmocker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bl4cky99%2Fmocker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Bl4cky99","download_url":"https://codeload.github.com/Bl4cky99/mocker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bl4cky99%2Fmocker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276737524,"owners_count":25695700,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-24T02:00:09.776Z","response_time":97,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","development","golang","mock-api","mock-server","web"],"created_at":"2025-09-24T11:01:11.981Z","updated_at":"2025-09-24T11:03:18.007Z","avatar_url":"https://github.com/Bl4cky99.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca id=\"readme-top\"\u003e\u003c/a\u003e\n\n\u003cbr /\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003ca href=\"https://github.com/Bl4cky99/mocker\"\u003e\n        \u003cimg src=\"README_ASSETS/logo.png\" width=\"600\"\u003e\n    \u003c/a\u003e\n    \u003ch3\u003emocker\u003c/h3\u003e\n    \u003cp align=\"center\"\u003e\n        A file-driven mock \u003cb\u003eHTTP API server\u003c/b\u003e with templated responses, schema validation, and pluggable auth for local development and integration tests.\n        \u003cbr/\u003e\n        Define endpoints in YAML/JSON, serve multiple variants, enforce request contracts, and explore responses with real-time templating helpers.\n        \u003cbr/\u003e\u003cbr/\u003e\n        \u003ca href=\"https://github.com/Bl4cky99/mocker/issues/new?template=bug_report.yml\"\u003eReport Bug\u003c/a\u003e\n        \u0026middot;\n        \u003ca href=\"https://github.com/Bl4cky99/mocker/issues/new?template=feature_request.yml\"\u003eRequest Feature\u003c/a\u003e\n        \u003cbr/\u003e\u003cbr/\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eTable of Contents\u003c/summary\u003e\n\u003col\u003e\n  \u003cli\u003e\u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"#install-go\"\u003eGo install (recommended)\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#install-release\"\u003eGitHub Releases\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#install-build\"\u003eBuild from source\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#install-docker\"\u003eDocker (GHCR)\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#quickstart\"\u003eQuickstart\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#configuration\"\u003eConfiguration\u003c/a\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"#config-server\"\u003eServer settings\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#config-auth\"\u003eAuthentication\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#config-endpoints\"\u003eEndpoints\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#config-variants\"\u003eResponse variants\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#config-template\"\u003eTemplate data \u0026 helpers\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#config-validation\"\u003eRequest validation\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#examples\"\u003eExamples\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#cli\"\u003eCLI reference\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#troubleshooting\"\u003eTroubleshooting\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#compatibility\"\u003eCompatibility\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#roadmap\"\u003eRoadmap\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#faq\"\u003eFAQ\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#developer-documentation\"\u003eDeveloper Documentation\u003c/a\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"#architecture\"\u003eArchitecture\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#tests\"\u003eTests\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#minimal-dev-loop\"\u003eMinimal dev loop\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/details\u003e\n\n---\n\n## \u003cspan id=\"features\"\u003eFeatures\u003c/span\u003e\n\n- **Declarative mocks**: describe endpoints, variants, and contracts in a single YAML or JSON file; runtime validation rejects misconfigured responses early.\n- **Variant matching**: choose responses by method, path params, query strings, or request headers with deterministic fallback rules.\n- **Templated bodies**: inline Go templates (or external files) get live request data such as path parameters, headers, and the current timestamp; reuse helpers like `{{ json . }}` for quick payloads.\n- **Schema-aware inputs**: optional JSON Schema validation (Draft 2020) and `Content-Type` checks let you enforce request payloads before returning mock data.\n- **Built-in auth**: enable bearer-token or HTTP basic authentication with constant-time comparisons, or disable auth entirely for open mocks.\n- **Production-like behaviour**: configurable response delays, global default headers, request IDs, and structured logs mimic real services during integration tests.\n- **Developer-friendly CLI**: `mocker serve` starts the server with pretty logs, `mocker validate` verifies configurations, and `--version` prints build metadata at startup.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"installation\"\u003eInstallation\u003c/span\u003e\n\n### \u003cspan id=\"install-go\"\u003eGo install (recommended)\u003c/span\u003e\n\n```bash\ngo install github.com/Bl4cky99/mocker/cmd/mocker@latest\n\n# Run from any folder\nmocker serve -c ./config.yaml\n```\n\nRequires Go **1.25+**. The binary is placed in `$(go env GOPATH)/bin` (add it to your `$PATH`).\n\n### \u003cspan id=\"install-release\"\u003eGitHub Releases\u003c/span\u003e\n\nTagged builds ship as tarballs for each supported architecture. Download and verify a release binary:\n\n```bash\nVERSION=v1.2.3\nOS=linux\nARCH=amd64\n\nBASE=https://github.com/Bl4cky99/mocker/releases/download/${VERSION}\nFILE=mocker-${VERSION}-${OS}-${ARCH}.tar.gz\n\ncurl -sSLO ${BASE}/${FILE}\ncurl -sSLO ${BASE}/${FILE}.sha256\nsha256sum -c ${FILE}.sha256\n\ntar -xzf ${FILE}\nchmod +x mocker-${OS}-${ARCH}\n./mocker-${OS}-${ARCH} serve -c config.yaml -p\n```\n\nRename the binary or move it to a directory on your `$PATH` (for example `/usr/local/bin`).\n\n---\n\n### \u003cspan id=\"install-build\"\u003eBuild from source\u003c/span\u003e\n\nClone the repository and use the provided Makefile (or plain `go build`).\n\n```bash\nmake build           # produces ./bin/mocker with git version metadata\nmake serve           # builds \u0026 starts the server using config.yaml\n\n# or without Makefile\nGOFLAGS=\"-trimpath\" go build -o bin/mocker ./cmd/mocker\n```\n\nEnvironment variables at build time (`VERSION`, `COMMIT`, `DATE`) are embedded into the binary. Override them when cutting releases.\n\n---\n\n### \u003cspan id=\"install-docker\"\u003eDocker (GHCR)\u003c/span\u003e\n\nTagged pushes trigger an automated build that publishes `ghcr.io/bl4cky99/mocker` (currently linux/amd64). Use semantic version tags or the floating aliases `latest`, `vX`, and `vX.Y`.\n\n```bash\nIMAGE=ghcr.io/bl4cky99/mocker\nTAG=v1.2.3    # or latest\n\ndocker pull ${IMAGE}:${TAG}\n\ndocker run --rm -p 8080:8080 \\\n  -v $(pwd)/config.yaml:/app/config.yaml:ro \\\n  ${IMAGE}:${TAG} serve -c /app/config.yaml -p\n```\n\nThe container entrypoint runs `mocker serve -c /app/config.yaml -p`; mount your config there or override the command.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"quickstart\"\u003eQuickstart\u003c/span\u003e\n\n1. Copy the sample config (`examples/example.yaml`) to `config.yaml` and customise it.\n2. Start the server (pretty logs enabled):\n\n```bash\nmocker serve -c config.yaml -p\n```\n\n3. Exercise endpoints with `curl` or your favourite API client:\n\n```bash\ncurl -i -H \"Authorization: Bearer devtoken123\" \\\n  \"http://localhost:1337/api/users/42?verbose=true\"\n```\n\n\u003e Tip: run `mocker validate -c config.yaml` in your CI pipeline to catch schema errors or missing files before deployment.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"configuration\"\u003eConfiguration\u003c/span\u003e\n\nConfiguration files accept **YAML (`.yml`, `.yaml`)** or **JSON (`.json`)**. Unknown fields are rejected, defaults are applied automatically, and the resolved configuration is validated before the server starts.\n\n### \u003cspan id=\"config-server\"\u003eServer settings\u003c/span\u003e\n\n```yaml\nserver:\n  addr: \":1337\"           # default :8080\n  basePath: \"/api\"        # default \"/\"\n  defaultHeaders:\n    X-Powered-By: \"mocker\"\n    Cache-Control: \"no-store\"\n  cors:\n    enabled: true\n    allowOrigins: [\"*\"]\n    allowMethods: [\"GET\", \"POST\"]\n    allowHeaders: [\"Authorization\"]\n```\n\n- `addr`: listening address; override at runtime via `--addr`.\n- `basePath`: mounted prefix (trimmed of trailing `/`). All endpoints are registered beneath it.\n- `defaultHeaders`: applied to every response unless the handler has already set the header.\n- `cors`: reserved for upcoming first-class CORS support. When enabled today it allows unauthenticated `OPTIONS` preflight requests while you manage the actual headers via `defaultHeaders`.\n\n### \u003cspan id=\"config-auth\"\u003eAuthentication\u003c/span\u003e\n\n```yaml\nauth:\n  type: token         # \"none\" | \"token\" | \"basic\"\n  token:\n    header: \"Authorization\"\n    prefix: \"Bearer \"\n    tokens: [\"devtoken123\", \"staging-secret\"]\n\n# or basic auth\n# auth:\n#   type: basic\n#   basic:\n#     users:\n#       - username: \"admin\"\n#         password: \"password\"\n```\n\n- `token`: constant-time comparison against the configured token list. Prefix is optional.\n- `basic`: validates username/password pairs; responses include `WWW-Authenticate` when credentials are missing or wrong.\n- `none`: disables auth entirely.\n\n### \u003cspan id=\"config-endpoints\"\u003eEndpoints\u003c/span\u003e\n\nEach endpoint specifies an HTTP method, path (chi-style parameters like `/users/{id}`), optional request validation, and one or more response variants.\n\nRules enforced during load:\n- Paths must start with `/` and HTTP methods must be one of `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`.\n- Duplicate endpoints without `when` clauses are rejected to avoid ambiguous fallbacks.\n- Every endpoint needs at least one response.\n\n### \u003cspan id=\"config-variants\"\u003eResponse variants\u003c/span\u003e\n\n```yaml\nresponses:\n  - when:\n      query: { search: \"alice\" }\n      header: { X-Debug: \"1\" }\n    status: 200\n    headers: { Content-Type: \"application/json\" }\n    bodyFile: \"./examples/bodies/users.list.json.tmpl\"\n  - status: 404\n    headers: { Content-Type: \"application/json\" }\n    body: '{ \"error\": \"user not found\" }'\n    delayMs: 150\n```\n\n- `when.query`: exact match on query parameters.\n- `when.header`: exact match on request headers (canonicalised names).\n- Selection order: the first matching variant wins. If none match, the earliest variant without a `when` clause is used as fallback, otherwise the first variant is returned.\n- `status`: defaults to `200` when omitted.\n- `headers`: override or extend the global `defaultHeaders` for that response.\n- `delayMs`: artificial latency before writing the response (cancelled if the request context ends).\n- Exactly one of `body` (inline string) or `bodyFile` (path to template or raw file) must be set.\n\n### \u003cspan id=\"config-template\"\u003eTemplate data \u0026 helpers\u003c/span\u003e\n\nThe renderer uses Go's `html/template` with `missingkey=default` and a growing set of helpers:\n\n```go\n{{ .Path.id }}            # chi path parameter\n{{ .Query.verbose }}      # query parameter (string)\n{{ index .Header \"X-Correlation-Id\" }}\n{{ .NowRFC3339 }}         # timestamp injected per request\n{{ json .Query }}         # helper -\u003e JSON encode any value\n```\n\n- Inline templates (`body`) are parsed on each request; files (`bodyFile`) are cached and reloaded when their mtime changes.\n- Headers are canonicalised (`X-Correlation-Id`), queries preference the first value, path params come from chi's URL params.\n\n### \u003cspan id=\"config-validation\"\u003eRequest validation\u003c/span\u003e\n\n```yaml\nvalidate:\n  contentType: \"application/json\"\n  schemaFile: \"./examples/schemas/user.create.json\"\n```\n\n- `contentType`: optional strict equality check for the request `Content-Type`.\n- `schemaFile`: compile-on-start JSON Schema (Draft 2020). Files are cached per absolute path and reused across endpoints.\n- Request bodies are limited to 1 MiB for schema validation to avoid runaway payloads.\n- Validation errors result in `400 Bad Request` with the schema error message.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"examples\"\u003eExamples\u003c/span\u003e\n\nExplore `/examples` for ready-to-run demos:\n\n- `examples/example.yaml` - full sample covering auth, validation, templated responses, delays, and query/header routing.\n- `examples/bodies/*.tmpl` - Go templates showing how to echo request data back to the caller.\n- `examples/schemas/*.json` - JSON Schemas used to validate POST/PUT payloads.\n\nRun the sample config directly:\n\n```bash\ncp examples/example.yaml config.yaml\nmocker serve -c config.yaml -p\n\n# Try different variants\ncurl -i -H \"Authorization: Bearer devtoken123\" \\\n  \"http://localhost:1337/api/users?search=alice\"\n\ncurl -i -H \"Authorization: Bearer devtoken123\" \\\n  -H \"X-Debug: 1\" \"http://localhost:1337/api/orders/42\"\n```\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"cli\"\u003eCLI reference\u003c/span\u003e\n\n```\nmocker - local mock API server\n\nUsage:\n    mocker \u003ccommand\u003e [flags]\n\nCommands:\n    serve       Start the mock server (alias: mocker serve)\n    validate    Validate a config file and exit\n    version     Print version info\n```\n\n### `serve`\n\n| Flag | Description |\n|------|-------------|\n| `-c, --config` | Path to config file (default `config.yaml`). |\n| `-a, --addr` | Override server address from the config. |\n| `-l, --log-level` | `debug`, `info`, `warn`, or `error` (default `info`). |\n| `-p, --pretty` | Use human-readable text logs instead of JSON. |\n| `--version` | Print build metadata at startup. |\n\n### `validate`\n\n| Flag | Description |\n|------|-------------|\n| `-c, --config` | **Required** path to config file to validate. |\n\nExit codes follow UNIX conventions: `0` on success, `1` for runtime errors, `2` for CLI misuse (missing flags, unknown commands, etc.).\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"troubleshooting\"\u003eTroubleshooting\u003c/span\u003e\n\n- **\"empty config path\" or \"read ...\":** ensure the path passed to `--config` exists and has `.yaml`, `.yml`, or `.json` extension.\n- **Schema compile errors:** paths inside `schemaFile` are resolved relative to the working directory. Use absolute paths or keep schemas next to your config.\n- **\"set exactly one of body or bodyFile\":** every variant needs exactly one body source. Remove the redundant field.\n- **Unexpected fallback response:** remember that variants without `when` clauses serve as fallbacks; put more specific matches earlier.\n- **401 Unauthorized:** confirm the correct bearer token or basic credentials and header prefix. Prefix matching is case-sensitive.\n- **Body file not found at runtime:** `bodyFile` paths are read on demand; missing files will log an error and return `500`. Keep mock payloads alongside your config or use absolute paths.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"compatibility\"\u003eCompatibility\u003c/span\u003e\n\n- Go runtime: **1.25+**\n- Platforms: tested on Linux and macOS; Windows is expected to work (chi + net/http).\n- JSON Schema: compiled with [`github.com/santhosh-tekuri/jsonschema/v6`](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v6) using Draft 2020 defaults.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"roadmap\"\u003eRoadmap\u003c/span\u003e\n\n- [ ] First-class CORS response headers derived from the `server.cors` block.  \n- [ ] Hot reload / watch mode for configuration changes.\n- [ ] Pluggable request matchers (e.g. regex, body predicates).\n- [ ] Additional template helpers (UUIDs, random data, timestamps).\n- [ ] Optional OpenAPI export to document configured endpoints.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"faq\"\u003eFAQ\u003c/span\u003e\n\n**Q: How are multiple variants evaluated?**  \nA: `mocker` walks the list once. The first variant whose `when` clause matches wins; if none match, the earliest variant without conditions becomes the fallback, otherwise the head of the list is used.\n\n**Q: Can I return binary files or images?**  \nA: Yes. Point `bodyFile` to any file on disk (e.g. PNG). The file is streamed as-is, so remember to set the matching `Content-Type` header in the variant.\n\n**Q: Do templates have access to the request body?**  \nA: Not yet. The renderer currently provides path params, query params, headers, and a timestamp. Body capture is on the roadmap.\n\n**Q: How do I disable logging?**  \nA: Use `--log-level error` (or `warn`). Structured logging remains active for observability but noise is reduced.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"developer-documentation\"\u003eDeveloper Documentation\u003c/span\u003e\n\n### \u003cspan id=\"architecture\"\u003eArchitecture\u003c/span\u003e\n\n```\n.\n|-- cmd/mocker          # CLI entrypoint (serve, validate, version)\n|-- internal/cli        # Command parsing, logging setup, signal handling\n|-- internal/config     # Config structs, defaulting, validation helpers\n|-- internal/httpx      # HTTP server, routing, middleware, response engine\n|-- internal/auth       # Basic and token auth providers\n|-- internal/render     # Template renderer with file caching \u0026 helpers\n`-- internal/validate   # JSON Schema compilation and runtime checks\n```\n\nKey flow:\n1. CLI loads configuration (`internal/config.Load`), applies defaults, and validates it.\n2. HTTP server (`internal/httpx`) compiles schema validators, builds chi routes, and wires middleware (logging, auth, validation).\n3. Requests resolve to a response variant, optional delay is applied, bodies are rendered via `internal/render`, and responses inherit default headers.\n\n### \u003cspan id=\"tests\"\u003eTests\u003c/span\u003e\n\nRun the entire suite (race detector enabled by default in the Makefile):\n\n```bash\ngo test ./...\nmake test        # equivalent with -race -timeout=2m\n\n# Specific packages\ngo test ./internal/config -run TestLoad\n```\n\n### \u003cspan id=\"minimal-dev-loop\"\u003eMinimal dev loop\u003c/span\u003e\n\n```\nmake build                             # compile binary with version metadata\n./bin/mocker serve -c config.yaml -p   # start the server with pretty logs\ncurl -H 'Authorization: Bearer devtoken123' http://localhost:1337/api/healthz\n./bin/mocker validate -c config.yaml   # ensure config stays valid\n```\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## \u003cspan id=\"license\"\u003eLicense\u003c/span\u003e\n\nThis project is licensed under the **MIT License**.\n\n- Copyright (c) 2025 [Jason Giese (Bl4cky99)](https://github.com/Bl4cky99)\n- See the full text in [LICENSE](./LICENSE).\n\n**Notes for users and integrators**\n- Commercial use, modification, distribution, and private forks are permitted.\n- Keep the copyright and permission notice from the MIT license in all copies/substantial portions.\n- (Optional) Add an SPDX header to source files for tooling: `// SPDX-License-Identifier: MIT`.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\nHappy mocking!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbl4cky99%2Fmocker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbl4cky99%2Fmocker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbl4cky99%2Fmocker/lists"}