Menu Search Me

Node JS

Created by admin on 2020-12-21

 

References

A good introductory tutorial

https://www.tutorialspoint.com/expressjs/expressjs_middleware.htm

Middleware reference

http://expressjs.com/en/resources/middleware/body-parser.html

covid19-viewer-server-contact-plus

Database integration reference

https://expressjs.com/en/guide/database-integration.html#oracle

What is Express?

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications. It is an open source framework developed and maintained by the Node.js foundation.

A Basic ExpressJS App

var express = require('express');

var app = express();

app.get('/', function(req, res){

   res.send("Hello world!");

});

app.listen(3000);

Running ExpressJS App

Suppose app.js is your app?s starting js, you can start your app as below

node app.js

Suppose you want to see all internal logs used in Express, you can set the DEBUG environment variable to Express.* when starting the app:

DEBUG=express.* node app.js

Express Router

Defining routes like above is very tedious to maintain. To separate the routes from our main index.js file, we will use Express.Router. Create a new file called things.js and type the following in it.

var express = require('express');

var router = express.Router();

 

router.get('/', function(req, res){

   res.send('GET route on things.');

});

router.post('/', function(req, res){

   res.send('POST route on things.');

});

 

//export this router to use in our index.js

module.exports = router;

Now to use this router in our index.js, type in the following before the app.listen function call.

var express = require('Express');

var app = express();

 

var things = require('./things.js');

 

//both index.js and things.js should be in same directory

app.use('/things', things);

 

app.listen(3000);

The app.use function call on route '/things' attaches the things router with this route. Now whatever requests our app gets at the '/things', will be handled by our things.js router. The '/' route in things.js is actually a subroute of '/things'.

Express Middleware

This example summarizes how to use middleware before and after route handler; also how a route handler can be used as a middleware itself.

var express = require('express');

var app = express();

 

//First middleware before response is sent

app.use(function(req, res, next){

   console.log("Start");

   next();

});

 

//Route handler

app.get('/', function(req, res, next){

   res.send("Middle");

   next();

});

 

app.use('/', function(req, res){

   console.log('End');

});

 

app.listen(3000);

When we visit '/' after running this code, we receive the response as "Middle" and on our console, the following:

Start

End

The following diagram summarizes what we have learnt about middleware:

Request received by server -> multiple middleware functions executed (optional) -> route handlers execution -> multiple middleware functions executed (optional) -> response sent to client

ExpressJS Static Files

Static files are files such as image files, static html files, javascript files, css files, etc. that clients download from the server. Express by default does not allow you to serve static files. You need to enable it using the following built-in middleware.

app.use(express.static('public'));

Then you create a new directory, public, under your express project. Express looks up the files relative to the static directory, so the name of the static directory "public" is not part of the URL.

Parsing Request

Body-parser parses incoming request bodies in a middleware before your handlers. we can use the body-parser for parsing application/json and x-www-form-urlencoded header requests.

// index.js

const express = require('express');

const bodyParser = require('body-parser');

 

// for parsing application/json

app.use(bodyParser.json());

// for parsing application/xwww-form-urlencoded

app.use(bodyParser.urlencoded({ extended: true }));

 

app.post('/post-test', (req, res) => {

    console.log('Got body:', req.body);

    res.sendStatus(200);

});

 

app.listen(8080, () => console.log(`Started server at http://localhost:8080!`));

 

$ node index.js

Started server at http://localhost:8080!

Got body: { username: 'scott',

  password: 'secret',

  website: 'stackabuse.com' }

As you can see, after the body-parser runs, the req.body becomes a JavaScript object that you can access.

Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. It is written on top of busboy for maximum efficiency. You can use multer for uploading single as well as multiple files. NOTE: Multer will not process any form which is not multipart (multipart/form-data).

This tutorial gives a good example: https://medium.com/@svibhuti22/file-upload-with-multer-in-node-js-and-express-5bc76073419f

Cookie Handling

var express = require('express');

var app = express();

var cookieParser = require('cookie-parser');

app.use(cookieParser());

 

