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:
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);
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
r+
open the file for reading and writingw+
open the file for reading and writing, positioning the stream at the beginning of the file. The file is created if not existinga
open the file for writing, positioning the stream at the end of the file. The file is created if not existinga+
open the file for reading and writing, positioning the stream at the end of the file. The file is created if not existing(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).
The fs module provides a lot of very useful functionality to access and interact with the file system.
File system method | Effect |
| check if the file exists and Node.js can access it with its permissions |
| append data to a file. If the file does not exist, it's created |
| close a file descriptor |
| copies a file |
| create a new folder |
| read the contents of a directory |
| read the content of a file. Related: |
| rename a file or folder |
| remove a folder |
| write data to a file. Related: |
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.
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);
});
}
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
Enpoints that :
xxx number
of students foundconst 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.
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.