Built-in CORS
A browser calling a Mimic-backed API from http://localhost:3000 normally fails twice: it sends OPTIONS /users first (which no mock answers), and every real mock has to repeat Access-Control-Allow-Origin in its response_headers. For an API with N endpoints that’s up to 2N files maintained by hand.
One variable replaces all of them:
MIMIC_CORS=trueThat’s it — preflights are answered automatically and every mock response carries the allow-origin header.
Configuration
Section titled “Configuration”| Variable | Default | What it does |
|---|---|---|
MIMIC_CORS |
false |
Master switch. Everything below is ignored while it’s off. |
MIMIC_CORS_ORIGINS |
* |
*, or a comma-separated allowlist like http://localhost:3000,http://localhost:5173. |
MIMIC_CORS_METHODS |
GET,POST,PUT,PATCH,DELETE,OPTIONS |
Advertised as Access-Control-Allow-Methods on a preflight. |
MIMIC_CORS_HEADERS |
* |
* reflects the request’s Access-Control-Request-Headers; a list is sent verbatim. |
MIMIC_CORS_CREDENTIALS |
false |
Sends Access-Control-Allow-Credentials: true. |
MIMIC_CORS_MAX_AGE |
600 |
Access-Control-Max-Age, in seconds. |
docker run -d -p 8080:8080 \ -e MIMIC_CORS=true \ -e MIMIC_CORS_ORIGINS=http://localhost:3000,http://localhost:5173 \ -v $(pwd)/mocks:/app/mocks:ro \ ragilhadi/mimic:latestWhat it does
Section titled “What it does”# No OPTIONS mock anywhere — Mimic answers the preflight itselfcurl -i -X OPTIONS http://localhost:8080/users \ -H 'Origin: http://localhost:3000' \ -H 'Access-Control-Request-Method: POST' \ -H 'Access-Control-Request-Headers: content-type'HTTP/1.1 204 No Contentaccess-control-allow-origin: *access-control-allow-methods: GET, POST, PUT, PATCH, DELETE, OPTIONSaccess-control-allow-headers: content-typeaccess-control-max-age: 600Semantics
Section titled “Semantics”- Off by default. With
MIMIC_CORSunset, responses are byte-identical to what they were before this existed — no new headers, andOPTIONSstill 404s. - A mock’s own header always wins. If a mock sets
Access-Control-Allow-Originin itsresponse_headers, the global config leaves it alone — so mocking a CORS failure stays possible. - Preflights are gap-filled, not hijacked. An
OPTIONSrequest that no mock matches, but whose path has a mock registered for the method inAccess-Control-Request-Method, is answered204. An explicitOPTIONSmock matches first and wins. A preflight for a path with nothing behind it still404s. - Only real endpoints, in the current scenario. A mock hidden by the active scenario has no endpoint to preflight, and its preflight
404s too. - A bare
OPTIONSisn’t a preflight. WithoutAccess-Control-Request-Method— curl, a health probe — the request behaves exactly as it always has. - Preflights are logged. They appear in
/admin/requestsand the dashboard withmatched_mock: nulland the explanation “answered as a CORS preflight”, so nothing looks dropped. - The allowlist is honored. A request from an origin outside
MIMIC_CORS_ORIGINSgets noAccess-Control-Allow-Originheader rather than a wrong one, which is what makes the browser’s own error message correct. Responses that depend on the origin also carryVary: Origin. *with credentials.MIMIC_CORS_ORIGINS=*plusMIMIC_CORS_CREDENTIALS=trueis invalid per the CORS spec; Mimic reflects the request origin instead and warns once at startup.- Matching is untouched: CORS headers are added to the response, never to the request the matcher sees.
- Mimic’s own error responses carry the headers too. The
mock not found404, thepayload too large413, the admin API’s 401, and both proxy fallback outcomes all get the sameAccess-Control-Allow-Origin(and friends) a matched mock would — so a request to a path you forgot to mock reads as a 404 in the browser console, not as an opaque CORS failure. A proxied response that already carries its ownAccess-Control-Allow-Originfrom upstream keeps it.
Worked example: frontend development
Section titled “Worked example: frontend development”docker run -d -p 8080:8080 \ -e MIMIC_CORS=true \ -e MIMIC_CORS_ORIGINS=http://localhost:3000 \ -v ./mocks:/app/mocks:ro ragilhadi/mimic:latestPoint your frontend dev server at http://localhost:8080 — preflights are handled for you, and every JSON response already carries the right allow-origin header.