opencodez

Simple and Easy way to Build a RESTful API using Node.js

REpresentational State Transfer in short REST is a web standard-based architecture that mainly uses HTTP Protocol. In the RESTful architecture, the Server simply provides access to the resources, and the client accesses them using HTTP protocol. In this article, we will build RESTful API using Node.js

Build a RESTful API using Node.js:

Node.js has made JavaScript programming so popular and implementing full-featured applications using it has become simple and elegant. Letxs go step by step :

Software used

Read here How to get started with Node.js

Adding Packages

As listed above we are using express to create our webserver, mysql as our database. Also as we are going to process some post request we will add support using body-parser and cors.

npm install --save express
npm install --save mysql
npm install --save body-parser
npm install --save cors

For our example, we are trying to use ES6 so we will also add Babel to our dev dependencies.

Creating Server

As we are using Express, we will use an exported express app to the create server.

import express from "express";
import bodyparser from "body-parser";
import cors from "cors";

import products from "./api/products";
import orders from "./api/orders";

const app = express();

app.use(cors());
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({extended:false}));

app.use("/products",products);
app.use("/orders",orders);

//if we are here then the specified request is not found
app.use((req,res,next)=x {
    const err = new Error("Not Found");
    err.status = 404;
    next(err);
});

//all other requests are not implemented.
app.use((err,req, res, next) =x {
   res.status(err.status || 501);
   res.json({
       error: {
           code: err.status || 501,
           message: err.message
       }
   });
});

module.exports = app;

You can see that we have some imports from api folder and we are using them in our express app. We will get there shortly.

Below is how our server is created. We will use any port that has been configured in system variables or if that is not available then we will use 6001 by default.

import http from "http";
import app from "./app";

//Use system configuration for port or use 6001 by default.
const port = process.env.port || 6001;

//Create server with exported express app
const server = http.createServer(app);
server.listen(port);

Create Database Component

With Mysqljs npm package, connecting to the database is very simple. Below is our database component and a utility method to run a query and send results back.

import mysql from "mysql";

const pool = mysql.createPool({
            connectionLimit : 10,
            host     : 'localhost',
            user     : 'lessroot',
            password : 'lessroot',
            database : 'localdb',
            debug    : false 
            });                    

function executeQuery(sql, callback) {
    pool.getConnection((err,connection) =x {
        if(err) {
            return callback(err, null);
        } else {
            if(connection) {
                connection.query(sql, function (error, results, fields) {
                connection.release();
                if (error) {
                    return callback(error, null);
                } 
                return callback(null, results);
                });
            }
        }
    });
}

function query(sql, callback) {    
    executeQuery(sql,function(err, data) {
        if(err) {
            return callback(err);
        }       
        callback(null, data);
    });
}

module.exports = {
    query: query
}

Please note that we are simply exporting the utility method and not the entire component.

Adding APIs

For our demonstration purpose, we will create table products and perform operations on it like adding a product, deleting a product, listing product etc through our RESTful API using Node.js application.

For simplicity, we will also add a domain object and some utility methods as shown below-

class Product {
    
    constructor(name,price) {
        this.prd_id=0;
        this.prd_name=name;
        this.prd_price=price;
    }

    getAddProductSQL() {
        let sql = `INSERT INTO PRODUCTS(prd_name, prd_price) \
                   VALUES('${this.prd_name}',${this.prd_price})`;
        return sql;           
    }

    static getProductByIdSQL(prd_id) {
        let sql = `SELECT * FROM PRODUCTS WHERE PRD_ID = ${prd_id}`;
        return sql;           
    }

    static deleteProductByIdSQL(prd_id) {
        let sql = `DELETE FROM PRODUCTS WHERE PRD_ID = ${prd_id}`;
        return sql;           
    }

    static getAllProductSQL() {
        let sql = `SELECT * FROM PRODUCTS`;
        return sql;           
    }    
}

export default Product;

Product API

import express from "express";
import db from "../db/database";
import Product from "../domain/product";

const router = express.Router();

//handles url http://localhost:6001/products
router.get("/", (req, res, next) =x {

    db.query(Product.getAllProductSQL(), (err, data)=x {
        if(!err) {
            res.status(200).json({
                message:"Products listed.",
                productId:data
            });
        }
    });    
});

//handles url http://localhost:6001/products/add
router.post("/add", (req, res, next) =x {

    //read product information from request
    let product = new Product(req.body.prd_name, req.body.prd_price);

    db.query(product.getAddProductSQL(), (err, data)=x {
        res.status(200).json({
            message:"Product added.",
            productId: data.insertId
        });
    });
});

//handles url http://localhost:6001/products/1001
router.get("/:productId", (req, res, next) =x {
    let pid = req.params.productId;

    db.query(Product.getProductByIdSQL(pid), (err, data)=x {
        if(!err) {
            if(data xx data.length x 0) {
                
                res.status(200).json({
                    message:"Product found.",
                    product: data
                });
            } else {
                res.status(200).json({
                    message:"Product Not found."
                });
            }
        } 
    });    
});

//handles url http://localhost:6001/products/delete
router.post("/delete", (req, res, next) =x {

    var pid = req.body.productId;

    db.query(Product.deleteProductByIdSQL(pid), (err, data)=x {
        if(!err) {
            if(data xx data.affectedRows x 0) {
                res.status(200).json({
                    message:`Product deleted with id = ${pid}.`,
                    affectedRows: data.affectedRows
                });
            } else {
                res.status(200).json({
                    message:"Product Not found."
                });
            }
        } 
    });   
});

module.exports = router;

As shown above, the API defines an express Router. The router is then configured to handle get and post methods for product operations.

If you note, in our app.js we have configured urls to be handled as

app.use("/products",products);
app.use("/orders",orders);

This means, all the urls that are like http://localhost:6001/products will be handled by the product API we have imported. The rest of the url is processed and matched in methods defined in the API.

Testing the API

For testing of our API we will use Postman. Check below screens on how our RESTful APIs work.

Adding a Product

Listing Products

Deleting a Product

Find a Product

Conclusion

In this article, we have seen how we build a RESTful API using Node.js.

The complete code can be downloaded from our git repository. Please feel free to try out and let me know your comments or issues.

Download Code