Definition

An API for a website is code that allows two software programs to communicate with each other. The API spells out the proper way for a developer to write a program requesting services from an operating system or other application.

A RESTful API is an architectural style for an application program interface (API) that uses HTTP requests to access and use data. That data can be used to GET, PUT, POST and DELETE data types, which refers to the reading, updating, creating and deleting of operations concerning resources.

This is also refered as C.R.U.D process

A RESTful API uses existing HTTP methodologies defined by the RFC 2616 protocol, such as:

What we've learnt

We have been building al-most-RESTful api for the past few days. We focus on GET method to retrieve data and response. Today we will learn more about the rest, especially POST method and the logic to add/edit/delete content in your database

Example

//Create :
app.post("/", createHandler);
//Read
app.get("/", readHandler);
//Update
app.put("/", updateHandler);
//Delete
app.delete("/", deleteHandler);

Before we start

Every A.P.I. will allow us to C.R.U.D. one or more collections of resources,

Additionally, they'll need some reasonable default configurations.

Knowing this, we'll use a template to work more quickly for this project and future projects, specifically one supplied by Express called express generator

Today we'll learn how to generate an express application quickly and easily. In doing so we'll define routes, commonly used middlewares, and structure for our apis.

Important: Today lab will be building on the work that we made previously. So let's quickly go through the existing file.

We have learn how read a file and make a readHandler for our GET route. But that is like one-way communication. Establish a routing rule for CRUD is easy now, the challenges lie within the logic of it handler.

const fs = require("fs");

const content = "Some content!";

fs.writeFile("test.txt", content, (err) => {
  if (err) {
    console.error(err);
    return;
  }
  //file written successfully
});

Alternatively, you can use the synchronous version fs.writeFileSync():

const fs = require("fs");

const content = "Some content!";

try {
  const data = fs.writeFileSync("test.txt", content);
  //file written successfully
} catch (err) {
  console.error(err);
}

By default, this API will replace the contents of the file if it does already exist.

You can modify the default by specifying a flag:

fs.writeFile("/Users/joe/test.txt", content, { flag: "a+" }, (err) => {});

The flags you'll likely use are

(you can find more flags at https://nodejs.org/api/fs.html#fs_file_system_flags)

A handy method to append content to the end of a file is fs.appendFile() (and its fs.appendFileSync() counterpart).

Recalled :Other fs modules

The fs module provides a lot of very useful functionality to access and interact with the file system.

File system method

Effect

fs.access()

check if the file exists and Node.js can access it with its permissions

fs.appendFile()

append data to a file. If the file does not exist, it's created

fs.close()

close a file descriptor

fs.copyFile()

copies a file

fs.mkdir()

create a new folder

fs.readdir()

read the contents of a directory

fs.readFile()

read the content of a file. Related: fs.read()

fs.rename()

rename a file or folder

fs.rmdir()

remove a folder

fs.writeFile()

write data to a file. Related: fs.write()

Read

Most of the time we will be using .json file as database. While reading a .json file could be executed by both changing a file content located in your machine is not as simple

To read a file.

require("/path");
//
require("fs").readFileSync("/path", "utf8", callback);

We may choose the shorter option since, well, it is shorter and easier to understand. However, what we did in the first option is like a one way call, you could get the method and the values however, we cannot send back a changes, update to the data. This is where node fs module comes into play.

Create a file

writeFile and writeFileSync() are the 2 option we have to create a new file. The fs.writeFileSync () is a synchronous method. The fs.writeFileSync () creates a new file if the specified file does not exist

Since we will be working with JSON file, we need to translate our JS object into JSON before write the content to the database

function save({ data, name }) {
  const json = JSON.stringify(data);
  fs.writeFile(`../data/${name}.json`, json, function (err) {
    if (err) return console.log(err);
  });
}

Find and Update/Delete existing document in database

To update/delete something it must be already existed. So before any changes with the file, first thing to do is able to FIND the file and also identify where the changes should be apply

fs.appendFileSync(path, data, [options]);

Structure of this method Parameters:

fs.appendFileSync("example_file.txt", "This is the appended text", {
  encoding: "utf8",
  flag: "w", //default is a
});

Using your previous work You are now require to replace the handler of all routes with approriate logic

Requirement

Enpoints that :

Random hexstring helper

You are provided with a helper function

const crypto = require("crypto");
utilsHelper.generateRandomHexString = (len) => {
  return crypto
    .randomBytes(Math.ceil(len / 2))
    .toString("hex") // convert to hexadecimal format
    .slice(0, len)
    .toUpperCase(); // return required number of characters
};

The Node.js Crypto module supports cryptography. It provides cryptographic functionality that includes a set of wrappers for open SSL's hash HMAC, cipher, decipher, sign and verify functions. They support function offer security for our app.

Discuss with your group :

Group your controllers

Eventhough each ruote method and configuration are different and connected to different handlers. These handlers are usually belong to the same endpoints. It is recommended to group handlers of the same endpoint as controllers of that specific route

Project structure

|- routes/
  |- x.js
|- controllers/
  |- x.js
const xController = {};

xController.doSomething = async (req, res, next) => {
  //logic
  const result = {};
  return res.status(200).send(result); //this will be different if we have SendResponse helper
};

xController.doOtherThing = async (req, res, next) => {
  //logic
  const result = {};
  return res.status(200).send(result); //this will be different if we have SendResponse helper
};

module.exports = xController;
const xController = require("./controllers/x.js");
router.method("/dosomething", xController.doSomething);

const xController = require("./controllers/x.js");
router.method("/doOtherThing", xController.doOtherThing);

Hey there, travelers! if you want to learn everything about Express and RestfulAPI that has not been covered (lots of it), check out the links below to have better understanding of the concepts.