Tuesday, June 23, 2020

Express JS framework for NodeJs development

As per the site Express is :- Fast, unopinionated, minimalist web framework for Node.js. In short it is a framework for developing web and mobile development using nodejs. It also help in creating robust API framework with good performance and secure.

There are many other framework avaialable in addition to ExpressJS  like NestJS, Feather,Sails etc.

Please refer to
https://expressjs.com/en/resources/frameworks.html

Lets setup the express for our application in nodeJS. FYI I am using VSCode as an IDE.
1- First create a package.json file using
npm init
2- we need to install it using below command. you can also follow https://expressjs.com/en/starter/installing.html
npm install express --save
3- We will also add nodemon for quick development and auto refresh of the server using  https://www.npmjs.com/package/nodemon
npm install -g nodemon
4- Lets create first express nodejs application hello world as shown below

//Aquire express module
const express = require('express')
//create app using express function
const app = express()
const port = 3000

//getting ready for accepting GET request on URL "/" and sending hellow world response
app.get('/', (req, res) => res.send('Hello World!'))

//Listen to the port that is define along with the console log that indicate starting of the server.
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))

check the browser hitting url http://localhost:3000/ you will be able to see hello world on the browser.



2-Express Template Engine Basic Introduction

Express frame work give us many UI template to display the runtime data on the screen web/mobile using nodejs. Few of them are pug, jade etc. You can find list of the template on this location supported by expressjs.

https://expressjs.com/en/resources/template-engines.html


We will discuss few of them
1- pug
To use this first we need to install pug view using command
npm install pug --save

once it is installed use below line to inform express to indicate which engine need to be used for rendring page on ui.

app.set('view engine', 'pug')


Whole code:-
//Aquire the express
const express = require('express');
//Create the App from the express
const app = express();
//Indicate the express which engine need to be taken for rendring the ui.
app.set('view engine', 'pug')
//indicating the port on which the nodejs application will listen.
const port = 3000;

//shows the url on which it will take the request
app.get('/', (req, res) => { res.render('index', { titlename: 'Hey', bodymessage: 'Hello there!' }) })

//listening the port
app.listen(port, () => { Console.log(`Server started at the port ${port}`) })

Now we need to defind index.pug file as shown below
html
  head
    title= titlename
  body
    h1= bodymessage

Now lets run the applications and check the url using command


3- Basic and Advance Routing in express and node.js

In express routing is handled in simple format
app.METHOD(PATH, HANDLER)
depending on the path we suggest we have different PATH depending of he path our request can be bifergated. Also depending upon the METHOD we can bifergate get,put,post,delete etc.

few of the example are:-

Respond to GET request on the root route (/)
app.get('/', function (req, res) {
  
})
Respond to POST request on the root route (/)

app.post('/', function (req, res) {
  
})

Respond to a PUT request to the /user route:
app.put('/user', function (req, res) {
  
})

Respond to a DELETE request to the /user route:
app.delete('/user', function (req, res) {
  
})

Lets create one small application that will demonstrate the different routing

//Aquire express module
const express = require('express')
//create app using express function
const app = express()
const port = 3000

//getting ready for accepting GET request on URL "/" and sending hellow world response
app.get('/', (req, res) => res.send('Get request on /'))

app.post('/', (req, res) => res.send('Post request on /'))

app.put('/user', (req, res) => res.send('Put Request on /'))

app.delete('/employee', (req, res) => res.send('Delete request on /'))

//Listen to the port that is define along with the console log that indicate starting of the server.
app.listen(port, () => console.log(`Example app listening at http:localhost:${port}`))


try to hit all the url using postman and check the response and you will find we can easily rout the request to respective

Also please do visit to below site which will give you details of Advance routing

https://expressjs.com/en/guide/routing.html

i.e.
This route path will match acd and abcd. i.e. b will be there or not. it is not mandate.
app.get('/ab?cd', function (req, res) {
 })

