Creating Mocks
Proxying and Hosts
Most of the time you do not want to mock a whole API, just the parts that matter for the scenario at hand. This page shows how Mocko sits in front of real backends: forwarding unmatched requests, proxying conditionally from inside a template, and routing multiple services through one instance with hosts.
Forward what you do not mock
Start Mocko with a proxy URL and point your app at Mocko instead of the real API:
Requests that match a mock are answered by the mock. Everything else is forwarded to https://demo-api.mockoapp.net(a demo backend you can actually hit) with the same method, path, query string, headers, and body, and the backend's response comes back untouched. Your app cannot tell the difference; it just sees an API where one or two routes happen to be under your control.
Proxying from inside a template
The proxy helper moves that decision into the body, so a single route can be partly real and partly mocked:
mock "GET /posts" {
body = <<-EOF
{{#is request.query.userId 1}}
[]
{{else}}
{{proxy}}
{{/is}}
EOF
}User 1 gets an empty list, everyone else gets the real backend. This is the single most useful pattern for testing edge cases against live systems, and the Mock One Edge Case recipe explores variations of it.
{{proxy}} halts template execution: the proxied response becomes the entire response, and anything after the helper in the template is ignored.proxy also accepts a destination, used as a base URL with the request path appended. GET /users/42 through {{proxy 'http://other:3000'}} becomes GET http://other:3000/users/42. That lets different branches of one template proxy to different backends.
Hosts: several services, one Mocko
A host block gives a name to an upstream service and matches incoming requests by their Host header. This is how one Mocko instance stands in for several microservices at once:
host "billing" {
name = "Billing Service"
source = "billing.local"
destination = "https://demo-billing.mockoapp.net"
}
mock "GET /invoices/{id}" {
host = "billing"
format = "json"
body = <<-EOF
{ "id": {{request.params.id}}, "status": "past_due" }
EOF
}sourceis the hostname to match on incoming requests.destinationis optional. When set, requests for this host that no mock matches are proxied there automatically, so each host gets its own passthrough backend.- A mock with
host = "billing"only answers requests carrying that host'sHostheader. Mocks without ahostfield answer any host.
In real setups the Host header comes from DNS or service discovery rather than a curl flag: point billing.local at Mocko and the routing is automatic. The Mock Microservices by Host recipe walks through a complete two-service setup.
Templates can proxy to a named host by its slug, which keeps destination URLs out of mock bodies:
mock "GET /passthrough" {
body = "{{proxy 'billing'}}"
}Hosts in the UI
Hosts can also be created and edited in the control panel, alongside mocks. Hosts defined in files are read-only there, and hosts created in the UI follow the same persistence rules as deployed mocks: in-memory by default, durable with Redis.
Behavior details
- Proxied requests time out after 30 seconds by default. Tune it with
-ton the CLI or the equivalent configuration on deployed instances. - A mock's
delayapplies before proxying too, sodelay = 3000plus{{proxy}}simulates a slow but otherwise real backend. - Proxied requests carry
x-forwarded-*headers, and the originalHostheader passes through. - Without a proxy URL, a host destination, or a
{{proxy}}call, unmatched requests return404, as covered in How Matching Works.
Next
One piece of the mock file format remains: shared fixtures. Continue to Data Blocks.