{"id":50188149,"url":"https://github.com/mridang/chasm","last_synced_at":"2026-05-25T11:07:03.591Z","repository":{"id":359766118,"uuid":"1247408531","full_name":"mridang/chasm","owner":"mridang","description":"An OpenAPI 3 mock server in Rust, distributed as a static binary, a WASM module, and reusable crates","archived":false,"fork":false,"pushed_at":"2026-05-23T10:04:51.000Z","size":339,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-23T12:09:31.779Z","etag":null,"topics":["api-mocking","json-schema","mock-server","mocking","oas3","openapi","openapi3","prism","rust","wasm"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mridang.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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":"2026-05-23T09:19:41.000Z","updated_at":"2026-05-23T10:05:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mridang/chasm","commit_stats":null,"previous_names":["mridang/chasm"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/mridang/chasm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mridang%2Fchasm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mridang%2Fchasm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mridang%2Fchasm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mridang%2Fchasm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mridang","download_url":"https://codeload.github.com/mridang/chasm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mridang%2Fchasm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33471610,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-25T06:32:55.349Z","status":"ssl_error","status_checked_at":"2026-05-25T06:32:35.322Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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-mocking","json-schema","mock-server","mocking","oas3","openapi","openapi3","prism","rust","wasm"],"created_at":"2026-05-25T11:07:00.493Z","updated_at":"2026-05-25T11:07:03.573Z","avatar_url":"https://github.com/mridang.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# chasm\n\nchasm is an OpenAPI 3 mock server in Rust. It ships as a single static binary, a WASM module, and a pair of reusable Rust crates: give it an OAS3 spec, it serves mock responses driven by the spec's `example:` blocks or by schema-faking when no example is declared. It mirrors the CLI shape and `Prefer`-header semantics of `@stoplight/prism-http`, so existing scripts and clients work unchanged.\n\n##### Why?\n\nOne static binary, no Node runtime, no `npm install` in CI. Fast cold start, suitable for ephemeral test containers and per-PR previews. Compiles to WASM for browsers, service workers, and Node bindings. Library-first: the engine and faker are usable as plain crates from any Rust app without dragging in HTTP plumbing.\n\n## Usage\n\nClone and run against the bundled petstore spec.\n\n```bash\ngit clone https://github.com/mridang/chasm.git\ncd chasm\ncargo run --bin chasm-server -- etc/petstore.yaml\n```\n\nIn another shell:\n\n```bash\ncurl http://localhost:4010/pets\ncurl -H 'Prefer: code=404' http://localhost:4010/pets/1\ncurl -H 'Prefer: dynamic=true, seed=42' http://localhost:4010/pets\n```\n\nRequires Rust 1.75+.\n\n### Server (CLI)\n\nRun `chasm-server` against an OAS3 spec.\n\n```bash\nchasm-server etc/petstore.yaml --port 8080 --host 0.0.0.0\nchasm-server etc/petstore.yaml --dynamic --seed 1234\nchasm-server etc/petstore.yaml --watch\nchasm-server --dry-run etc/petstore.yaml\nchasm-server validate etc/petstore.yaml\ncat etc/petstore.yaml | chasm-server -\n```\n\nThe spec path is positional; pass `-` to read from stdin (JSON or YAML, sniffed from the first non-whitespace byte). `chasm-server validate \u003cSPEC\u003e` runs the same structural checks the server runs on startup and exits non-zero with a diagnostic if the spec cannot be served — suitable as a pre-commit or CI gate.\n\nEvery response carries an `X-Request-ID` header (either the incoming client value or a fresh UUIDv4) and the same id is attached to the structured log line for the request. Errors are returned as RFC 7807 problem documents at `https://chasm.dev/errors#\u003cSLUG\u003e`.\n\n#### Options\n\n| Flag | Short | Default | Description |\n| --- | --- | --- | --- |\n| `\u003cSPEC\u003e` | | required | Path to the OAS3 specification (JSON or YAML), positional. Use `-` to read from stdin. |\n| `--spec \u003cSPEC\u003e` | | | Long form of the spec path, retained for backwards compatibility. |\n| `--port \u003cPORT\u003e` | `-p` | `4010` | TCP port to listen on. |\n| `--host \u003cHOST\u003e` | | `127.0.0.1` | Interface to bind to. |\n| `--dynamic` | `-d` | `false` | Generate response bodies from the schema rather than static examples. |\n| `--cors [\u003cBOOL\u003e]` | `-c` | `true` | Enable permissive CORS. Pass `--cors=false` to disable. |\n| `--cors-origin \u003cORIGIN\u003e` | | | Allowed origin for CORS responses. Repeat to allowlist multiple origins. |\n| `--cors-credentials` | | `false` | Emit `Access-Control-Allow-Credentials: true`. Requires at least one `--cors-origin`. |\n| `--cors-max-age \u003cSECONDS\u003e` | | `600` | `Access-Control-Max-Age` returned on CORS preflight responses. |\n| `--cors-expose-headers \u003cNAME\u003e` | | `x-request-id` | Response header name to advertise via `Access-Control-Expose-Headers`. Repeat for multiple. |\n| `--expose-spec [\u003cBOOL\u003e]` | | `true` | Mount `/openapi.yaml`, `/openapi.json`, and `/openapi` introspection routes. |\n| `--max-connections \u003cN\u003e` | | `1024` | Cap on in-flight HTTP requests; excess clients receive `503 Service Unavailable`. |\n| `--errors` | `-e` | `false` | Return `422` with RFC 7807 problem JSON when request validation fails. |\n| `--seed \u003cN\u003e` | | | Default seed for dynamic generation; per-request `Prefer: seed=` overrides it. |\n| `--ignore-examples` | | `false` | Skip the example pipeline entirely and always go to schema-driven generation. |\n| `--watch` | | `false` | Watch the spec file and hot-reload routing tables on change without dropping the listener. |\n| `--dry-run` | | `false` | Load and validate the spec, print a summary, then exit without binding. |\n| `--verbose` | `-v` | `0` | Increase log verbosity. Repeatable: `-v` = debug, `-vv` = trace. |\n| `--json-schema-faker-fill-properties` | | `true` | Controls `json-schema-faker` `fillProperties` behaviour. |\n| `--strict-method-matching` | | `false` | `HEAD`/`OPTIONS` on operations that do not declare them return `405` instead of being implicitly served. |\n| `--tls-cert \u003cPATH\u003e` | | | PEM certificate chain. Pair with `--tls-key` to terminate TLS via `rustls`. Also reads `CHASM_TLS_CERT`. |\n| `--tls-key \u003cPATH\u003e` | | | PEM private key paired with `--tls-cert`. Also reads `CHASM_TLS_KEY`. |\n| `--log-format \u003cFORMAT\u003e` | | `text` | On-the-wire log format: `text` or `json`. Also reads `CHASM_LOG_FORMAT`. |\n| `--request-timeout \u003cSECONDS\u003e` | | `30` | Per-request handler timeout; on expiry the server emits a `408 Request Timeout` problem+json envelope. Also reads `CHASM_REQUEST_TIMEOUT`. |\n\nOperational endpoints (always reserved, outside the spec's path-space):\n\n| Path | Purpose |\n| --- | --- |\n| `/healthz` | Aggregate health check. |\n| `/livez` | Process liveness. |\n| `/readyz` | Returns `200` once the spec is loaded; flips to `503` during a `--watch` reload. |\n| `/metrics` | Prometheus text exposition (request counters, latency histograms, faker/validation timings). |\n\n### Prefer header\n\nPer-request overrides may also be supplied as query parameters prefixed with `__`; query values win on conflict.\n\n| Directive | Query | Type | Effect |\n| --- | --- | --- | --- |\n| `code=` | `__code` | `u16` | Force a specific response status code. |\n| `example=` | `__example` | string | Pick a named entry from the response's `examples` map. |\n| `dynamic=` | `__dynamic` | bool | Toggle schema-driven generation for this request. |\n| `seed=` | `__seed` | `u64` | Seed dynamic generation for this request. |\n| `validate=` | `__validate` | bool | Disable request validation for this request (default: on under `--errors`). |\n| `security=` | `__security` | bool | Disable security/auth evaluation for this request (default: on). |\n\n```bash\ncurl -H 'Prefer: code=404' http://localhost:4010/pets/1\ncurl -H 'Prefer: example=fido' http://localhost:4010/pets/1\ncurl -H 'Prefer: dynamic=true, seed=42' http://localhost:4010/pets\ncurl 'http://localhost:4010/pets?__dynamic=true\u0026__seed=42'\n```\n\nSee [`docs/PREFER_HEADER.md`](docs/PREFER_HEADER.md) for full semantics, precedence, and edge cases.\n\n### WASM\n\n```js\nimport init, { Chasm } from \"./pkg/chasm_wasm.js\";\n\nawait init();\nconst specJson = await fetch(\"/petstore.json\").then(r =\u003e r.text());\nconst chasm = new Chasm(specJson, /* dynamic */ false);\n\nconst resp = chasm.handle(\"GET\", \"/pets\", \"\", \"application/json\");\nconsole.log(resp);\n```\n\nIn Node:\n\n```js\nconst { Chasm } = require(\"chasm-wasm\");\nconst fs = require(\"fs\");\nconst chasm = new Chasm(fs.readFileSync(\"petstore.json\", \"utf8\"), false);\nconsole.log(chasm.handle(\"GET\", \"/pets\", \"code=404\", \"application/json\"));\n```\n\n### Library (Rust)\n\n`chasm-engine` is a plain crate. No HTTP server is required to use it. `MockRequest`, `MockResponse`, and `MockConfig` are `#[non_exhaustive]`, so external callers must use `default()` + field mutation rather than struct literals.\n\n```rust\nuse chasm_engine::{load_spec, mock, MockConfig, MockRequest};\nuse std::collections::HashMap;\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let spec = load_spec(\"etc/petstore.yaml\")?;\n\n    let mut headers = HashMap::new();\n    headers.insert(\"Prefer\".into(), \"dynamic=true, seed=42\".into());\n\n    let mut req = MockRequest::default();\n    req.method = \"GET\".into();\n    req.path = \"/pets\".into();\n    req.headers = headers;\n\n    let cfg = MockConfig::default();\n    let resp = mock(\u0026spec, \u0026req, \u0026cfg)?;\n\n    println!(\"{} {} {}\", resp.status, resp.content_type, resp.body);\n    Ok(())\n}\n```\n\n`chasm-faker` is similarly standalone if you only need schema-driven value generation.\n\n```rust\nuse chasm_faker::{generate, GenerateOptions};\nuse serde_json::json;\n\nlet schema = json!({\n    \"type\": \"object\",\n    \"required\": [\"id\", \"name\"],\n    \"properties\": {\n        \"id\":   { \"type\": \"integer\", \"format\": \"int64\" },\n        \"name\": { \"type\": \"string\", \"minLength\": 1, \"maxLength\": 32 }\n    }\n});\n\nlet mut opts = GenerateOptions::default();\nopts.seed = Some(42);\nlet value = generate(\u0026schema, \u0026opts).unwrap();\nprintln!(\"{}\", value);\n```\n\n#### Crates\n\n| Crate | Purpose |\n| --- | --- |\n| `chasm-faker` | Port of `json-schema-faker`. Generates JSON values from a JSON Schema with seeding, formats, `$ref` resolution, and extension keywords. |\n| `chasm-engine` | Mocking core: spec loading, routing, content negotiation, example/schema pipeline, `Prefer` parsing. No HTTP. |\n| `chasm-server` | Axum binary. Wraps `chasm-engine` behind a CLI and emits RFC 7807 problem documents on error. |\n| `chasm-wasm` | `wasm-bindgen` bindings exposing `chasm-engine` to browsers and Node. |\n\n### Error envelope\n\nErrors are returned as RFC 7807 problem documents. The `type` URI is `https://chasm.dev/errors#\u003cSLUG\u003e`; clients that switch on the slug portion (`NO_PATH_MATCHED_ERROR`, etc.) keep working across the 0.2.0 base-URI change.\n\n- `NO_PATH_MATCHED_ERROR` (HTTP 404)\n- `NO_METHOD_MATCHED_ERROR` (HTTP 405)\n- `NOT_FOUND` (HTTP 404) — `Prefer: example=\u003cname\u003e` references a missing example.\n- `NOT_ACCEPTABLE` (HTTP 406) — no media type intersects with the request `Accept` header.\n- `UNAUTHORIZED` (HTTP 401)\n- `UNPROCESSABLE_ENTITY` (HTTP 422) — request validation failed under `--errors`.\n- `NO_RESPONSE_DEFINED` (HTTP 404) — `Prefer: code=\u003cn\u003e` names a status the operation does not declare.\n- `NO_RESPONSE_RESPONSE_DEFINED` (HTTP 500) — operation has no usable response definition.\n- `INTERNAL_SERVER_ERROR` (HTTP 500)\n- `REQUEST_TIMEOUT` (HTTP 408) — handler exceeded `--request-timeout`.\n- `PAYLOAD_TOO_LARGE` (HTTP 413) — request body exceeded the 16 MiB ceiling.\n\n## Configuration\n\nEnvironment variables are an alternative to CLI flags. Every flag noted as \"Also reads `CHASM_*`\" above is overridable this way. See [`docs/ENV.md`](docs/ENV.md) for the full list.\n\nThe `etc/` directory ships small specs covering specific features: [`etc/petstore.yaml`](etc/petstore.yaml) (canonical OAS 3.0), [`etc/auth.yaml`](etc/auth.yaml) (bearer JWT + `apiKey` + Basic), [`etc/oneof-discriminator.yaml`](etc/oneof-discriminator.yaml) (`discriminator.propertyName`), [`etc/oas31-nullable.yaml`](etc/oas31-nullable.yaml) (OAS 3.1 `type: [..., \"null\"]`). All four validate under `chasm-server validate \u003cpath\u003e`.\n\nLong-form reference docs:\n\n- [`docs/SCOPE.md`](docs/SCOPE.md) — what chasm does and intentionally doesn't.\n- [`docs/PREFER_HEADER.md`](docs/PREFER_HEADER.md) — `Prefer` directive semantics.\n- [`docs/METRICS.md`](docs/METRICS.md) — Prometheus metric names, labels, types.\n- [`docs/ENV.md`](docs/ENV.md) — every `CHASM_*` environment variable.\n- [`docs/BENCHMARKS.md`](docs/BENCHMARKS.md) — measured throughput, memory, binary size.\n\n## Caveats\n\n- Proxy mode (forwarding to an upstream when no example matches) is not implemented. chasm is mock-only.\n- No Spectral linting pipeline; `chasm-server validate` performs structural checks only.\n- No `prism.json` config file. Configuration is CLI flags and `CHASM_*` env vars.\n- Operation-level callbacks and links are parsed but ignored.\n- `bearerFormat: JWT` is treated as opaque credentials; chasm does not parse or validate the JWT shape.\n- TLS mode does not yet support graceful shutdown on SIGTERM.\n\n## Contributing\n\nContributions are welcome! If you find a bug or have suggestions for improvement, please open an issue or submit a pull request.\n\n## License\n\nApache License 2.0 © 2026 Mridang Agarwalla\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmridang%2Fchasm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmridang%2Fchasm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmridang%2Fchasm/lists"}