Mocking your own RESTful APIs on Sandbox

Mohamed Hassanin
Sep 5, 2018 · 7 min read

Are you a Frontend/Mobile Developer who always says “We have a bottleneck because of the Backend” ? 😇.. Well, you can’t use this excuse anymore 😒, because now you can be your own Backend Developer with just some basic programming knowledge (Which you should possess if you’re a Frontend/Mobile Developer). 🤷‍♂️

Maybe I did…

The most popular types of APIs or Webservices are of course REST and SOAP, but we’re gonna focus only on RESTful APIs on this article because remind me again when was the last time you used SOAP ? 🤔(You can check this Infographic to know the difference between REST and SOAP and when it’s better to use any of them).


Let me introduce an amazing tool called Sandbox. (https://getsandbox.com)

The tool simply gives you the ability to create your own very sophisticated APIs on the cloud and even allows you to manipulate an on-the-fly Database.

Pretty damn serious

Sandbox provides you with the option to import the APIs represented with one of the following options, and you can alter/extend them as you wish.

We’ll go with the option Blank for now, just because I wouldn’t even have to be here if I happen to have a Swagger. 🤦‍♂️


Getting Started

When you choose option Blank, it’s not as blank as you think, Sandbox actually creates 4 template APIs for you.

Unfortunately, it’s not your lucky day as we’re going to delete all the templates from the “x” button on the right side and start everything from scratch..

Because you know..

Give a Man a Fish, and You Feed Him for a Day. Teach a Man To Fish, and You Feed Him for a Lifetime

Sandbox Default Dashboard, remove the template APIs by clicking on the “x” button on the right side of each API

After deleting everything, let’s create our own APIs by clicking on “Add new route”

You will find a template request for you, let’s just call our API “status” by adding it to the Path and leave everything with the default so that it would be a REST GET API with Content-type: application/json and then click Create.

Sandboxes are run in the cloud so changes you make are automatically and instantly deployed.

Sample GET API

The API as you can tell returns a simple json response saying that status is OK

Your mock services are made available at your unique URL which is your Sandbox name appended with . Open a terminal:

$curl -X GET -H "Content-Type: application/json" http://{{ your-sandbox-name }}.getsandbox.com/status

And you’ll get this response:

{ "status": "ok" }

And Voilà! You have created your first API


HTTP Request Handling

At some point you need to achieve more things that just knowing that status is OK, So we have to make our APIs a little bit more dynamic.

Sandbox gives you full control on the generated Javascript code for each API you create using the wizard.. Wait, What! Javascript?

Yes, it’s that language you hated most at college. But guess what? not anymore!

HTTP request messages are handled by defining requests using and providing a URL path, HTTP method and a callback function that holds the request and the response objects. For example:

Sandbox.define('/users', 'GET', function(req, res) {...}

or for a POST method:

Sandbox.define('/users', 'POST', function(req, res) {...}

The Request (req) object contains all the data attached to the coming request like headers, body and parameters. and we then use the Response (res) object to build responses to the request.

Let’s do something useful then… 💪

Create a new GET route and call it /users, edit the route and replace the Route Definition with the below code..

var users = [{
username: "user1",
email: "user1@mydomain.com"
}, {
username: "user2",
email: "user2@mydomain.com"
}]
return res.json(users)

Keep in mind that you’re already inside the implementation of the block so you already have access to and objects

Click Update and let’s try our new request in terminal

$curl -X GET -H "Content-Type: application/json" http://{{ your-sandbox-name }}.getsandbox.com/users

and you get the following response:

{"username": "user1","email": "user1@mydomain.com"},{"username": "user2","email": "user2@mydomain.com"}

Pretty easy, huh ?

Piece of Cake

Let’s add support for filters based on the user’s age using Query Parameters, is an object containing the parsed request query string, so if we submit a request of we can access the age value inside the block by

Extend your GET users API Route Definition like below..

var users = [{
username: "user1",
email: "user1@mydomain.com",
age: 30
}, {
username: "user2",
email: "user2@mydomain.com",
age: 26
}]
if (req.query.age) {
// convert req.query.age from String to a Number before filtering
return res.json(_.filter(users, { 'age': Number(req.query.age) }))
}
return res.json(users)

We here used a LoDash function (a.k.a Higher Order Functions in Swift) which is to filter the users array according to the age that’s matching the number in the query parameter.

Let’s give it a try:

$curl -X GET -H "Content-Type: application/json" http://{{ your-sandbox-name }}.getsandbox.com/users?age=26

We get:

{"username": "user2","email": "user2@mydomain.com","age": 26}

Also Route/Path parameters can be used in GET requests, let’s create a new GET route on Sandbox and call it the object will then contain the property mapped to the named path parameter, so in this case the username value for the request would be in

Replace the route definition with the below code:

var users = [{
username: "user1",
email: "user1@mydomain.com",
age: 30
}, {
username: "user2",
email: "user2@mydomain.com",
age: 26
}]
// respond with the user or an empty object if user doesnt exist
return res.json(_.find(users, { 'username': req.params.username }) || {})

Here we used the LoDash function to query the array for a username matching our path parameter.

Let’s try it again:

$curl -X GET -H "Content-Type: application/json" http://{{ your-sandbox-name }}.getsandbox.com/users/user1

Response:

{"username": "user1","email": "user1@mydomain.com","age": 30}

By default, all responses return a 200. If a number is provided as the only parameter to a response body string is assigned for you. For example, 400 will respond with "Bad Request". We've specified a custom error message in the below example.

res.json(400, { error: { message: "A custom error message" } })

Stateful Responses

In order to have a well integrated system, we need to make our APIs more dynamic and not just sending canned responses.

For this, Sandbox provides a global object for persisting data.

Let’s create a new POST route and call it

Edit the route and select “View in full code editor” from the Route Definition.

A new editor will open with a main.js file, locate the implementation of the newly created route and replace it with..

// create state.users if it doesn't exist
state.users = state.users || []
Sandbox.define('/users', 'POST', function(req, res) {
// validate username is present
if (req.body.username === undefined) {
return res.json(400, { status: "error", details: "Missing username" })
}
state.users.push(req.body)return res.json({status: "ok"})})

We initialize the object before all the routes to make sure it’s always accessible, think of it as a Database on-the-fly.

Try it:

$curl -X POST -d '{"username":"user3"}' -H "Content-Type: application/json" http://{{ your-sandbox-name }}.getsandbox.com/users

You get:

{"status": "ok"}

Time to update our GET APIs accordingly so it will also read from the object and not the canned array we already created.

Sandbox.define('/users', 'GET', function(req, res) {
if (req.query.age)
{
// convert req.query.age from String to a Number before comparing
return res.json(_.filter(state.users, { 'age': Number(req.query.age) }))
}
return res.json(state.users)
}) Sandbox.define('/users/{username}', 'GET', function(req, res) {
var user = _.find(state.users, { 'username': req.params.username })
// respond with 404 if user isn't found
if (!user)
{
return res.json(404, { error: { message: 'User doesnt exist' } })
}
return res.json(user)})

By now you might become so proud that you were able to create this sophisticated system but you didn’t realize you’ve added too many dummy users.. Uh oh! 😏

Time to delete some users from the object.. Add the following API to your main.js file

Sandbox.define('/users/{username}', 'DELETE', function(req, res) {
var user = _.find(state.users, { 'username': req.params.username })
if (!user)
{
return res.json(404, { error: { mesage: 'User doesnt exist'} })
}
// use Lodash reject to remove the user
state.users = _.reject(state.users, { 'username': req.params.username })
return res.json({status: 'ok'})
})

We use the LoDash fuction to remove user from

$curl -X "DELETE"  http://{{ your-sandbox-name }}.getsandbox.com/users/user3

Last but not least, we add an update API to update an existing User using the LoDash

Sandbox.define('/users/{username}', 'PUT', function(req, res) {
var user = _.find(state.users, { username: req.params.username })
if (!user)
{
return res.json(404, { error: { message: 'User doesnt exist' }})
}
// update the user object
_.merge(user, req.body)
// drop the user and subsequently readd
state.users = _.reject(state.users, { username: req.params.username })
state.users.push(user) return res.json({ status: 'ok'})
})

Give it a go:

$curl -X PUT -d '{"username":"updateduser", "email": "updateduser@mydomain.com"}' -H "Content-Type: application/json" http://{{ your-sandbox-name }}.getsandbox.com/users/user3

Then try executing the GET you will find amazing results!

There are still lots of other features that Sandbox can support like: Adding delay to responses and Authentication, but that’s a topic for another day….

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade