App Development

Configuring Monkeypuzzle - The Monkeypod Virtual API

WillowTree default article featured image

In recent weeks we’ve talked a lot about Monkeypod, our cloud-based API design and virtualization tool that produces beautiful, living API documentation and allows teams of developers to collaborate concurrently to design APIs. Today we’re diving a little deeper and discussing Monkeypuzzle. What does Monkeypuzzle do?  Monkeypuzzle uses the Monkeypod API design to create a virtual API that serves as a nice starting point for developing client side solutions, and API integrations. Out of the box, it creates Json responses based on the Monkeypod models that are populated with random data. But random data is not always ideal. If I make a request like:

GET /users

and the virtual service returns a payload like:

[
...
  {
    "name": "xNq",
    "age": 701329366,
    "date_enrolled": "75770682-04-22T15:02:42.451+0000",
    "pets": [
      "wjZ",
      "hut",
      "BRc"
    ]
  }
...
]

That’s neat, but not as useful as we’d like. Displaying “names” that look like these in our client app isn’t terribly helpful at validating the design. The pets look just as bad as the names, and can’t be used to drive the display of the correct pet icon. The date is very specific, but it’s well over 75 million years into the future, a day the 701 million year old user ‘xNq’ might not even live to see. It would be cool if we had a way to tell Monkeypuzzle how to make the data it returns look a bit more real. Anatomy of a Monkeypuzzle configuration Monkeypuzzle accepts response configurations in a simple Json format. There are three levels of scope to the configuration, becoming progressively narrower with each nested section:

  1. Global - configuration applied when no specific configuration is provided for an element
  2. Model - configuration applied to all properties of a model for which no specific configuration is provided
  3. Property - configuration applied to a specific property of a specific model

So an empty shell configuration would look like this:

{
  //global configuration goes here
  “model1”: {
    //configuration for all of model1’s properties goes here
    “property1”: {
      //configuration specific to property1 of model1 goes here
    }
  }
}

When determining what data the virtual API should generate, Monkeypuzzle will look for configuration for the specific property first, falling back on model configuration, then global configuration and system defaults as needed. Configuration options are provided as key/value pairs where the key is a Monkeypuzzle configuration option, and the value is a value appropriate to the option. As of this writing, the following keys are recognized:

Global Options
mp/response_code one of the response codes configured for this API call in Monkeypod
mp/latency desired latency of response in milliseconds
Any Scope Options
mp/size the length of a string property or element count of an array property
mp/content a valid Monkeypuzzle content descriptor
mp/date_format A formatting string describing how dates should be returned - format follows that of Java SimpleDateFormat

The current list of Monkeypuzzle content descriptors follows:

Key Field type Notes
value[…] any The literal value contained will be returned - e.g. value[foo]
firstname string A random value that looks like a first name
surname string A random value that looks like a surname
fullname string A random value that looks like a full name
enum[value1, value2,…] string, number, date One of the provided enum values selected at random
range[a - b] number, date A value in the provided range randomly selected
positive number A random positive number
negative number A random negative number

Many more content descriptors are in the works, but you get the idea. Configuration examples Some examples are probably warranted at this point. Let’s start with the call above, but now we’ll add a x-mpconfig header that contains the following configuration:

{
  “mp/size”: 5,
  “mp/date_format”: “MM/dd/yyyy”
}

This change results in a response that looks like this:

[
    {
        "name": "xNZpw",
        "age": 466524564,
        "date_enrolled": "12/12/213249329",
        "pets": [
            "ByLDe",
            "agnkl",
            "OoHTF",
            "wcjvm",
            "VrjTm"
        ]
    },
// 4 more user records here
]

OK, that’s a bit better. We set the config option ‘mp/date_format’, and now the date values are more readable, if still ridiculous. We also set the ‘mp/size’ config option to be 5 at a global level. Because no models or properties have override values for ‘mp/size’, the size 5 applies to everything: we get 5 users back, their names have five characters, they each have 5 pets, and each pet has 5 characters in its name. Let’s make the names look more like names, the pets look more like pets, and limit it to 2 pets per user. We’ll change the config to the following:

{
  “mp/size”: 5,
  “mp/date_format”: “MM/dd/yyyy”,
  “user”: {
    “name” {
      “mp/content”: “fullname”
    },
    “pets”: {
      “mp/size”: 2,
      “mp/content”: “firstname”
    }
  }
}

We added a nested configuration object for the ‘user’ model, which is the only model in this example, and within that model added property specific configuration objects for the ‘name’ and ‘pets’ properties. This config changes the output to something like the following:

[
    {
        "name": "Chase Johnson",
        "age": 840729707,
        "date_enrolled": "04/19/68874978",
        "pets": [
            "dog",
            "fish"
        ]
    }
// 4 more user records
]

We used the ‘fullname’ Monkeypuzzle content descriptor to get some name-like values for the users. And we limited the pets to 2 per user and selected their values at random from the provided enum. Just like that our response looks much more “real”. Now let’s wrap things up by constraining the ‘age’ values to likely human ages, and the ‘date’ values to something a bit more familiar. To accomplish this change, we’ll use the ‘range’ Monkeypuzzle content descriptor:

{
  “mp/size”: 5,
  “mp/date_format”: “MM/dd/yyyy”,
  “user”: {
    “name” {
      “mp/content”: “fullname”
    },
    “pets”: {
      “mp/size”: 2,
      “mp/content”: “firstname”
    },
    “age”: {
      “mp/content”: “range[13-93]”
    },
    “date_enrolled”: {
      “mp/content”: “range[last Wednesday-yesterday]”
    }
  }
}

And now the response looks like:

[
    {
        "name": "Barbara Tanner",
        "age": 49,
        "date_enrolled": "10/10/2014",
        "pets": [
            "cat",
            "dog"
        ]
    }
// 4 more users here
]

That’s a pretty “real” looking response, and will let our client app developers build something they can demo without having to explain why all the values are ridiculous.   It’s worth pointing out the values used in the ‘range’ content descriptor for the date_enrolled. The system will take date values in many different formats, both absolute and relative, so you can do all sorts of cute things like ‘last Wednesday’ or ‘tomorrow’ as well as dates like ‘Dec 2 1983’. Play around with it to see what else works. Combining and Overriding Configurations It’s flexible and powerful to be able to provide custom response configuration with each request. Application developers can write suites of integration tests while developing against Monkeypod and later use those same tests to validate the API implementation. But in some cases, you may want to set some configuration options that persist over a number of requests. Monkeypod can do that too. By issuing a PUT to https://monkeypod.io/mpapi/monkeypuzzle/responseconfigs/ORGKEY/PROJECTKEY/ with a body containing a Monkeypuzzle config, that config will be saved and applied to every request made to the project. If an additional config is provided in the x-mpconfig header, the request configuration will be combined with the saved project configuration, overriding any configuration options that are provided in both. Coming Soon Look for lots of new ways to simulate different scenarios in the virtual API in the coming weeks. If you have any ideas or use cases you’d like to see supported, let us know. Monkeypod is by API developers, for API developers, so your feedback is always welcome. If you haven’t already, sign up for the Monkeypod private Beta at https://monkeypod.ioQuestions, comments and feedback will be eagerly read when sent to support@monkeypod.ioAnd please follow us on Twitter for all the news and updates twitter.com/monkeypodio

Quickstart-Guide-to-Kotlin-Multiplatform

A Quick Start Guide to Kotlin Multiplatform

Kotlin Multiplatform, though still experimental, is a great up-and-coming solution...

Read the article