Makes API simulation easy and fast.
Sim is straight-forward API simulation tool that's tiny, fast, secure and scalable.
Sim turns OpenAPI specs into executable API specs.
Sim doesn't just mock APIs, it allows you to specify scripts for each API operation which have access to a key-value database that allows APIs to save state between requests.
Most of today's API mocking tools run in virtual machines such as the JVM or NPM. Sim is a single binary with zero dependencies.
- It's orders of magnitude smaller binary and memory usage. Which much lower CPU usage. Each process can simulation multiple APIs.
- Running on Kubernetes? Three pods could simulate every API in your organization with high-availability.
Sim was written with extensive help from AI.
Like jq, sim is a tiny (16Mb) standalone binary. You can download it from
the releases page.
If you're on MacOS, you can use brew:
brew tap kitproj/sim --custom-remote https://github.com/kitproj/sim
brew install simOtherwise, you can use curl:
curl -q https://raw.githubusercontent.com/kitproj/sim/main/install.sh | shWe do not support go install.
As Docker image:
docker run --rm -ti -v examples:/apis ghcr.io/kitproj/simCreate a directory containing files named *.yaml.
Then run:
sim apis
Simulations are described by their API specification. For simple mocking, specify your examples in the OpenAPI spec:
openapi: 3.0.0info:
title: Hello APIversion: 1.0.0servers:
- url: http://localhost:8080paths:
/hello:
get:
responses:
'200':
description: OKcontent:
application/json:
example: { "message": "Hello, world!" }openapi: 3.0.0info:
title: Teapot APIversion: 1.0.0servers:
- url: http://localhost:4040# This script is executed when the spec is loaded.# You can use it to specify global variables and functions that are available to all scripts.x-sim-script: | var status = 418paths:
/teapot:
get:
# This script is executed whenever the request is serviced.# The last variable is the response object.x-sim-script: | response = { "status": status, "headers": { "Teapot": "true" }, "body": { "message": "I'm a teapot" } }responses:
'200':
description: OKopenapi: 3.0.0info:
title: Document APIversion: 1.0.0servers:
- url: http://localhost:4040paths:
/documents:
post:
x-sim-script: | var uuid = randomUUID(); db.put("/documents/" + uuid, request.body) response = { "status": 201, "headers": { "Location": "/documents/" + uuid } }responses:
'200':
description: OKget:
x-sim-script: | response = { "body": db.list("/documents") }responses:
'200':
description: OK/documents/{id}:
get:
parameters:
- name: idin: pathrequired: trueschema:
type: stringx-sim-script: | var document = db.get("/documents/" + request.pathParams.id); if (document) { response = { "body": document } } else { response = { "status": 404, } }responses:
'200':
description: OKdelete:
parameters:
- name: idin: pathrequired: trueschema:
type: stringx-sim-script: | db.delete("/documents/" + request.pathParams.id) response = {}responses:
'204':
description: OKA script can make a HTTP request:
#!/usr/bin/env simopenapi: 3.0.0info:
title: Proxy APIversion: 1.0.0servers:
- url: http://localhost:5050paths:
/proxy:
get:
x-sim-script: | hello = http({"url": "http://localhost:8080/hello"}) response = { "status": hello["status"], "headers": { "Proxy": "true" }, "body": hello.body }responses:
'200':
description: OKYou can make you spec an executable program, add the following line:
#!/usr/bin/env simMake your YAML executable with chmod +x.
In you script you have access to the following:
An object containing the HTTP request, e.g.
{
"method": "PUT",
"path": "/documents/bar",
"pathParams": {
"id": "bar"
},
"queryParams": {
"foo": "bar"
},
"headers": {
"Content-Type": "application/json"
},
"body": {
"baz": "qux"
}
}For example:
varbody=request.body;A function that generates a random UUID. For example:
varuuid=randomUUID();A service that allows you to persist and access data:
// get an object, maybe nullvarvalue=db.get(key);// put an object (idempotent)varexisted=db.put(key,value);// delete an object (idempotent)vardeleted=db.delete(key)// return an array of all objectsvarlist=db.list(keyPrefix);For example:
varobj=db.get("/my-api/"+id)if(obj){response={status: 404}}else{response={body: obj}}