Simulation "Hello, World!"

Overview

The "Hello, World!" example simulation demonstrates how easy it is to model and run API simulations with API Simulator. This simulation is included in the download along with other examples.

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.

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 instead of defining them all in one file. Manageability and usability become more important when simulations get big or simlets have large response payloads.

"Hello, World!" Stub/Mock

  1. Let’s create a directory for our simulation and name it hello-world-sim.

    mkdir hello-world-sim
  2. Create in the hello-world-sim directory a file called apisim.yaml with the following content while making sure the indentation is preserved:

    apisim.yaml
    simlet: 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.

  3. 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!

…​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

apisim.yaml
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.

  1. 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 same apisim.yaml configuration file.

  2. 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:

apisim.yaml
---
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 to get the first value of the name URI query parameter. Add this to apisim.yaml:

apisim.yaml
---
simlet: howdy

request:
- method: GET
- uriPath: /howdy

response:
  from: template
  body: "Howdy, ${ _request.queryParams.first('name') ?: 'Stranger' }!"

The _request object is documented here.

…​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:

apisim.yaml
---
simlet: hey

request:
- method: GET
- uriPath: /hey

Greeting:
  is: parameter
  from: list
  list: [ 'Hi', 'Hello', 'Hey', 'Howdy' ]
  pick: 1

response:
  from: template
  body: ${ Greeting }

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!