app.get('/', function(req, res){

   //cookie-parser parses Cookie header and populates req.cookies with an object keyed by the cookie names.

   console.log('Cookies: ', req.cookies);

   //you can also set response cookie, like name = express, with the following code line

   res.cookie('name', 'express');

   //Way 1- Set response cookie that expires after 360000 ms from the time it is set.

   res.cookie(name, 'value', {expire: 360000 + Date.now()});

   //Way 2 - Set response cookie that expires after 360000 ms from the time it is set.

   res.cookie(name, 'value', {maxAge: 360000});

   res.send('cookie set');

});

app.listen(3000);

RESTful API

index.js

var express = require('express');

var bodyParser = require('body-parser');

var multer = require('multer');

var upload = multer();

 

var app = express();

 

app.use(cookieParser());

app.use(bodyParser.json());

app.use(bodyParser.urlencoded({ extended: true }));

app.use(upload.array());

 

//Require the Router we defined in movies.js

var movies = require('./movies.js');

 

//Use the Router on the sub route /movies

app.use('/movies', movies);

 

app.listen(3000);

movies.js

var express = require('express');

var router = express.Router();

var movies = [

   {id: 101, name: "Fight Club", year: 1999, rating: 8.1},

   {id: 102, name: "Inception", year: 2010, rating: 8.7},

   {id: 103, name: "The Dark Knight", year: 2008, rating: 9},

   {id: 104, name: "12 Angry Men", year: 1957, rating: 8.9}

];

router.get('/:id([0-9]{3,})', function(req, res){

   var currMovie = movies.filter(function(movie){

      if(movie.id == req.params.id){

         return true;

      }

   });

  

   if(currMovie.length == 1){

      res.json(currMovie[0])

   } else {

      res.status(404);  //Set status to 404 as movie was not found

      res.json({message: "Not Found"});

   }

});

router.post('/', function(req, res){

   //Check if all fields are provided and are valid:

   if(!req.body.name ||

      !req.body.year.toString().match(/^[0-9]{4}$/g) ||

      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){

      res.status(400);

      res.json({message: "Bad Request"});

   } else {

      var newId = movies[movies.length-1].id+1;

      movies.push({

         id: newId,

         name: req.body.name,

         year: req.body.year,

         rating: req.body.rating

      });

      res.json({message: "New movie created.", location: "/movies/" + newId});

   }

});

 

router.put('/:id', function(req, res) {

   //Check if all fields are provided and are valid:

   if(!req.body.name ||

      !req.body.year.toString().match(/^[0-9]{4}$/g) ||

      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||

      !req.params.id.toString().match(/^[0-9]{3,}$/g)){

      res.status(400);

      res.json({message: "Bad Request"});

   } else {

      //Gets us the index of movie with given id.

      var updateIndex = movies.map(function(movie){

         return movie.id;

      }).indexOf(parseInt(req.params.id));

     

      if(updateIndex === -1){

         //Movie not found, create new

         movies.push({

            id: req.params.id,

            name: req.body.name,

            year: req.body.year,

            rating: req.body.rating

         });

         res.json({

            message: "New movie created.", location: "/movies/" + req.params.id});

      } else {

         //Update existing movie

         movies[updateIndex] = {

            id: req.params.id,

            name: req.body.name,

            year: req.body.year,

            rating: req.body.rating

         };

         res.json({message: "Movie id " + req.params.id + " updated.",

            location: "/movies/" + req.params.id});

      }

   }

});

 

router.delete('/:id', function(req, res){

   var removeIndex = movies.map(function(movie){

      return movie.id;

   }).indexOf(req.params.id); //Gets us the index of movie with given id.

  

   if(removeIndex === -1){

      res.json({message: "Not found"});

   } else {

      movies.splice(removeIndex, 1);

      res.send({message: "Movie id " + req.params.id + " removed."});

   }

});

module.exports = router;

Error Handling Middleware

Error handling in Express can be done using a middleware. The error handling middleware are defined in the same way as other middleware functions, except that error-handling middleware functions MUST have four arguments instead of three ? err, req, res, next.

var express = require('express');

var app = express();

 

app.get('/', function(req, res){

   //This is for testing = to deliberately create an error and pass it to the next function

   var err = new Error("Something went wrong");

   next(err);//this will pass handling to below error handling middleware

});

/*

 * other route handlers and middleware here

 * ....

 */

//An error handling middleware

app.use(function(err, req, res, next) {

   res.status(500);

   res.send("Oops, something went wrong.")

});

 

app.listen(3000);

Winston Logger

Handlebars

Promise based HTTP client (axios)

Database integration