This route path will match abcd, abbcd, abbbcd, and so on. i.e. we can have as many b as it is possible
app.get('/ab+cd', function (req, res) {
 )

This route path will match abcd, abxcd, abRANDOMcd, ab123cd, and so on.i.e. any thing between b and c
app.get('/ab*cd', function (req, res) {

})

This route path will match /abe and /abcde. i.e. cd may or may not be there in the url.

app.get('/ab(cd)?e', function (req, res) {
})

we can also use regular expression 
This route path will match anything with an “a” in it.

app.get(/a/, function (req, res) {  
  })

This route path will match butterfly and dragonfly, but not butterflyman, dragonflyman, and so on.
app.get(/.*fly$/, function (req, res) {
})

Using Rout parameters
Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }

app.get('/users/:userId/books/:bookId', function (req, res) {
  res.send(req.params)
})

We can use - and . also in the url.


app.get('/flights/:from-:to', function (req, res) {
    console.log(req.params.from, req.params.to)
    res.send(req.params)
})
hit this url :- http://localhost:3000/flights/sid-dhu
Output :- {"from":"sid","to":"dhu"}


app.get('/plantae/:genus.:species', function (req, res) {
    console.log(req.params.genus, req.params.species)
    res.send(req.params)
})

hit this url :- http://localhost:3000/plantae/sid.dhu
Output :- {"genus":"sid","species":"dhu"}


ExpressJs also support chainable route handlers for a route path by using app.route().

Using app.route() we can create path at a single location

app.route('/book')
  .get(function (req, res) {
    res.send('Get a random book')
  })
  .post(function (req, res) {
    res.send('Add a book')
  })
  .put(function (req, res) {
    res.send('Update the book')
  })

 
We can also create router handlers that can be easily mounted to any component using express.Router

This means we can have a seperate js file that will be treated as a router module for your application. Lets do it

expressrouter.js 

var express = require('express')
var router = express.Router()

//middleware that is specific to this router
//We will learn middle ware in details in next chapte. For now just remember it is the additional funtionality that we want to introduced
//as a middle men before the reques is executed.
router.use(function timeLog (req, res, next) {
  console.log('Time: ', Date.now())
  next()
})
// define the home page route
router.get('/', function (req, res) {
  res.send('home page')
})
// define the about route
router.get('/about', function (req, res) {
  res.send('About Pages')
})
// define the siddhu route
router.get('/siddhu', function (req, res) {
  res.send('Siddhu Pages')
})
module.exports = router 

now lets add this rounter class in our main app.js

like this

var expressrouter = require('./expressrouter')
app.use('/expressrouter', expressrouter)


Now start your nodejs
PS C:\Visual_Source_Code_WorkSpace_NodeJS\expressjsexample\component\router> nodemon .\app.js


hit :- http://localhost:3000/expressrouter
Output on browser :- home page

hit :- http://localhost:3000/expressrouter/siddhu
Output on browser :- Siddhu Pages


So in short we have two Router
1- Basic
2- Advance - AWCR

In basic we can differentiate routing using app.METHOD(PATH, HANDLER) where METHOD can be GET,PUT,POST,PATCH etc and PATH  can be your url path. HANDLER can be function with req and res as parameters.

In advance we have concept like

'- app.all - We can use app.all instead of defining request for get,put,post etc
'- Wild card - we can use *, ?, //, ./$
'- handling more than one call back functions using next() and array
'- app.route() - create chainable route handlers for a route path by using app.route()
'- express.Router :- we can have module base router.

For more details visit to site
https://expressjs.com/en/guide/routing.html



4- Serving static files in Express

We can use belwo command to  load the static files such as image, css, defualt html 404 etc using below comments
express.static(root, [options])

By using below middleware command we load all the files from folder public.

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

After doing this we can directly access the static files using direct url
i.e.
http://localhost:3000/images/XYZ.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
we can also create a virtual path using for security i.e. if we want to hide the original path of our files from url we can give virtual path as in below we have given name as static which did not exist

app.use('/xyzpath', express.static('public'))

After this we can access images and css files.

http://localhost:3000/xyzpath/images/XYZ.jpg
http://localhost:3000/xyzpath/css/style.css
http://localhost:3000/xyzpath/js/app.js

