Build a REST API in Deno using MongoDB and Oak

Deno is the new buzzword since its release and we are all over it.

Yash Garudkar
8 min readMay 31, 2020
A background of screen with some code/script and an overlay of Deno logo and MonogoDB logo
Photo by Shahadat Rahman on Unsplash

RESTful API’s have been around for a while, as a developer it’s almost an unwritten rule to learn how to make a REST API when dealing with a new technology. It makes you understand the basics of that technology and makes it easier to dive deep in that technology. As per Wikipedia — ‘RESTful Web services allow the requesting systems to access and manipulate textual representations of Web resources by using a uniform and predefined set of stateless operations’.

In the preceding article we built a basic Deno server and used its weather API to get location specific weather updates in JSON format.

Now it’s time to take a detour and build a RESTful API in Deno using the middleware framework Oak and MongoDB database.

Prerequisites: Make sure you following requirements are met on your system

  1. Deno must be installed on your system.
  2. MongoDB must be installed to handle our database or an online hosted MongoDB will also be fine.
  3. A internet connection is needed for importing functions from deno at runtime.
  4. If you use VS Code make sure you add supporting extension for Deno.
  5. Make sure you have Postman installed on your system. Or else get it at Postman.com

PART 1: Build Deno RESTful API

Now let’s start building our REST API 👨🏻‍💻

Usain Bolt

1. Create a folder name ‘deno-mongo-rest-api’ and create the following folder and file structure

We are a implementing CRUD (Create, Read, Update, Delete) application for a Pizza Shop 🍕

deno-mongo-rest-api
├── app.ts
├── controller
│ └── pizzas.ts
├── db
│ └── mongo.ts
└── routes
└── routes.ts

2. Create a server in app.ts file

The Application wraps the serve() fro http package.

We will add our routes in the two methods .use() and .listen

router.routes() — It allows all the routes defined in the routes.ts file through the router object.

router.allowedMethods() — It allows all the methods used in Oak routing such as GET, POST, PUT, DELETE.

app.ts

3. Create a routes in /routes/router.ts file

We will use /api/v1/ as a version 1 for our API it is the best practice so that we can manage versions in the near future.

  1. router.get(“/”, home) — We use “/” for our home page and return a hello message and routes information. It is always better to return something on the homepage not returning a message makes a bad impression.
  2. router.get(“/api/v1/pizzas”, getPizzas) — In this route we simply fetch the pizzas from our database and return the json object to the client.
  3. router.get(“/api/v1/pizzas/:id”, getPizza) — In this route we fetch only one pizza from the database and return it to the client.
  4. router.post(“/api/v1/pizzas”, addPizza) — Here we use post method to add a new pizza to the database and return message of success to the client.
  5. router.put(“/api/v1/pizzas/:id”, updatePizza) — In this put route update a pizza in the database.
  6. router.delete(“/api/v1/pizzas/:id”, deletePizza) — In this delete route we delete a single pizza from the database.

We import handler functions from /controller/pizzas.ts this is also considered as one of the best practices. We will build the handlers in the 4th step after we design our database handler function in MongoDB.

/routes/routes.ts

4. Configure our MongoDB in /db/mongo.ts

MongoClient is the deno_mongo module we import to access MongoDB functions.

After instantiating the MongoClient function, we connect to the MongoDB database using connectWithUri(URI)

URI is the MongoDB URI that we pass to the connectWithUri() to connect our database. I am using MongoDB on my local machine hence the URI is from the local Mongo URI.

The db variable is an instance of database named “test”, similarly the pizzaObj is the instance of collection in test database named “pizzas”.

And finally we export the pizzaObj so we can import it in our handler to carry out CRUD functions.

/db/mongo.ts

5. Implement handlers in /controller/pizzas.ts

The following code we are about to write in pizzas.ts is a long one, so I recommend reading a single function explanation and then go to the referred line number in the code.

To understand the concepts perfectly, implement a single handler function and test it for only that route, this will reduce any possible errors. For testing instructions below in this article.

We just created our pizzasObj in the mongo.ts file. Lets import that first so we can define CRUD functions.

  1. home — (refer line 3) its the homepage handler function which only one sends a response.body in which we greet our user and display information about our routes.
  2. getPizzas — (refer line 11) this function returns all the pizzas in the database. It uses the pizzaObj.find() to get all the pizzas in the database.
  3. getPizza — (refer line 23) as the name suggests this function returns a singular pizza object from the database. It requests an id from the url which is passed as params. It uses pizzaObj.findOne() which finds the single object in the database. In case there is no object for given id we return a success: false flag and a “no product found” message to the user.
  4. addPizza — (refer line 42) in this function we add a new product into the database. It makes a request with request.body. Here we give a JSON obj though Postman and make a POST request to the route. We use pizzaObj.insertOne() to add the data to the database. If the body does not have any data provided then we return a success: false and message “No data provided” to the user.
  5. updatePizza — (refer line 67) We use this function to update an existing pizza object in the database. It takes a params.id from the url and makes a body request to get data from body that needs to be updated the database for the given object id. If the value of the pizza is updated successfuly in the database we return a success: true flag and a message “Updated pizza”. If the pizza is not updated we return success: false and a message “No product found for the given id”.
  6. deletePizza — (refer lie 97) this function is used to delete a single pizza from the database. It only needs the params.id of the referred pizza obj in the database. Then it passes this id to pizzaObj.deleteOne() which deletes the pizza object referred by given id parameter and returns success: true and a message: “Pizza deleted”. If the pizza is not deleted from database we return success: false and a message “No product found for the given id”.
/controller/pizzas.ts

6. Run the deno run command in the terminal.

Since we are using MongoDB for database and Oak for middleware functions we need to pass some extra parameters in deno run command. This is because Deno is secure by default; no file, network, environment access is granted unless explicitly specified.

Run the following command in the terminal to start your Deno server.

deno run  --allow-net --allow-write --allow-read --allow-plugin --unstable app.ts

After running the command in step six your terminal should throw this message.

Terminal

Now the API is complete and being served on our local machine🎉

PART 2: TESTING OUR API

Testing Our API Using Postman

  1. The drop-down contains all the method to send a request to a particular route.
  2. The send button is used to send a request to a route with the selected method.
How to Postman Basic 1

3. While sending JSON data to a route select Body in Postman and follow the setup according to the following screenshot.

How to Postman 2

Testing Our API

Note: In the testing screenshots given below; the orange color signifies needed environment setup to send a particular request, black is for response received and red is for JSON data we send in the body.

  1. Testing our Homepage at GET ‘/’
Homepage ‘/’

2. Test GET at route ‘/api/v1/pizzas’ it should return following results.

GET ‘/api/v1/pizzas/’

3. Test GET at route /api/v1/pizzas/id’ it should return following results.

Here we pass and id of an object in database, we copy it from the response in above GET request

GET ‘/api/v1/pizzas/id’

4. Test POST at route ‘/api/v1/pizzas’ with the given JSON in body

We have given pizza and price in the body, as necessary.

POST ‘/api/v1/pizzas/’

5. Test PUT at route ‘/api/v1/pizzas/:id’

Here and id is need to select the database object to be updated and the data to be updated through body as required.

PUT ‘/api/v1/pizzas/:id’

5. Test DELETE at route ‘/api/v1/pizzas/:id’

We delete an object in database using this method, the only parameter passed is the id in the url.

DELETE ‘api/v1/pizzas/:id’

That’s it! You now have an api in Deno and MongoDB!

Conclusion

Now that we have built and tested a RESTful API in Deno, MongoDB and Oak, we have learned how a REST API actually works in Deno with MongoDB and it’s significance in back-end web development.

This was a simple CRUD app we made, it is a stepping stone towards more complex applications. You can now build your own solutions and handle request and response.

If you have suggestions please let me know in the comments section🙋‍♂️

Thank You!🖤

Here is the GitHub Repository for all the source code.

--

--