mkdir hello-world-sim
Simulation "Hello, World!"
Overview
The "Hello, World!" example demonstrates how easy it is to model and run API simulations with API Simulator. It starts with modeling a simlet that returns static response to any request and moves onto simlets, which produce simple dynamic responses. The simulation is included in the download along with other examples.
This "Hello, World!" simulation has only few simlets so we are going to model them in a single configuration file. You have a choice with API Simulator - there is also a more structured way to organize simlets than defining them all in one file. That helps with manageability and usability when simulations get big or simlets have large response payloads.
Prerequisites
Install API Simulator first if you want to run the simulation. Installation is as simple as downloading the distro and unpacking it - see the documentation here.
"Hello, World!" Stub/Mock
-
Let’s create a directory for our simulation and name it
hello-world-sim
. -
Create in the
hello-world-sim
directory a file calledapisim.yaml
with the following content while making sure the indentation is preserved:apisim.yamlsimlet: hello-world response: from: stub body: "Hello, World!"
The configuration is in API Simulator’s Domain-Specific Language (DSL). The DSL, a subset of YAML, uses few simple concepts: name/value pairs, maps, and lists. Just like JSON. It is very easy to read and write.
-
Start API Simulator for the
hello-world-sim
simulation (replace/path/to/
appropriately):apisimulator start "/path/to/hello-world-sim"
Now point your browser to http://localhost:6090/ or execute this with cURL:
curl localhost:6090
In both cases API Simulator replies with
Hello, World!
Let’s try few more in the browser:
http://localhost:6090/greetings
http://localhost:6090/greetings/Luke
http://localhost:6090/hi
…or using curl
:
curl localhost:6090/greetings
Hello, World!
curl -X POST localhost:6090/greetings
Hello, World!
curl -X GET localhost:6090/greetings/Luke
Hello, World!
curl localhost:6090/hi
Hello, World!
The same Hello, World!
response comes back every time.
Execute this command to stop API Simulator (replace /path/to/
appropriately):
apisimulator stop "/path/to/hello-world-sim"
The Explanation
simlet: hello-world
response:
from: stub
body: "Hello, World!"
The simlet configuration does not have anything about the request. For this reason, the simlet matches any and all requests. Given that there are no other simlets configured yet for the simulation, API Simulator will reply to any request with the response defined in this hello-world
simlet. The response, Hello, World!
, is from a stub - it is static and doesn’t change between requests. There is no HTTP status code configured explicitly so API Simulator will return 200 OK
by default.
Dynamic Simlets
Replying with the same static, stubbed Hello, World!
response every time may be OK for some use cases but often times we need more than that. How about an API simlet where we pass in a name and API Simulator greets us using that name?
Name from Path Variable
This simlet will handle requests where the name comes from a path variable.
-
Let’s add the following to
apisim.yaml
(again, make sure the indentation is preserved):apisim.yaml--- simlet: greetings request: - method: GET - uriPathPattern: /greetings/{name} Name: is: parameter from: uriPathPattern pattern: /greetings/{name} response: from: template body: "Greetings, ${ Name }!"
The three dashes on a single line
---
is a separator between simlets defined in the sameapisim.yaml
configuration file. -
Start API Simulator for the
hello-world-sim
simulation (replace/path/to/
appropriately):apisimulator start "/path/to/hello-world-sim"
Access with your browser http://localhost:6090/greetings/Luke and http://localhost:6090/greetings/Princess Leia, or execute with curl
:
curl -X GET localhost:6090/greetings/Luke
Greetings, Luke!
curl -X GET localhost:6090/greetings/Princess+Leia
Greetings, Princess Leia!
Stop the API Simulator instance (replace /path/to/
appropriately):
apisimulator stop "/path/to/hello-world-sim"
The Explanation
Let’s take a look at each part of the simlet configuration:
simlet: greetings
request:
- method: GET (1)
- uriPathPattern: /greetings/{name} (2)
Name: (3)
is: parameter
from: uriPathPattern
pattern: /greetings/{name}
response:
from: template (4)
body: "Greetings, ${ Name }!" (5)
1 | The greetings simlet matches requests that use the HTTP GET method. |
2 | In addition, requests' URI path must match the pattern /greetings/{name} . The pattern describes URI path that starts with /greetings/ and has one non-empty path segment {name} ; how the segment is called isn’t important. |
3 | The simlet configuration defines a parameter - Name - which value comes from the URI path pattern /greetings/{name} , so it gets the value of whatever is in the {name} path segment after /greetings/ . |
4 | The response is rendered from a template. By default, the template is an API Simulator Simula template. |
5 | The response body has a placeholder - ${ Name } . The placeholder is resolved (substituted, interpolated) using the value of the Name parameter. |
There is no HTTP status code configured explicitly so API Simulator will return 200 OK
by default.
The response to a request that doesn’t match the greetings
simlet is rendered and returned according to the definition of the hello-world
simlet because the hello-world
simlet matches any and all requests that are not matched by another simlet with concrete request-matching rules.
Name from Query Parameter
It is also very easy to extract the name for the greeting from a URI query parameter. Let’s model a simlet for that.
Append to the bottom of apisim.yaml
the following simlet definition:
---
simlet: hi
request:
- method: GET
- uriPath: /hi
Name:
is: parameter
from: uriQueryParameter
named: name
response:
from: template
body: "Hi, ${ Name && Name.first() ? Name.first() : 'Stranger' }!"
Start API Simulator for the simulation and access in your browser http://localhost:6090/hi?name=Luke and http://localhost:6090/hi?name=Princess Leia, or with curl
:
curl -X GET localhost:6090/hi?name=Luke
Hi, Luke!
curl -X GET localhost:6090/hi?name=Princess+Leia
Hi, Princess Leia!
What if we don’t pass a value for the name parameter or don’t pass name parameter at all? If the HTTP method is GET
and the URI is /hi
, we would get Hi, Stranger!
. Try in your browser http://localhost:6090/hi?name= and http://localhost:6090/hi, or with curl
:
curl -X GET localhost:6090/hi?name=
Hi, Stranger!
curl -X GET localhost:6090/hi
Hi, Stranger!
Let’s see why is that and what is this Name && Name.first() ? Name.first() : 'Stranger'
expression in the ${}
placeholder.
The Explanation
The request matching rules check for HTTP method of GET
and for the URI path to be equal to /hi
. On purpose - to show more advance capabilities - they don’t check anything about a query parameter named name
. So, a GET /hi
request will be a match regardless of what the URI query parameters are.
Then the configuration defines the Name
parameter with values (potentially more than one) from URI query parameter named name
.
It could happen that URI query parameter named name
is missing, in which case the Name
parameter value will be null
, or is present but has no value. That is why we don’t just output in the body the value of the Name
parameter but use the expression Name && Name.first() ? Name.first() : 'Stranger'
- "if Name is not null and has at least one value then output the first value; otherwise output the string 'Stranger'".
We could also use a placeholder with shorter expression: ${ Name?.first() ?: 'Stranger' }
. In the expression, ?.
is the Safe Navigation operator and ?:
is the Elvis operator. The Safe Navigation and Elvis operators make the expression succinct - brief and, arguably, clearly expressed.
Another option is to use a scriptlet with if…else
statements. You have choices with API Simulator - use the one that suites your style.
Stop API Simulator just like before.
Built-in Request Object
API Simulator has a built-in object - _request
. We can use it in a Simula template to get any component of the request without the need to define a parameter first.
Below is an example - a simlet called howdy
- that uses the _request
object in a placeholder to get the first value of the name
URI query parameter. The _request
object is documented here.
Add this to apisim.yaml
:
---
simlet: howdy
request:
- method: GET
- uriPath: /howdy
response:
from: template
body: "Howdy, ${ _request.queryParams.first('name') ?: 'Stranger' }!"
Start API Simulator like before and try in your browser:
http://localhost:6090/howdy?name=Luke
http://localhost:6090/howdy?name=Princess Leia
http://localhost:6090/howdy?name=
http://localhost:6090/howdy
…or with curl
:
curl -X GET localhost:6090/howdy?name=Luke
Howdy, Luke!
curl -X GET localhost:6090/howdy?name=Princess+Leia
Howdy, Princess Leia!
curl -X GET localhost:6090/howdy?name=
Howdy, Stranger!
curl -X GET localhost:6090/howdy
Howdy, Stranger!
Stop API Simulator.
Random Greeting
Let’s have more fun! How about a simlet that replies with a random greeting to an informal "hey"? Here is the hey
simlet:
---
simlet: hey
request:
- method: GET
- uriPath: /hey
Greeting:
is: parameter
from: list
list: [ 'Hi', 'Hello', 'Hey', 'Howdy' ]
pick: 1
response:
from: template
body: ${ Greeting }
It is to notice that API Simulator also supports external files as source of list elements to allow the loading of larger lists or for sharing lists between simlets (e.g. names to choose randomly from).
Start API Simulator for the simulation and reload in your browser multiple times http://localhost:6090/hey, or execute this curl
command repeatedly:
curl -X GET localhost:6090/hey
The response from the simlet will be the value of the Greeting
parameter - one randomly picked value from the list upon each execution of the simlet.
In Conclusion
Using API Simulator’s YAML DSL, we modeled in no time an API simulation with simlets for static and dynamic responses. We started an API Simulator instance locally and exercised the functionality of the API simulation.
This only scratches the surface of what is possible with API Simulator. We invite you to learn more about API Simulator, download and install it, run the examples found in the distro… Why not even create API simulations to help your own testing and development?
We would love to hear your feedback! Shoot us a quick email to [feedback at APISimulator.com] to let us know what you think.
Happy API Simulating!