download :- https://github.com/shdhumale/expressjsexample

5- MiddleWare concept in Express

Middleware functions access to the request and  response object and then after doing some function on it transfer it to next function using next(). Next will always invoked, executes the middleware succeeding the current middleware.

Middleware functions can perform the following tasks:

'- Execute any code written inside it
'- Make changes to the request and the response objects.
'- End the request-response cycle.
'- Call the next middleware in the stack.

we can use the middleware function in three ways

1- using use() method
2- we can directly us it in rounting between path and hanlder i.e. app.METHOD(PATH, MIDDLEWARE , HANDLER). This MIDDLEWARE can be an array also.
i.e. app.get('/', requestTime, function (req, res) or app.get('/', [requestTime], function (req, res)

Uses:- Middle ware can be use espicially for validation, cookies verification , loggers or anyother function which we want to execute before our main

There are many ways/level/postions we can use middleware

1-Application-level middleware :- this are the middleware defined at the app level using key word as app.use()
2-Router-level middleware :- this are the middleware definded at the router level i.e. var router = express.Router() and then expose using module.exports = router . And finally those js which want to use it has to required it and use it using app.use()
3-Error-handling middleware - This are the middleware used to handle the err it is thrown using var err = new Error() and then next(err)...and finally app.use(function (err, req, res, next) catch that error and do the proper functions.
4-Built-in middleware :- Express from 4.16+ uses some of the inbuild middleware such as "express.static" serves static assets such as HTML files, images, and so on, "express.json" parses incoming requests with JSON payloads. NOTE: Available with Express 4.16.0+ and "express.urlencoded" parses incoming requests with URL-encoded payloads. NOTE: Available with Express 4.16.0+
5-Third-party middleware :- This are the middleware provided by the third party the best examle is cookie-parser. it can be used by installing it  npm install cookie-parser and then

var express = require('express')
var app = express()
var cookieParser = require('cookie-parser')

// load the cookie-parsing middleware
app.use(cookieParser())


6- Error Handling in Express  - Start from here.
https://expressjs.com/en/guide/error-handling.html

There are two type of function
1- Sync :- For express if you throw any error from the sync block it will be caught by deafult by the express. you dont need to do anything extra as show below

app.get('/', function (req, res) {
  throw new Error('BROKEN') // Express will catch this on its own.
})


2- Asysn :- if you are using async method like writefiles, readfiles in such Async file it is mandate to give your error to the Express if it comes. For doing that you need to use next function i.e.

app.get('/', [
    function (req, res, next) {
        fs.writeFile('d:\\', 'data', next)
        //next(err)
    },
    function (req, res) {
        res.send('OK')
    }
])

app.use(function (err, req, res, next) {
    res.status(500);
    res.send(err.message + " ---Oops, something went wrong.")
});

In above function while writing the file using Async writeFile we have given wrong path and hence error is thrown and by default we have used next in the write files as a last argument and because of that our express are able to catch the error in belwo block ie,e, res.send(err.message + " ---Oops, something went wrong."). In above case if the error come then only the next is called else it will execute res.send('OK')

In short For errors returned from asynchronous functions invoked by route handlers and middleware, you must pass them to the next() function, where Express will catch and process them.

Another example

app.get('/', function (req, res, next) {
  fs.readFile('/file-does-not-exist', function (err, data) {
    if (err) {
      next(err) // Pass errors to Express.
    } else {
      res.send(data)
    }
  })
})

app.use(function (err, req, res, next) {
    res.status(404);
    res.send(err.message + " ---Oops, something went wrong.")
});

There is also another way to handle the error in Asys fucntion and that is to use the Try..Catch blog

app.get('/', [
    function (req, res, next) {
        try {
            const post = db.post.insert({ title, author });
            res.json(post);
        } catch (error) {
            //We can directly catch the error her and do what ever we want to do 
            return res.status(500).json({
                status: 'error',
                message: 'Internal Server Error'
            });
            //Else we can give it to Express function using next which will be caught by the given below functions.
            //next(error)
        }

    }
])


No comments: