89-Nodejs Course 2023: Restful Routes: Introduction
Tags: node, typescript, mongodb, fastify
Published: 2022-12-06 19:41:01

---
title: 89-Nodejs Course 2023: Restful Routes: Introduction
published: true
description: 
series: Nodejs Course 2023
tags: nodejs, typescript, mongodb, fastify
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jkalrxdp4mo1kr7vgem5.png
# Use a ratio of 100:42 for best results.
---

Let's take a break from `Response Resources` and move to another section of our code, let's head back to our beloved router, today we're going to talk about `Restful Routes` and how to implement them in our project.

## Restful Api Concept

So, what is `Restful Api`, you might heard that expression before, but what does it mean? `Restful Api` is a concept that was introduced by `Roy Fielding` in his dissertation, it's a set of rules that we should follow to create a `Restful Api`, the main idea behind this concept is to make our api more `standard` and `consistent`, so that we can easily use it in any project.

## Restful Api Rules

There are 6 rules that we should follow to create a `Restful Api`, let's take a look at them:

1. **Use nouns for the route path**. For example, `/users` instead of `/getAllUsers`.
2. **Use HTTP verbs for the route methods**. For example, `GET` instead of `getAllUsers`.
3. **Use plural nouns for the route path**. For example, `/users` instead of `/user`.
4. **Use query parameters to filter, sort, and paginate collections**. For example, `/users?sort=age&limit=10`.
5. **Use HTTP status codes to represent the status of the response**. For example, `200` for success, `404` for not found, and `500` for server error.
6. **Use snake_case (never camelCase) for query parameters and fields**. For example, `/users?sort_by=age`.

> I prefer camelCase in the last point though, but it's up to you.

## Restful Api Routes

Now that we know the rules, let's take a look at the routes that we should implement in our project, we're going to implement the following routes:

1. `GET /users` to get all users.
2. `GET /users/:id` to get a single user.
3. `POST /users` to create a new user.
4. `PUT /users/:id` to update a user.
5. `DELETE /users/:id` to delete a user.
6. `PATCH /users/:id` to update a user partially.

These are the main routes that we could implement in our restful API per module, but of course we can add any other routes that we need, for example, we can add a route to get the user's posts, or to get the user's comments, or to get the user's friends, etc.

## Restful Api Implementation

We 're going to start our implementation starting from the next article, but this article we need to fix some stuff first as you will get hit with it if you are working with me step by step, inch by inch and code by code.

## Response Body Parser

We have already introduced the [Response Body Parser](https://dev.to/hassanzohdy/85-nodejs-course-2023-response-async-body-parser-1poo) earlier to make any `toJSON` called asynchronous, there are some issues with it, for example `Is.iterable` will loop over `strings` which is definitely not what we want, so we need to fix it, here is the new version of the `Response Body Parser`:

```ts
// src/core/http/response.ts
// ...
  /**
   * Parse the given value
   */
  protected async parse(value: any): Promise<any> {
    // if it is a falsy value, return it
    if (!value || Is.scalar(value)) return value;

    // if it has a `toJSON` method, call it and await the result then return it
    if (value.toJSON) {
      return await value.toJSON();
    }

    // if it is iterable, an array or array-like object then parse each item
    if (Is.iterable(value)) {
      const values = Array.from(value);

      return Promise.all(
        values.map(async (item: any) => {
          return await this.parse(item);
        }),
      );
    }

    // if not plain object, then return it
    if (!Is.plainObject(value)) {
      return value;
    }

    // loop over the object and check if the value and call `parse` on it
    for (const key in value) {
      const subValue = value[key];

      value[key] = await this.parse(subValue);
    }

    return value;
  }
```

What i added here is the `Is.scalar` check, this checks if the value is `string`, `number` or `boolean`, if so then just return it as we are not going to parse it.

I also enhanced the code in the promise all by splitting the `Array.from` to be initialized in a variable, this is to make the code more readable.

## Prevent sending response object to response

As the validator returns a response instance, any middleware also could return a response instance and the router handler of course could do so, then we need to check if the returned output is a response instance, then just return without sending it to the `response.send` method, also to be more consistent, we could also add that check inside the `send` method itself.

```ts
// src/core/http/response.ts

// ...

  /**
   * Send the response
   */
  public async send(data?: any, statusCode?: number) {
    // if the data is a response instance, then just return current response object
    if (data === this) return this;

    if (data) {
      this.currentBody = data;
    }

    // parse the body and make sure it is transformed to sync data instead of async data
    data = await this.parseBody();

    if (statusCode) {
      this.currentStatusCode = statusCode;
    }

    if (!this.currentStatusCode) {
      this.currentStatusCode = 200;
    }
    // ...
  }
```

Now let' update our `request` execute method as well.

```ts
// src/core/http/request.ts


  /**
   * Execute the request
   */
  public async execute() {
    // check for middleware first
    const middlewareOutput = await this.executeMiddleware();

    if (middlewareOutput !== undefined) {
      // 👇🏻 make sure first its not a response instance
      if (middlewareOutput instanceof Response) return;
      // 👇🏻 send the response
      return this.response.send(middlewareOutput);
    }

    const handler = this.route.handler;

    // 👇🏻 check for validation using validateAll helper function
    const validationOutput = await validateAll(
      handler.validation,
      this,
      this.response,
    );

    if (validationOutput !== undefined) {
      // 👇🏻 make sure first its not a response instance
      if (validationOutput instanceof Response) return;
      // 👇🏻 send the response
      return this.response.send(validationOutput);
    }

    // call executingAction event
    this.trigger("executingAction", this.route);
    const output = await handler(this, this.response);

      // 👇🏻 make sure first its not a response instance
    if (output instanceof Response) return;

    // call executedAction event
    this.trigger("executedAction", this.route);

    // 👇🏻 send the response
    await this.response.send(output);
  }
```

Now we're good here. let's update another part of the response as well.

## Not found response

We already have our `notFound` method in the response class, but it is required to send a data to it, this is okay, but we can unify the response by making it optional, so we can call it without sending any data, here is the updated version of the `notFound` method:

```ts
// src/core/http/response.ts

  /**
   * Send a not found response with status code 404
   */
  public notFound(
    data: any = {
      error: "notFound",
    },
  ) {
    return this.send(data, 404);
  }
// ...
```

Why would we do this? because later on, we can enhance it to make it configurable, so we can send a custom not found response, for example, we can send a custom not found json response.

This will apply to `badRequest` method as well, but we'll keep it for now.

## 🎨 Conclusion

So in this article, we have talked about `Restful APIs` and its standards, then we made some enhancements to our `response` class to make it more consistent, and we also made some enhancements to our `request` class to make it more consistent as well.

In our next chapter, we're going to start implementing our `Restful API` and see how to handle it with our router system, stay tuned!

## ☕♨️ Buy me a Coffee ♨️☕

If you enjoy my articles and see it useful to you, you may [buy me a coffee](https://www.paypal.com/paypalme/hassanzohdy), it will help me to keep going and keep creating more content.

## 🚀 Project Repository

You can find the latest updates of this project on [Github](https://github.com/hassanzohdy/nodejs-2023)

## 😍 Join our community

Join our community on [Discord](https://discord.gg/pb2vmdfhGf) to get help and support (Node Js 2023 Channel).

## 🎞️ Video Course (Arabic Voice)

If you want to learn this course in video format, you can find it on [Youtube](https://www.youtube.com/playlist?list=PLGO8ntvxgiZMJc7RN2lIq9WmMOlWZGzmz), the course is in Arabic language.

## 📚 Bonus Content 📚

You may have a look at these articles, it will definitely boost your knowledge and productivity.

General Topics

* [Event Driven Architecture: A Practical Guide in Javascript](https://dev.to/hassanzohdy/event-driven-architecture-the-best-paradigm-that-i-love-to-work-with-in-javascript-and-node-js-1gnk)
* [Best Practices For Case Styles: Camel, Pascal, Snake, and Kebab Case In Node And Javascript](https://dev.to/hassanzohdy/best-practices-for-case-styles-camel-pascal-snake-and-kebab-case-in-node-and-javascript-55oi)
* [After 6 years of practicing MongoDB, Here are my thoughts on MongoDB vs MySQL
](https://dev.to/hassanzohdy/after-6-years-of-practicing-mongodb-here-are-my-thoughts-on-mongodb-vs-mysql-574b)

Packages & Libraries

* [Collections: Your ultimate Javascript Arrays Manager](https://dev.to/hassanzohdy/collections-your-ultimate-javascript-array-handler-3o15)
* [Supportive Is: an elegant utility to check types of values in JavaScript](https://dev.to/hassanzohdy/supportive-is-an-elegant-utility-to-check-types-of-values-in-javascript-1b3e)
* [Localization: An agnostic i18n package to manage localization in your project](https://dev.to/hassanzohdy/mongez-localization-the-simplest-way-to-translate-your-website-regardless-your-favorite-framework-4gi3)

 React Js Packages

* [useFetcher: easiest way to fetch data in React Js](https://dev.to/hassanzohdy/usefetcher-the-easiest-way-to-fetch-data-in-react-45o9)

Courses (Articles)

* [OOP In JS And TS From The Very Beginning](https://dev.to/hassanzohdy/jsts-oop-course-1-introduction-2ld)
* [ES6++: The Ultimate Guide to ES6 and Beyond](https://dev.to/hassanzohdy/es6-1-introduction-h3e)
* [React Js: Let"s Create File Manager With React Js and Node Js](https://dev.to/hassanzohdy/lets-create-a-file-manager-from-scratch-with-react-and-typescript-chapter-i-a-good-way-to-expand-your-experience-5g4k)