hello-world-sim (1)
└─ simlets (2)
└─ hello-world (3)
Simulation "Hello, World!"
Overview
This is an example demonstrating how easy it is to model and run API simulations with API Simulator.
To be able to run the example you would need API Simulator installed and that is as simple as downloading the distro and unpacking it - see the installation document.
Along with other examples, this example is included in the distro download.
"Hello, World!" Stub
-
Let’s create the following directory structure:
1 hello-world-sim
is the name of the simulation.2 All simlets for the simulation reside under the simlets
directory.3 hello-world
is the directory where we will create the configuration for the "Hello, World!" simlet. -
Place in the
hello-world
directory a file calledsimlet.yaml
with the following content while making sure the indentation is preserved:hello-world/simlet.yamlresponse: from: stub body: "Hello, World!"
Notice that the simlet configuration doesn’t have anything about the request.
The configuration uses the API Simulator’s YAML-based Domain-Specific Language (DSL). You don’t have to learn all of YAML - the DSL only uses few simple concepts: name/value pairs, maps, and lists.
-
Start API Simulator for the
hello-world-sim
simulation (replace/path/to/
appropriately):apisimulator start "/path/to/hello-world-sim"
-
Point your browser to http://localhost:6090/ or use
curl
:curl localhost:6090
In both cases API Simulator replies with
Hello, World!
Because this is how we configured the "Hello, World!" simlet and because the simulation doesn’t have any other simlets yet, API Simulator will actually reply with same response to any request. For example, try in the browser http://localhost:6090/greetings or http://localhost:6090/greetings/Luke, and these 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"
Dynamic Simlets
Replying with the same static 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 extend the current setup and add another directory under
simlets
calledgreetings
and create in it a file namedsimlet.yaml
having the following content (again, make sure the indentation is preserved):greetings/simlet.yamlrequest: - method: GET - where: uriPathPattern matches: /greetings/{name} Name: is: parameter from: uriPathPattern pattern: /greetings/{name} response: from: template body: "Greetings, ${ Name }!"
This is what you should have:
hello-world-sim └─ simlets ├─ greetings │ └─ simlet.yaml └─ hello-world └─ simlet.yaml
-
Start API Simulator for the
hello-world-sim
simulation (replace/path/to/
appropriately):apisimulator start "/path/to/hello-world-sim"
-
Try in your browser to access http://localhost:6090/greetings/Luke and http://localhost:6090/greetings/Princess Leia, or with
curl
:curl -X GET localhost:6090/greetings/Luke Greetings, Luke! curl -X GET localhost:6090/greetings/Princess+Leia Greetings, Princess Leia!
What do you get in reply to http://localhost:6090/greetings/Luke/Skywalker? How about http://localhost:6090/greetings? http://localhost:6090/greetings/?
We can now 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:
request:
- method: GET (1)
- where: uriPathPattern (2)
matches: /greetings/{name}
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 by default 200 OK
.
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.
Add another directory under simlets
called hi
and create a file simlet.yaml
in it with the following content:
request:
- method: GET
- where: uriPath
equals: /hi
Name:
is: parameter
from: uriQueryParameter
named: name
response:
from: template
body: "Hi, ${ Name?.first() ?: 'Stranger' }!"
Start API Simulator for the simulation and try in your browser to access 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?.first() ?: 'Stranger' }
expression in the placeholder.
The request matching rules check for HTTP method of GET
and for the URI path to be equal to /hi
- they don’t check anything about a query parameter named name
. So, a GET /hi
request will be matched regardless of what are the query parameters.
Then the configuration defines the Name
parameter with values (potentially more than one) from URI query parameter named name
.
It could happen that the query parameter named name
is missing in a request or has no value - then the Name
parameter value will be null
. That is why we don’t just output in the body the value of the Name
parameter. We use the expression ${ Name?.first() ?: 'Stranger' }
where ?.
is the Safe Navigation operator and ?:
is the Elvis operator. In essence, if Name
is not null
then the first()
method will be called to return its first value; if the result is not null
then that value will be output, or otherwise Stranger
will be output.
It is to note that the Safe Navigation and Elvis operators make the expression succinct - brief and, yet, clearly expressed. We could have as well used a scriptlet with if…else
statements instead.
Stop API Simulator just like before.
Built-in Request Object
API Simulator has a built-in object - _request
- that we can use in a Simula template to get any component of the request without the need to define a parameter. Here is an example - a simlet called howdy
- that uses the _request
object to get the first value of the name
URI query parameter:
request:
- method: GET
- where: uriPath
equals: /howdy
response:
from: template
body: "Howdy, ${ _request.queryParams.first('name') ?: 'Stranger' }!"
The _request
object is documented here.
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:
request:
- method: GET
- where: uriPath
equals: /hey
Greeting:
is: parameter
from: list
list: [ Hi, Hello, Hey, Howdy ]
pick: 1
response:
from: template
body: ${ Greeting }
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!