Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Unit 3

Download as pdf or txt
Download as pdf or txt
You are on page 1of 127

1

Unit-III
Node.js: Introduction, Advantages, Node.js Process Model, Node JS Modules.Express.js:
Introduction to Express Framework, Introduction to Nodejs , What isNodejs, Getting
Started with Express, Your first Express App, Express Routing,Implementing MVC in
Express, Middleware, Using Template Engines, ErrorHandling , API Handling ,
Debugging, Developing Template Engines, Using ProcessManagers, Security &
Deployment.

Node.JS: Introduction:

Why and What Node.js: Let us look at the below scenarios for understanding the need for Node.js:
Scenario 1: JavaScript has been the most used language for creating dynamic web pages. Its rising
popularity has brought in a lot of changes. JavaScript has moved to the server-side too, establishing
itself on the web servers as well. That entailed a capability to generate web pages on the server. Node.js
was the first legitimate attempt to bring JavaScript to the server-side thereby making it possible to run
JavaScript outside the web browser. Node.js also represents the "JavaScript everywhere" paradigm, by
unifying web application development around a single language, rather than using different languages
for server-side and client-side.

Scenario 2: Consider a scenario where you are trying to upload videos to a social media website. You
may observe that lot of time is taken for getting your request processed. This may be because the
preceding requests need to be completed first by the web server of the application before executing this
new request. In order to ensure the requests get served concurrently, multiple approaches have been
proposed. This is where Node.js comes in. Since Node.js uses an event looping mechanism, a Node.js
web server is capable of sending responses in a non-blocking way. This eventually means, a Node.js
server can handle a large number of requests than the commonly used traditional web servers.

Let us have a look at the nature of Node.js and some of the benefits associated with Node.js:

1. Node is popular: Node.js is one of the most popular platforms for application development as it uses
JavaScript. JavaScript is a powerful programming language as it provides good flexibility to developers.

2. Full-stack JavaScript development: Node.js has paved the way for JavaScript to be on the server-side
as well. Hence applications can now have both back-end and front-end developed with the same
JavaScript language. We now have two popular JavaScript software stacks for building full stack web
applications: MEAN and MERN.Node is the N in the MEAN stack. In this stack, Node is used along with
the MongoDB database and Express, which is a Node framework for back-end application development.
Angular framework is used for front-end application development.Node is the N in the MERN stack as
well. Here, Node is used along with MongoDB database and Express for back-end application
development. React is used for front-end application development in this stack.
2

3. Very fast: Node applications have better performance than applications developed using other
technologies due to the JavaScript engine used internally in Node. The engine converts JavaScript code
into machine code and provides extremely fast execution.

4. Node is powerful: Node uses a non-blocking I/O model and asynchronous programming paradigm,
which helps in processing requests in a non-blocking way.

5. Data Streaming: Node has a built-in Streams API that helps in creating applications where data
streaming is required.

6. Rich Ecosystem: Node.js provides a package manager called NPM (Node Package Manager) which is
the world's largest software registry that helps open source developers to share and use packages using
NPM.

7. Modularity: Node applications can be developed as modules which helps in dividing the application
into a reusable set of code.

8. Wide client-side and database connectivity: Node.js has absolutely no dependencies and also goes
perfectly with any possible client-side technologies like Angular, React, etc., and any database like
MySQL or MongoDB.

Node.js is used in applications developed for a wide range of domains.


The below table lists out a few domains and the companies that are migrated to Node.js.

All these organizations were using different technologies like Java, Rails, etc. for developing the server-
side of their applications. But later, they migrated to Node.js because of the features provided by it.

The below table lists the reasons why they migrated to Node.js.
3

What is Node.js?

Node.js is an open-source JavaScript run-time environment used for building scalable network
applications. It helps in developing the server-side of the application using JavaScript language. It is used
for building data-intensive real-time applications.

What can we build using Node.js?

1. Complex SPA(Single Page Applications)

2. Real-time applications like Chat rooms

3. Data streaming applications

4. REST APIs

5. Server-side web applications

Let us understand the features of Node.js which makes it the most popular platform for server-side
application development.

1. V8 engine

As application development in Node uses JavaScript language, the Node.js platform needs an engine for
executing JavaScript. The engine used in the platform is V8 which is an open-source high-performance
engine. It is developed by Google and written in C++. V8 compiles JavaScript source code into native
machine code. The same engine is used in the Google Chrome browser as well to execute JavaScript
code. The performance of the Node.js application is faster due to this ultra-fast engine used in the
platform.

2. Single codebase

Since coding in Node is based on JavaScript, both the client and the server-side code can be written
using the same JavaScript language. It allows the front-end and back-end teams to be combined into a
single unit. Also since Node.js uses JavaScript, we can quickly manipulate the JSON data retrieved from
external web API sources like MongoDB, hence reducing the processing time needed per request.

3. Asynchronous and event-driven

All the APIs in Node are asynchronous i.e. non-blocking, which means Node-based server will never wait
for an API to return data or to complete the request, it will move to the next request process. The
notification mechanism of Node.js helps in getting the response from the previous requests after its
completion.

Let us now understand the Asynchronous programming in Node.js.

Executing JavaScript code can happen in a Synchronous or Asynchronous way.


4

Synchronous programming In Synchronous programming, the code execution happens synchronously.


This allows only one task to execute at a time.

Consider the scenario where we need to read the content of a file and then database
operation is to be executed. When the file read operation is started, the rest of the code in the program
gets blocked until the file reading operation is finished. Once the file reading is done, then it continues
to execute the remaining code. Though the database operation code is not dependent on the file read
operation, it is getting blocked. This kind of code is considered as blocking code or synchronous code.

Asynchronous programming Asynchronous programming is a design pattern that ensures code


execution in a non-blocking way. The asynchronous code will get executed without affecting other code
execution. This allows multiple tasks to happen at the same time.

Consider the same scenario of reading a file and then database operation is to be executed.
On asynchronously implementing this, when the file read operation is started, it will not wait for the
read operation to complete, it will just continue execution of the rest of the code. Once the file reading
is done, it will be informed and the corresponding function gets called. This provides a non-blocking way
of executing the code.

This improves system efficiency and throughput.

In Node.js, asynchronous programming is implemented using the callback functions.

Callback function: One approach to asynchronous programming is through callback functions. A


callback is a function passed as an argument to another function and it will be executed after the task
gets completed. It helps in non-blocking code execution.

1. setTimeout(() => {

2. console.log("after 20 seconds");

3. }, 20000);

In the above example, setTimeout() takes two arguments. The first argument is the callback function
and the second argument is the delay in milliseconds. The callback function is called after 20 seconds.

In Node.js, at the completion of each task, the respective callbacks written gets invoked. All the APIs of
Node.js are written in a way to support callbacks. This makes Node.js highly scalable as it can handle a
large number of requests in a non-blocking way.

4. Single-threaded event loop model

Node.js is said to be highly scalable because it handles the client request using the Single-threaded
model with an event loop. Node environment follows the Single Threaded Event Loop Model which is
based on JavaScript's callback mechanism.
5

Let us take a look at the Single-threaded model with the event loop of Node.js.

Single-threaded event loop model processing steps:

Step 1: Assume 'n' number of clients, send requests to the webserver to access the web application
concurrently.

Node web server receives those requests and places them into a queue known as "Event Queue". The
Node web server internally maintains a limited thread pool to provide service to the client. Let us
assume that 'm' number of threads can be created and maintained.
Step 2: The Node web server internally has a component, known as "Event Loop". It uses the indefinite
loop to receive requests and process them. But the Event loop component uses a "Single Thread" to
process the requests.

Step 3: The event Loop component checks for any client request that is placed in the Event Queue. If
norequests are present, then it waits for incoming requests. If the requests are present, then it picks up
one client request from the Event Queue and starts processing that request.

Step 4: If that client request does not require any blocking I/O operations, then the request is processed
till completion and the response is sent back to the client.

Step 5.1: If the client request requires some blocking I/O operations like file operations, database
interactions, any external services then it checks the availability of threads from the internal thread
pool.

Step 5.2: One thread is assigned from the internal pool of threads and assigned to the client request.
That thread is responsible for taking that request, processing it, and performing blocking I/O operations.
6

Step 6: After processing the request, the response is prepared and sends back to the Event Loop. Event
Loop then sends that response back to the requested client.
5. Scalability
 One of the reasons for the Node.js application scalability is that it makes use of event-driven
programming with the Single Threaded Event Loop Mechanism.
 This enables the Node application to serve a huge number of incoming requests concurrently
and it scales up automatically to serve those requests efficiently.
 Companies like eBay and Walmart makes use of Node.js to scale up their application to support
multiple external services and handle the requests flowing in with those services.
6. I/O bound operations
 Due to its asynchronous/non-blocking nature, Node.js can be used to create I/O bound
applications that involve huge input-output operations, such as creating real-time applications
that have real-time data flowing in.
 Applications like Facebook, online chat applications, and Twitter are a few examples. An online
marketing company like eBay makes use of Node.js to handle lots of I/O-bound operations to
handle eBay-specific services that display information on the page.
7. Streaming of data
 Node.js can be used to create data streaming applications that involve streaming the data
quickly. Node.js has a built-in Stream API available using which we can stream the data very fast.
 Applications like the Twitter stream, video stream, etc. use this feature.
 Media companies like National Public Radio, Direct TV, HBO makes use of Node.js to stream the
data to their viewers.
8. Modularity
 Node.js supports modular JavaScript. Instead of writing code in a single JavaScript file, the code
can be written in modules which can then be accessed at multiple places in the application.
 This helps in easy maintenance and reusability of the code.
How to use Node.js:
 Download Node.js from the official site. Follow the instructions mentioned on the site for
installing it on your machine.
 It is important to download the stable version while installing, as the Node.js team keeps
upgrading the version by adding new features and enhancements.
 To check whether Node.js is installed or not in your machine, open the Node command prompt
and check the Node.js version by typing the following command.
7

Node.js also provides a package manager called NPM(Node Package Manager) which is a collection of
all open-source JavaScript libraries. It helps in installing any library or module into your machine.

Thus we have successfully installed Node.js in the machine and we can start the application
development using Node.js.

Let us create our first Node.js program:

Getting started with Node.js


Step 1: Create a folder NodeJS in D drive and create a new JavaScript file, first.js inside the folder. Type
the below code inside the JavaScript file.

1.console.log("My First Node.js program");

Step 2: Navigate to the created NodeJS folder in the NodeJS command prompt and execute the
JavaScript file, first.js using the node command.

1. node first.js

Step 3: After the successful interpretation of the code, we can see the output in the Node.js command
prompt as shown below.

Node.js command prompt:


8

So, we can now conclude that any JavaScript file which doesn't contain codes for browser interactions
will execute successfully using the Node platform.

Create web server in Node.js:


A node.js web application contains the following three parts:
1. Import required modules: The "require" directive is used to load a Node.js module.
2. Create server: You have to establish a server which will listen to client's request similar to Apache
HTTP Server.
3. Read request and return response: Server created in the second step will read HTTP request made by
client which can be a browser or console and return the response.
How to create node.js web applications
Follow these steps:
 Using require() and createServer() method
  Running a web server in Node.js
9

Step 1: Create a new JavaScript file httpserver.js and include the HTTP module.
1. const http = require("http");
Step 2: Use the createServer() method of the HTTP module to create a web server. var server =
http.createServer((req, res) => { res.write("Hello World! I have created my first server!"); res.end(); });
server.listen(3000);
console.log("Server started... Running on localhost:3000");
Step 3: Save the file and start the server using the node command. When the file executes successfully,
we can observe the following output in the console.

Step 4: We will observe the following in the browser.

Introduction
Node.js is a JavaScript run-time environment built on Chrome's V8 engine, not a
framework or library. It enables server-side execution of JavaScript code.

When Node.js performs an I/O operation, like reading from the network, accessing a
database or the filesystem, instead of blocking the thread and wasting CPU cycles
waiting, Node.js will resume the operations when the response comes back.
This allows Node.js to handle thousands of concurrent connections with a single
server without introducing the burden of managing thread concurrency, which could
be a significant source of bugs.
10

Node.js has a unique advantage because millions of frontend developers that write
JavaScript for the browser are now able to write the server-side code in addition to the
client-side code without the need to learn a completely different language.
In Node.js the new ECMAScript standards can be used without problems, as you don't
have to wait for all your users to update their browsers - you are in charge of deciding
which ECMAScript version to use by changing the Node.js version, and you can also
enable specific experimental features by running Node.js with flags.

Node.js is an open-source and cross-platform JavaScript runtime


environment. It is a powerful tool suitable for a wide range of
projects. Node.js stands out as a game-changer. Imagine using the power of
JavaScript not only in your browser but also on the server side.
What is Node.JS?
Node.js is an open-source, cross-platform JavaScript runtime
environment that executes JavaScript code outside of a web browser. It’s a
powerful tool used for various types of projects. Let’s explore some key
aspects:
 JavaScript Runtime: Node.js runs on the V8 JavaScript engine, which
is also the core engine behind Google Chrome. However, unlike the
browser context, Node.js executes JavaScript code outside of the
browser.
 Single Process Model: A Node.js application operates within a single
process, avoiding the need to create a new thread for every request. This
design choice contributes to Node.js’ performance.
 Asynchronous I/O: Node.js provides a set of asynchronous I/O
primitives in its standard library. These primitives prevent JavaScript
code from blocking, making non-blocking behavior the norm. When
performing I/O operations (e.g., reading from the network, accessing
databases, or the filesystem), Node.js doesn’t waste CPU cycles waiting.
Instead, it resumes operations when the response arrives.
 Concurrency Handling: Node.js efficiently handles thousands of
concurrent connections using a single server. It avoids the complexities
of managing thread concurrency, which can lead to bugs.
 JavaScript Everywhere: Frontend developers familiar with JavaScript
can seamlessly transition to writing server-side code using Node.js. You
don’t need to learn a different language.
 ECMAScript Standards: Node.js supports the latest ECMAScript
standards. You can choose the version you want to use, independent of
users’ browser updates.
11

Why Node.JS?
Node.js is used to build back-end services like APIs like Web App, Mobile
App or Web Server. A Web Server will open a file on the server and return
the content to the client. It’s used in production by large companies such
as Paypal, Uber, Netflix, Walmart, and so on.

Reasons to Choose Node.js


 Easy to Get Started: Node.js is beginner-friendly and ideal for
prototyping and agile development.
 Scalability: It scales both horizontally and vertically.
 Real-Time Web Apps: Node.js excels in real-time synchronization.
 Fast Suite: It handles operations quickly (e.g., database access, network
connections).
 Unified Language: JavaScript everywhere—frontend and backend.
 Rich Ecosystem: Node.js boasts a large open-source library and
supports asynchronous, non-blocking programming.
PHP and ASP handling file requests:
Send Task -> Waits -> Returns -> Ready for Next Task
Node.js handling file request:
Send Task -> Returns -> Ready for Next Task
Node.js takes requests from users, processes those requests, and returns
responses to the corresponding users, there is no Wait for open and read file
phase in Node.js.

Basic Concepts of Node.JS


The following diagram depicts some important parts of Node.js that are
useful and help us understand it better.
12

Node.js Example to Create Web Server


It is the basic code example to create node.js server.

// Importing the http module


const http = require('http');

// Creating a server
const server = http.createServer((req, res) => {
// Setting the content type to HTML
res.writeHead(200, {
'Content-Type': 'text/html'
});

// Sending the HTML response


res.end('<h1>Hello GFG</h1>');
});

// Listening on port 3000


const PORT = 3000;
server.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}/`);
});

Code Explaination:
 We use the http module to create an HTTP server.
 The server listens on the specified port and hostname.
 When a new request arrives, the callback function handles it by setting
the response status, headers, and content.
13

How Node.JS Works?


Node.js accepts the request from the clients and sends the response, while
working with the request node.js handles them with a single thread. To
operate I/O operations or requests node.js use the concept of threads.
Thread is a sequence of instructions that the server needs to perform. It runs
parallel on the server to provide the information to multiple clients. Node.js is
an event loop single-threaded language. It can handle concurrent requests
with a single thread without blocking it for one request.
Advantages of Node.JS
 Easy Scalability: Easily scalable the application in both horizontal and
vertical directions.
 Real-time web apps: Node.js is much more preferable because of faster
synchronization. Also, the event loop avoids HTTP overloaded for Node.js
development.
 Fast Suite: NodeJS acts like a fast suite and all the operations can be
done quickly like reading or writing in the database, network connection,
or file system
 Easy to learn and code: NodeJS is easy to learn and code because it uses
JavaScript.
 Advantage of Caching: It provides the caching of a single module.
Whenever there is any request for the first module, it gets cached in the
application memory, so you don’t need to re-execute the code.
What is Node.JS file?
Node.js files contain tasks that handle file operations
like creating, reading, deleting, etc., Node.js provides an inbuilt module called
FS (File System).
Application of Node.JS
Node.js is suitable for various applications, including:
 Real-time chats
 Complex single-page applications
 Real-time collaboration tools
 Streaming apps
 JSON APIs
Common Use Cases of Node.JS
Node.js is versatile and finds applications in various domains:
1. Web Servers : Node.js excels at building lightweight and efficient web
servers. Its non-blocking I/O model makes it ideal for handling concurrent
connections.
2. APIs and Microservices : Many companies use Node.js to create RESTful
APIs and microservices. Express.js simplifies API development.
14

3. Real-Time Applications: Node.js shines in real-time scenarios like chat


applications, live notifications, and collaborative tools. Socket.io facilitates
real-time communication.
4. Single-Page Applications (SPAs): SPAs benefit from Node.js for server-side
rendering (SSR) and handling API requests.
5. Streaming Services: Node.js is well-suited for streaming data, whether it’s
video, audio, or real-time analytics.
Node.JS Ecosystem
Node.js has a vibrant ecosystem with a plethora of libraries, frameworks, and
tools. Here are some key components:
1. npm (Node Package Manager): npm is the default package manager for
Node.js. It allows developers to install, manage, and share reusable code
packages (called modules). You can find thousands of open-source
packages on the npm registry.
2. Express.js: Express is a popular web application framework for Node.js. It
simplifies routing, middleware handling, and request/response
management. Many developers choose Express for building APIs, web
servers, and single-page applications.
3. Socket.io: For real-time communication, Socket.io is a go-to library. It
enables bidirectional communication between the server and clients using
WebSockets or fallback mechanisms.
4. Mongoose: If you’re working with MongoDB (a NoSQL database),
Mongoose provides an elegant way to model your data and interact with
the database. It offers schema validation, middleware, and query building

Node.js Advantages
Node.js Advantages include
1. High Performance
2. Scalability
3. Easy to Learn
4. Reduces Loading time using caching
5. Improves Response time and boosts performance
6. Large Community Support
7. Cost-Effective
8. Extensibility
15

High Performance
 One of the most important features of node.js is the ability to create lightning-fast
apps that produce results in seconds.
 The ability to multitask that Node.js provides is extremely beneficial to web apps.
Its event-driven, single-threaded design rapidly processes several simultaneous
requests without clogging the RAM. Additionally, its event-loop and non-blocking
I/O operations allow code to be executed at a rate that indirectly influences the
application's overall performance.
 Node.js advantage is that it is powered by the V8 engine in Google Chrome,
written in C++. It rapidly and efficiently converts JavaScript to machine code.
 This engine is significant because Google makes significant investments in
improving efficiency and security and providing strong support for sophisticated
JavaScript capabilities.
 Furthermore, because it allows non-blocking I/O operations, the run-time
environment speeds up code execution.
 Google released the V8 benchmark set to improve node.js performance with
faster execution, better compilers, security patchworks, and scalability.
Scalability
 One of the Node.js advantages is that developers can easily grow applications in
both horizontal and vertical orientations.
 The applications can be horizontally scaled by adding additional nodes to the
existing system.
16

Furthermore, during the vertical scaling of the application, Node.js allows you to add
extra resources to single nodes. As a result, it is extremely scalable and offers a
superior alternative to existing JavaScript servers.

Easy to Learn
 Most frontend developers are familiar with JavaScript because it is one of the
most extensively used programming languages.
 It will be lot easier for them to get started using Node.js on the backend. It is
simpler to understand Node.js, and working with it takes less time.
Cost-Effective
 Node.js allows programmers to develop server-side JavaScript and frontend
JavaScript codes with simplicity.
 One of the major node.js advantages is that it eliminates the need for two
resource teams, saving time, money, and energy for overall project development.
 LinkedIn's development team switched from Ruby on Rails to Node.js, and the
benefits of Node.js helped them gain performance.
 They lowered the number of servers from 30 to only three. They began
delegating and utilizing resources more effectively, changing their attention from
debugging to app development.
Extensibility
 Node.js offers a lot of extensibility, which means it can be changed and improved
to fit unique requirements.
 Data may be sent between the web server and the client using the JSON format.
It also has APIs for constructing HTTP, TCP, and DNS servers, among other
features.
Large Community Support
 Millions of developers actively contribute to the Node.js community. To address
even the most bizarre development difficulties, anticipate widespread
cooperation from development specialists all across the world.
 NPM is the world's most comprehensive package manager registry. It includes a
number of tools and libraries that you may use right away in your project.
Developers will also have access to a wide pool of resources on GitHub,
including ready–to–use solutions, scripts, modules, libraries, and registries
created by developers to help them do more with less.
 IBM is a strong supporter of this rapidly evolving technology and has announced
plans to sponsor and speak at key Node events to expand the technology's reach
and use. They also want to create open authority in the Node.js and JS
Foundations merger, resulting in a strong and thriving JavaScript ecosystem.
Many big tech companies, including Amazon, Google, Facebook, and Netflix, contribute
significantly to the node.js community. They've made significant contributions in the
shape of several open-source projects. Acceptance by tech giants and the development
community ensures the presence and expansion of technology in the foreseeable
future.
Improves Response time and boosts performance
17

 When Netflix used Java and JavaScript, the startup time was 40 minutes. They
then moved to node.js and succeeded in cutting the startup time to under 40
seconds.
 A constant stream of queries impacts an app's response time and performance. If
your IT stack isn't ready to manage a high volume of requests, the value of your
product will rapidly dwindle.
 The single-threaded event-loop approach in Node.js provides a non-blocking
asynchronous design.
 This design uses fewer resources since it does not spawn more threads. It
improves the responsiveness of your application by dealing with several
concurrent users.
Reduces Loading Time using caching
 The Node.js Caching module makes it simple for developers to decrease task
workload and code re-execution.
 It is one of the major node.js advantages.
As a result, the initial module of the web application is cached in the in-app memory
each time it is accessed. A user may browse online sites quickly without having to wait
long.
Helps in building the cross-functional teams
 You can use Node.js to construct cross-platform real-time web apps using
platforms like Electron and NW.js.
 This eliminates the need to write separate code for different desktop versions
such as Windows, Linux, and macOS.
 Your development team will be able to create native desktop apps in the future
without needing expert-level knowledge of Objective-C, C#, or any other
language.
 Additionally, your Node.js engineers will have unlimited access to Google
Chrome Developer Tools to build, debug, and create code.
This powerful technique is used in web development using Javascript frameworks like
AnjularJS, Vue.js, and React for the frontend and Node.js for the backend. It has
enabled full-stack developers to take advantage of the benefits and opportunities that
node.js provides.

Node.js Disadvantages
Node.js Disadvantages include
1. Unstable API
2. Lack of Library Support
3. Asynchronous Programming Model
18

Unstable API
 The Application Programming Interface changes frequently and is not reliable,
which is one of the most prevalent challenges that most developers experience.
 Occasionally, a new API will come with several incompatible changes.
 As a result, developers must update existing code bases to verify that they are
compatible with the latest Node.js API version.
Lack Of Library Support
 In comparison to any other programming language, JavaScript lacks a well-
equipped and robust library system.
 As a result, processes like Object-Relational Mapping (ORM), image processing,
database operations, and XML parsing must be performed via a common library.
 This makes it difficult to use Node.js for even simple programming tasks.
Asynchronous Programming Model
 If you want to make your apps more scalable, you'll need to use the
asynchronous programming strategy.
 However, many engineers may find this programming method more difficult than
linear blocking I/O programming.
 Another disadvantage of asynchronous programming is that the code tends to
become clunky, forcing programmers to rely on nested calls.

Node.js Process Model


In this section, we will learn about the Node.js process model and
understand why we should use Node.js.

Traditional Web Server Model


In the traditional web server model, each request is handled by a
dedicated thread from the thread pool. If no thread is available in the
thread pool at any point of time then the request waits till the next
available thread. Dedicated thread executes a particular request and
19

does not return to thread pool until it completes the execution and
returns a response.

Traditional Web Server Model

Node.js Process Model


Node.js processes user requests differently when compared to a
traditional web server model. Node.js runs in a single process and
the application code runs in a single thread and thereby needs less
resources than other platforms. All the user requests to your web
application will be handled by a single thread and all the I/O work or
long running job is performed asynchronously for a particular
request. So, this single thread doesn't have to wait for the request to
complete and is free to handle the next request. When asynchronous
I/O work completes then it processes the request further and sends
the response.

An event loop is constantly watching for the events to be raised for


an asynchronous job and executing callback function when the job
completes. Internally, Node.js uses libev for the event loop which in
turn uses internal C++ thread pool to provide asynchronous I/O.

The following figure illustrates asynchronous web server model using


Node.js.
20

Node.js Process Model

Node.js process model increases the performance and scalability with


a few caveats. Node.js is not fit for an application which performs
CPU-intensive operations like image processing or other heavy
computation work because it takes time to process a request and
thereby blocks the single thread.

Node.js provides the facility to get process information such as process id, architecture, platform,
version, release, uptime, upu usage etc. It can also be used to kill process, set uid, set groups,
unmask etc.

The process is a global object, an instance of EventEmitter, can be accessed from anywhere.

Node.js Process Properties


A list of commonly used Node.js process properties are given below.
21

Property Description

arch returns process architecture: 'arm', 'ia32', or 'x64'

args returns commands line arguments as an array

env returns user environment

pid returns process id of the process

platform returns platform of the process: 'darwin', 'freebsd', 'linux', 'sunos' or 'win32'

release returns the metadata for the current node release

version returns the node version

versions returns the node version and its dependencies

Node.js Process Properties Example


Let's see the simple process example to print architecture, pid, platform and version of
the process.File: process_example1.js

1. console.log(`Process Architecture: ${process.arch}`);


2. console.log(`Process PID: ${process.pid}`);
3. console.log(`Process Platform: ${process.platform}`);
4. console.log(`Process Version: ${process.version}`);

Open Node.js command prompt and run the following code:

1. node process_example1.js
22

Let's see another process example to print command line arguments. Here node is
considered as the first argument, filename is considered as the second argument and
actual command line arguments are considered as third, fourth, fifth and so on.

File: process_example2.js

1. process.argv.forEach((value, index, array) => {


2. console.log(`${index}: ${value}`);
3. });

Open Node.js command prompt and run the following code:

1. node process_example2.js

Node.js Process Functions


A list of commonly used Node.js process functions are given below.

Function Description

cwd() returns path of current working directory

hrtime() returns the current high-resolution real time in a [seconds, nanoseconds] array

memoryUsage() returns an object having information of memory usage.

process.kill(pid[, signal]) is used to kill the given pid.

uptime() returns the Node.js process uptime in seconds.


23

Node.js Process Functions Example


Let's see the process example to print current working directory and uptime of the
process.

File: process_example3.js

1. console.log(`Current directory: ${process.cwd()}`);


2. console.log(`Uptime: ${process.uptime()}`);

Open Node.js command prompt and run the following code:

1. node process_example3.js

The process object in Node.js is a global object, although it is


defined in process module. It is an instance of EventEmitter class.
The process object provides information on current Node.js process.
With the help of a number of methods and properties associated
with this object, it is possible to control the current Node.js process.

Process Events
The process object is an instance of EventEmitter and emits the
following events −

Sr.No. Event & Description

exit
1
Emitted when the process is about to exit. There is no way to prevent the exiting of the event
loop at this point, and once all exit listeners have finished running, the process will exit.
24

beforeExit
2 This event is emitted when node empties its event loop and has nothing else to schedule.
Normally, the node exits when there is no work scheduled, but a listener for 'beforeExit' can
make asynchronous calls, and cause the node to continue.

uncaughtException
3
Emitted when an exception bubbles all the way back to the event loop. If a listener is added for
this exception, the default action (which is to print a stack trace and exit) will not occur.

warning
4 The 'warning' event is emitted whenever Node.js emits a process warning. A process warning is
similar to an error in that it describes exceptional conditions that are being brought to the user's
attention.

5 Signal Events
Emitted when the processes receives a signal such as SIGINT, SIGHUP, etc.

Example

In the following code, the beforeExit event of the process object is


associated with a callback arrow function. Similarly the exit event
calls another callback function. The function on beforeExit runs first,
followed by the one on exit event.

process.on('beforeExit', (code) => {


console.log('A beforeExit event occured with code: ', code);
});

process.on('exit', (code) => {


console.log('Process exit event with code: ', code);
});

console.log('This message is displayed first.');

Output
This message is displayed first.
A beforeExit event occured with code: 0
Process exit event with code: 0
25

Note that the listener functions must only perform synchronous


operations. The Node.js process will exit immediately after calling
the 'exit' event listeners causing any additional work still queued in
the event loop to be abandoned. In the following example, for
instance, the timeout will never occur −

Example

process.on('exit', function(code) {
// Following code will never execute.
setTimeout(function() {
console.log("This will not run");
}, 0);

console.log('About to exit with code:', code);


});
console.log("Program Ended");

Output
Program Ended
About to exit with code: 0

Process Methods
abort()

The abort() method immediately terminates the current process and


then creates a core file.

Example

The following program prints a message to the console after every


one second, and terminates the loop after 5 seconds as the abort()
function is called.

const abortfunction = () => {


console.log('Start...');
26

// It prints the message after every 1 second


setInterval((function() {
return console.log('Hello World');
}), 1000);

// It calls process.abort() after 5 seconds


setTimeout((function() {
return process.abort();
}), 5000);
};

abortfunction();
Output
Start...
Hello World
Hello World
Hello World
Hello World

The termination is followed by a long core file output.

chdir()

This method changes the current working directory of the Node.js


process or throws an exception if doing so fails (for instance, if the
specified directory does not exist).

cwd()

The process.cwd() method returns the current working directory of


the Node.js process.

Example
console.log(`Starting directory: ${process.cwd()}`);
try {
process.chdir('NewNodeApp');
console.log(`New directory: ${process.cwd()}`);
27

} catch (err) {
console.error(`chdir: ${err}`);
}
Output
Starting directory: D:\nodejs
New directory: D:\nodejs\NewNodeApp

If the directory is not found, the output will be as follows −

Starting directory: D:\nodejs


chdir: Error: ENOENT: no such file or directory, chdir 'D:\nodejs' -> 'NewDir'

exit()

This method terminates the current process synchronously with an


exit status of code (default is 'success' code 0). Node.js will not
terminate until all the 'exit' event listeners are called.

Example
console.log('Code running');
process.on('exit', function(code) {
return console.log(`exiting with the error code : ${code}`);
});
setTimeout((function() {
return process.exit(0); //after 5 sec
}), 5000);
Output
Code running
exiting with the error code : 0

kill()

This method terminates the current process and sends a signal to


the process identified by pid.

kill(pid[, signal])
28

Parameters

pid : A process ID

signal : The signal to send, either as a string or number. Default:


'SIGTERM'.

Signal names are strings such as 'SIGINT' or 'SIGHUP'.

Example

The following code obtains the pid of the current process. It waits
for a long enough duration before it exits normally. In between if
you emit SIGINT signal by pressing ctrl-C, the process doesn’t
terminate.

const pid = process.pid;


console.log(`Process ID: ${pid}`);
process.on('SIGHUP', () => console.log('Received: SIGHUP'));
process.on('SIGINT', () => console.log('Received: SIGINT'));
setTimeout(() => {}, 100000); // keep process alive
setTimeout((function() {
return process.kill(pid, 'SIGINT'); //after 5 sec
}), 5000);

The terminal shows the process ID and Received: SIGINT whenever


ctrlC is pressed. After another timeout of 5 seconds, the kill()
method is called, which terminates the process

Process ID: 1776


Received: SIGINT

memoryUsage()

This function returns an object describing the memory usage of the


Node.js process measured in bytes.

Example
console.log(process.memoryUsage());
29

Output
{
rss: 24768512,
heapTotal: 4079616,
heapUsed: 3153848,
external: 1097184,
arrayBuffers: 10519
}

nextTick()

This function defers the execution of a callback function until the


next Event Loop Iteration.

nextTick(callback[, ...args])

This function is an important part of the event loop in asynchronous


API of Node.js. In Node.js, each iteration of an Event Loop is called
a tick. To schedule a callback function to be invoked in the next
iteration of the Event Loop, we use process.nextTick().

Example
console.log('start');
process.nextTick(() => {
console.log('nextTick callback executed in next iteration');
});
console.log('scheduled');
Output
start
scheduled
nextTick callback executed in next iteration

Process properties
process.arch
30

The operating system CPU architecture for which the Node.js binary
was compiled.

Possible values are −

 'arm',
 'arm64',
 'ia32',
 'loong64',
 'mips',
 'mipsel',
 'ppc',
 'ppc64',
 'riscv64',
 's390',
 's390x',
 'x64'

Example
console.log(`This processor architecture is ${process.arch}`);
Output
This processor architecture is x64

process.argv

This property returns an array containing the command-line


arguments passed when the Node.js process was launched. You can
pass arguments to the script to be executed from the command
line. The arguments are stored in a an array process.argv. The 0th
element in the array is the node executable, first element is the
JavaScript file, followed by the arguments passed.

Save the following script as hello.js and run it from command line,
pass a string argument to it from command line.

const args = process.argv;

console.log(args);
31

const name = args[2];

console.log("Hello,", name);

In the terminal, enter

PS D:\nodejs> node hello.js TutorialsPoint


[ 'C:\\nodejs\\node.exe', 'c:\\nodejs\\a.js', 'TutorialsPoint' ]
Hello, TutorialsPoint

process.env

property returns an object containing the environment variables.

Example
const processEnvKeys = Object.keys(process.env);

processEnvKeys.forEach((key) => {
console.log(`${key}: ${process.env[key]}`);
});
Output
SystemDrive: C:
SystemRoot: C:\WINDOWS
TEMP: C:\Users\mlath\AppData\Local\Temp
TMP: C:\Users\mlath\AppData\Local\Temp
USERDOMAIN: GNVBGL3
USERDOMAIN_ROAMINGPROFILE: GNVBGL3
USERNAME: mlath
USERPROFILE: C:\Users\mlath
windir: C:\WINDOWS
ZES_ENABLE_SYSMAN: 1
TERM_PROGRAM: vscode
TERM_PROGRAM_VERSION: 1.84.2
LANG: en_US.UTF-8
COLORTERM: truecolor
VSCODE_INJECTION: 1
32

VSCODE_NONCE: b8069509-e0f5-4bbd-aac9-fc448279b154

You can also set environment variables from the command line.
Assign the values to one or more variables before the node
executable name.

USER_ID=101 USER_NAME=admin node app.js

Inside the script, the environment variables are available as the


properties of the process.env object

process.env.USER_ID; // "101"
process.env.USER_NAME; // "admin"

process.pid

property returns the PID of the process.

Example
const { pid } = require('node:process');

console.log(`This process is pid ${pid}`);


Output
This process is pid 16312

process.platform
This property returns a string identifying the operating system.

The possible values are −

 'aix'
 'darwin'
 'freebsd'
 'linux'
 'openbsd'
 'sunos'
 'win32'
33

process.version

This property contains the Node.js version string.

Example
console.log(`Version: ${process.version}`);
Output
Version: v20.9.0
What are Modules in Node.js ?
In Node.js Application, a Module can be considered as a block of code that
provide a simple or complex functionality that can communicate with external
application. Modules can be organized in a single file or a collection of
multiple files/folders. Almost all programmers prefer modules because of
their reusability throughout the application and ability to reduce the
complexity of code into smaller pieces.
Nodejs uses the CommonJS Module standard implementation in its module
ecosystem.
Types of Modules: In Nodejs, there is 3 type of modules namely
 Core Modules
 Local Modules
 Third-Party Modules
Core Modules: Node.js comes with dozens of built-in modules. These built-
in modules are sometimes referred to as core modules. The module system
is built around the require function. This function is used to load a module
and get access to its contents. require is a global variable provided to all
your Node.js scripts, so you can use it anywhere you like. require() function
will return a JavaScript type depending on your module.
Syntax for Importing Module:
const module = require("Name_of_Module_to_be_imported");
How to use Core Module: You can directly use the Nodejs core module in
your application without any installation. Let’s see an example of the file
system (fs) module to handle the files in the application.
Initially, the Project Directory will look like this:
34

Initially, the Project directory

Example: Write the below code in the index.js file


 Javascript

// Working code of fs module

const fs = require('fs'); // Import fs module

fs.writeFileSync('notes.txt', 'I love to code');

The script above uses require to load in the fs module. This is a built-in
Node.js module that provides functions you can use to manipulate the file
system. The script uses writeFileSync to write a message to notes.txt.
To run the script use the following command on your terminal
$ node index.js
After you run the script, you’ll notice a new notes.txt file in your directory.
Open it up and you’ll see, “I love to code”.
Output: Now we have a new file notes.txt in our directory. And “I love to
code” written has written on it.

Output

Here is the list of some Nodejs Core Modules:


35

Core Modules Name Description

fs To handle the file system.

http To make Node.js act as an HTTP server

https To make Node.js act as an HTTPS server.

os It provides information about the operation system.

path To handle file paths.

cluster To split a single Node process into multiple processes.

dns To do DNS lookups and name resolution functions.

tls To implement TLS and SSL protocols.

querystring To handle URL query strings.

url To parse URL strings.

events To handle events

timers To execute a function after a given number of milliseconds.

Local Modules: Putting all your code in a single file is not a good idea. As
you add more code, you’ll want to stay organized and break your Node.js
app into multiple scripts that all work together. For that purpose, we can
create local modules in our application.
Exporting from files: Firstly we need to create a file called utils.js. Now We
can export javascript code written on this file using module.exports. In below
a function is defined and assigned to the module.exports.
Project setup:
36

 Utils.js: Write the below code in the utils.js file


 Javascript

const tests = function() {

console.log("Yehh! Local file is running successfully...");

module.exports = tests;

Importing your own files: Now we need to import the local file
into index.js. require function is also used for importing the files in the
directory. All you need to do is provide require with a relative path to the
script you want to load. This path should start with ./ and then link to the file
that needs to be loaded.
Filename:- In the index.js file

 Javascript

const utility = require('./utils.js');

utility();
37

The code above uses require to load in a file called utils.js in the src
directory. It stores the module contents in a variable, and then use the
contents in the script.
If you run the above index.js script. you will see the message that is logged
from the tests function defined in the utils.js file.
Output:
Yehh! Local file is running successfully...

Third-party Modules: Third-party modules can be installed from the NPM


(Node Package Manager) available online.
Firstly we need to initialize the npm using the npm init command before npm
can be used. It creates a package.json file in the root directory and it stores
all the information about the third-party module that we have installed as a
dependency.
Installing an NPM module:
npm install "module_name"
The above command will do the following:
Firstly, It creates the node_modules directory which npm uses to store all the
codes of the npm module you have installed. Secondly, npm add a module
as a dependency by listing it in the dependencies property in the
package.json file, and lastly, npm creates a package-lock.json file. This is
used to store information about the modules you’ve installed which helps
keep things fast and secure.

Examples of Third-Party Module:


38

 npm install express


 npm install lodash
 npm install mocha
Let’s see with an example how to use third party modules:
 validator is a popular module used for string validations and
sanitizations.
To install run the following command:
$npm install validator

npm modules can be imported into your script using require. To load in an
npm module, pass the npm module name to require:
index.js: Write the below code in the index.js file
 Javascript

const validator = require("validator");

// Print: true

console.log("URL is " + validator.isURL("https://google.com"));

// Print: false

console.log("Email is " + validator.isEmail("johndoeeg.com"));

Output:
39

How to Create Modules in Node.js ?


Modules are the collection of JavaScript codes in a separate logical file that
can be used in external applications on the basis of their related
functionality. Modules are popular as they are easy to use and reusable. To
create a module in Node.js, you will need the exports keyword. This
keyword tells Node.js that the function can be used outside the module.
Syntax:
exports.function_name = function(arg1, arg2, ....argN) {
// function body
};
Example of a custom node module:
Create a file that you want to export
// File name: calc.js

exports.add = function (x, y) {


return x + y;
};

exports.sub = function (x, y) {


return x - y;
};

exports.mult = function (x, y) {


return x * y;
};

exports.div = function (x, y) {


return x / y;
};

Use the ‘require’ keyword to import the file


// File name: App.js
const calculator = require('./calc');

let x = 50, y = 20;

console.log("Addition of 50 and 20 is "


+ calculator.add(x, y));
40

console.log("Subtraction of 50 and 20 is "


+ calculator.sub(x, y));

console.log("Multiplication of 50 and 20 is "


+ calculator.mult(x, y));

console.log("Division of 50 and 20 is "


+ calculator.div(x, y));

Output:
Addition of 50 and 20 is 70
Subtraction of 50 and 20 is 30
Multiplication of 50 and 20 is 1000
Division of 50 and 20 is 2.5

What is Express?
Express is a small framework that sits on top of Node.js’s web server
functionality to simplify its APIs and add helpful new features.It makes it
easier to organize your application’s functionality with middle ware and
routing; it adds helpful utilities to Node.js’s HTTP objects;it facilitates the
rendering of dynamic HTTP objects.
Express.js is a fast, flexible and minimalist web framework for Node.js. It’s
effectively a tool that simplifies building web applications and APIs using
JavaScript on the server side. Express is an open-source that is developed
and maintained by the Node.js foundation.
Express.js offers a robust set of features that enhance your productivity and
streamline your web application. It makes it easier to organize your
application’s functionality with middleware and routing. It adds helpful utilities
to Node HTTP objects and facilitates the rendering of dynamic HTTP
objects.

Express.js is a minimalist web application framework for Node.js, designed


to make building web applications and APIs easier and more efficient. It
provides a robust set of features for web and mobile applications, allowing
developers to create powerful server-side applications with ease.
41

Here's a brief introduction to some key features of Express.js:

1. **Routing**: Express provides a simple yet powerful routing mechanism


that allows developers to define routes based on HTTP methods (GET,
POST, PUT, DELETE, etc.) and URL patterns. This makes it easy to handle
different types of requests and direct them to the appropriate handler
functions.

2. **Middleware**: Middleware functions are the heart of Express.js. They


are functions that have access to the request and response objects and can
modify them as needed. Middleware functions can be used for tasks such as
authentication, logging, parsing request bodies, and error handling. Express
comes with a range of built-in middleware functions, and developers can also
create custom middleware to suit their specific needs.

3. **Template engines**: Express supports a variety of template engines,


such as Pug (formerly Jade), EJS, and Handlebars, allowing developers to
generate dynamic HTML content easily. Template engines help streamline
the process of generating HTML by allowing developers to inject data into
HTML templates.

4. **Static file serving**: Express makes it simple to serve static files, such
as images, CSS files, and JavaScript files, using the `express.static`
middleware. This middleware function serves files from a specified directory,
making it easy to include client-side assets in your web applications.

5. **Error handling**: Express provides robust error handling mechanisms,


allowing developers to define error-handling middleware functions that catch
errors and respond to them appropriately. This helps ensure that errors are
handled gracefully and do not crash the server.

6. **Integration with third-party middleware and libraries**: Express.js is


highly extensible and can be easily integrated with a wide range of third-
party middleware and libraries, allowing developers to add additional
functionality to their applications as needed.

Overall, Express.js is a powerful and flexible framework for building web


applications and APIs with Node.js. Its simplicity, flexibility, and extensive
ecosystem of middleware and libraries make it a popular choice among
developers for building server-side applications.
42

Benefits:

 Fast and Minimalist: Express is known for its speed and minimalist approach. It
provides a lightweight framework that allows developers to build scalable and efficient
applications.
 Large Ecosystem: Express has a vast ecosystem of modules and libraries, making it easy
to find solutions for common tasks and challenges in web development.
 Flexibility: Express does not impose strict rules or conventions, allowing developers to
structure their applications according to their preferences and requirements.

Conclusion

 Express.js is a powerful and flexible framework for building web applications and APIs
with Node.js.
 Its simplicity, speed, and extensive feature set make it a popular choice among
developers for various projects.

Express is a part of MEAN stack, a full stack JavaScript solution used in


building fast, robust, and maintainable production web applications.
MongoDB(Database)
ExpressJS(Web Framework)
AngularJS(Front-end Framework)
NodeJS(Application Server)
Installing Express on Windows (WINDOWS 10)
Assuming that you have installed node.js on your system, the following steps
should be followed to install express on your Windows:
STEP-1: Creating a directory for our project and make that our working
directory.
$ mkdir gfg
$ cd gfg
STEP-2: Using npm init command to create a package.json file for our
project.
$ npm init
This command describes all the dependencies of our project. The file will be
updated when adding further dependencies during the development process,
for example when you set up your build system.
43

Keep pressing enter and enter “yes/no” accordingly at the terminus line.

STEP-3: Installing Express


Now in your gfg(name of your folder) folder type the following command line:
$ npm install express --save

NOTE- Here “WARN” indicates the fields that must be entered in STEP-2.
STEP-4: Verify that Express.js was installed on your Windows:
To check that express.js was installed on your system or not, you can run
the following command line on cmd:
C:\Users\Admin\gfg\node_modules>npm --version express
44

The version of express.js will be displayed on successful installation.


Summer-time is here and so is the time to skill-up! More than 5,000 learners
have now completed their journey from basics of DSA to advanced level
development programs such as Full-Stack, Backend Development, Data
Science.

Express.js is a minimal and flexible web application framework that


provides a robust set of features to develop Node.js based web and
mobile applications. Express.js is one of the most popular web
frameworks in the Node.js ecosystem. Express.js provides all the
features of a modern web framework, such as templating, static file
handling, connectivity with SQL and NoSQL databases.

Node.js has a built-in web server. The createServer() method in its


http module launches an asynchronous http server. It is possible to
develop a web application with core Node.js features. However, all
the low level manipulations of HTTP request and responses have to
be tediously handled. The web application frameworks take care of
these common tasks, allowing the developer to concentrate on the
business logic of the application. A web framework such as
Express.js is a set of utilities that facilitates rapid, robust and
scalable web applications.

Following are some of the core features of Express framework −


45

 Allows to set up middlewares to respond to HTTP Requests.


 Defines a routing table which is used to perform different
actions based on HTTP Method and URL.
 Allows to dynamically render HTML Pages based on passing
arguments to templates.

The Express.js is built on top of the connect middleware, which in


turn is based on http, one of the core modules of Node.js API.

Express Key Features


1. Middleware and Routing: Express.js makes it easy to organize your
application’s functionality using middleware and routing. Middleware
functions allow you to handle tasks like authentication, logging, and error
handling. Routing ensures that incoming requests are directed to the
appropriate handlers.
2. Minimalistic Design: Express.js follows a simple and minimalistic design
philosophy. This simplicity allows you to quickly set up a server, define
routes, and handle HTTP requests efficiently. It’s an excellent choice for
building web applications without unnecessary complexity.
46

3. Flexibility and Customization: Express.js doesn’t impose a strict


application architecture. You can structure your code according to your
preferences. Whether you’re building a RESTful API or a full-fledged web
app, Express.js adapts to your needs.
4. Scalability: Designed to be lightweight and scalable, Express.js handles
a large number of requests asynchronously. Its event-driven architecture
ensures responsiveness even under heavy loads.
5. Active Community Support: With a thriving community, Express.js
receives regular updates and improvements. You’ll find ample
documentation, tutorials, and plugins to enhance your development
experience.

Installing ExpressThe Express.js package is available on npm


package repository. Let us install express package locally in an
application folder named ExpressApp.

D:\expressApp> npm init


D:\expressApp> npm install express --save

The above command saves the installation locally in the


node_modules directory and creates a directory express inside
node_modules.

Hello world Example


Following is a very basic Express app which starts a server and
listens on port 5000 for connection. This app responds with Hello
World! for requests to the homepage. For every other path, it will
respond with a 404 Not Found.

var express = require('express');


var app = express();

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


res.send('Hello World');
})

var server = app.listen(5000, function () {


console.log("Express App running at http://127.0.0.1:5000/");
47

})

Save the above code as index.js and run it from the command-line.

D:\expressApp> node index.js


Express App running at http://127.0.0.1:5000/

Visit http://localhost:5000/ in a browser window. It displays the


Hello World message.

Application object
An object of the top level express class denotes the application
object. It is instantiated by the following statement −

var express = require('express');


var app = express();

The Application object handles important tasks such as handling


HTTP requests, rendering HTML views, and configuring middleware
etc.

The app.listen() method creates the Node.js web server at the


specified host and port. It encapsulates the createServer() method
in http module of Node.js API.

app.listen(port, callback);

Basic Routing
48

The app object handles HTTP requests GET, POST, PUT and DELETE
with app.get(), app.post(), app.put() and app.delete() method
respectively. The HTTP request and HTTP response objects are
provided as arguments to these methods by the NodeJS server. The
first parameter to these methods is a string that represents the
endpoint of the URL. These methods are asynchronous, and invoke
a callback by passing the request and response objects.

GET method

In the above example, we have provided a method that handles the


GET request when the client visits '/' endpoint.

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


res.send('Hello World');
})
 Request Object − The request object represents the HTTP
request and has properties for the request query string,
parameters, body, HTTP headers, and so on.
 Response Object − The response object represents the HTTP
response that an Express app sends when it gets an HTTP
request. The send() method of the response object formulates
the server's response to the client.

You can print request and response objects which provide a lot of
information related to HTTP request and response including cookies,
sessions, URL, etc.

The response object also has a sendFile() method that sends the
contents of a given file as the response.

res.sendFile(path)

Save the following HTML script as index.html in the root folder of


the express app.

<html>
<body>
<h2 style="text-align: center;">Hello World</h2>
49

</body>
</html>

Change the index.js file to the code below −

var express = require('express');


var app = express();
var path = require('path');

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


res.sendFile(path.join(__dirname,"index.html"));
})

var server = app.listen(5000, function () {

console.log("Express App running at http://127.0.0.1:5000/");


})

Run the above program and visit http://localhost:5000/, the


browser shows Hello World message as below:

Let us use sendFile() method to display a HTML form in the


index.html file.

<html>
<body>

<form action = "/process_get" method = "GET">


First Name: <input type = "text" name = "first_name"> <br>
50

Last Name: <input type = "text" name = "last_name"> <br>


<input type = "submit" value = "Submit">
</form>

</body>
</html>

The above form submits the data to /process_get endpoint, with


GET method. Hence we need to provide a app.get() method that
gets called when the form is submitted.

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


// Prepare output in JSON format
response = {
first_name:req.query.first_name,
last_name:req.query.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})

The form data is included in the request object. This method


retrieves the data from request.query array, and sends it as a
response to the client.

The complete code for index.js is as follows −

var express = require('express');


var app = express();
var path = require('path');

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

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


res.sendFile(path.join(__dirname,"index.html"));
})
51

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


// Prepare output in JSON format
response = {
first_name:req.query.first_name,
last_name:req.query.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})

var server = app.listen(5000, function () {


console.log("Express App running at http://127.0.0.1:5000/");
})

Visit http://localhost:5000/.

Now you can enter the First and Last Name and then click submit
button to see the result and it should return the following result −

{"first_name":"John","last_name":"Paul"}

POST method

The HTML form is normally used to submit the data to the server,
with its method parameter set to POST, especially when some
binary data such as images is to be submitted. So, let us change the
method parameter in index.html to POST, and action parameter to
"process_POST".

<html>
52

<body>

<form action = "/process_POST" method = "POST">


First Name: <input type = "text" name = "first_name"> <br>
Last Name: <input type = "text" name = "last_name"> <br>
<input type = "submit" value = "Submit">
</form>

</body>
</html>

To handle the POST data, we need to install the body-parser


package from npm. Use the following command.

npm install body-parser –save

This is a node.js middleware for handling JSON, Raw, Text and URL
encoded form data.

This package is included in the JavaScript code with the following


require statement.

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

The urlencoded() function creates application/x-www-form-


urlencoded parser

// Create application/x-www-form-urlencoded parser


var urlencodedParser = bodyParser.urlencoded({ extended: false })

Add the following app.post() method in the express application code


to handle POST data.

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


// Prepare output in JSON format
response = {
first_name:req.body.first_name,
last_name:req.body.last_name
53

};
console.log(response);
res.end(JSON.stringify(response));
})

Here is the complete code for index.js file

var express = require('express');


var app = express();
var path = require('path');

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


// Create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })

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

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


res.sendFile(path.join(__dirname,"index.html"));
})

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


// Prepare output in JSON format
response = {
first_name:req.query.first_name,
last_name:req.query.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})
app.post("/process_post", )
var server = app.listen(5000, function () {
console.log("Express App running at http://127.0.0.1:5000/");
})
54

Run index.js from command prompt and visit


http://localhost:5000/.

Now you can enter the First and Last Name and then click the
submit button to see the following result −

{"first_name":"John","last_name":"Paul"}

Serving Static Files


Express provides a built-in middleware express.static to serve static
files, such as images, CSS, JavaScript, etc.

You simply need to pass the name of the directory where you keep
your static assets, to the express.static middleware to start serving
the files directly. For example, if you keep your images, CSS, and
JavaScript files in a directory named public, you can do this −

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

We will keep a few images in public/images sub-directory as follows


node_modules
index.js
public/
public/images
public/images/logo.png

Let's modify "Hello Word" app to add the functionality to handle


static files.
55

var express = require('express');


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

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


res.send('Hello World');
})

var server = app.listen(5000, function () {


console.log("Express App running at http://127.0.0.1:5000/");
})

Save the above code in a file named index.js and run it with the
following command.

D:\expressApp> node index.js

Now open http://127.0.0.1:5000/images/logo.png in any browser


and see observe following result.

Introduction to NodejsNode.js is a powerful, open-source, cross-platform JavaScript


runtime environment built on Chrome's V8 JavaScript engine. It allows developers to run JavaScript code
56

outside the web browser, enabling server-side scripting to build scalable network applications. Here's an
introduction to Node.js:

Key Features:

1. Asynchronous and Event-Driven: Node.js utilizes a non-blocking, event-driven


architecture that makes it lightweight and efficient, suitable for handling concurrent
connections and I/O-heavy tasks.
2. Single-threaded, Non-blocking I/O Model: Unlike traditional server-side technologies,
Node.js operates on a single-threaded event loop, which enables handling multiple
connections simultaneously without creating new threads for each request. This approach
is particularly beneficial for handling I/O-bound operations efficiently.
3. NPM (Node Package Manager): Node.js comes with npm, the largest ecosystem of
open-source libraries and packages, which simplifies dependency management and
allows developers to easily install, share, and manage third-party modules.
4. Scalability: Node.js is well-suited for building highly scalable applications due to its
non-blocking nature and event-driven architecture. It can handle a large number of
concurrent connections with minimal resources, making it ideal for real-time applications
like chat servers, streaming platforms, and gaming servers.
5. Cross-Platform Compatibility: Node.js runs on multiple platforms, including Windows,
macOS, and Linux, providing developers with flexibility and portability in deploying
applications across different environments.
6. Rich Ecosystem: Node.js has a vibrant and active community that continuously
contributes to its ecosystem by developing and maintaining various frameworks, libraries,
and tools for web development, such as Express.js, Socket.IO, and Sequelize.

Use Cases:

1. Web Servers and APIs: Node.js is commonly used to build fast and scalable web
servers and APIs, powering a wide range of applications, including social networks, e-
commerce platforms, and content management systems.
2. Real-Time Applications: Its event-driven architecture makes Node.js well-suited for
building real-time applications like chat applications, online gaming platforms, and
collaboration tools, where instantaneous communication and updates are essential.
3. Microservices: Node.js is often used to build microservices architectures due to its
lightweight nature and ability to handle multiple microservices concurrently, facilitating
modularization and scalability in large-scale applications.
4. Data Streaming: Node.js is ideal for building data-intensive applications that involve
streaming large volumes of data, such as video streaming platforms, IoT (Internet of
Things) applications, and real-time analytics systems.

Conclusion:

Node.js revolutionizes server-side JavaScript development by enabling developers to build fast,


scalable, and real-time applications with JavaScript. Its asynchronous, event-driven architecture,
57

rich ecosystem, and cross-platform compatibility make it a popular choice for building a wide
range of web and network applications.

What is Nodejs,
What is Node.JS?
 Node.js is an open source server environment
 Node.js is free
 Node.js runs on various platforms (Windows, Linux, Unix, Mac OS X, etc.)
 Node.js uses JavaScript on the server

Node.js is an open-source, cross-platform JavaScript runtime


environment that executes JavaScript code outside of a web browser. It’s a
powerful tool used for various types of projects. Let’s explore some key
aspects:
 JavaScript Runtime: Node.js runs on the V8 JavaScript engine, which
is also the core engine behind Google Chrome. However, unlike the
browser context, Node.js executes JavaScript code outside of the
browser.
 Single Process Model: A Node.js application operates within a single
process, avoiding the need to create a new thread for every request. This
design choice contributes to Node.js’ performance.
 Asynchronous I/O: Node.js provides a set of asynchronous I/O
primitives in its standard library. These primitives prevent JavaScript
code from blocking, making non-blocking behavior the norm. When
performing I/O operations (e.g., reading from the network, accessing
databases, or the filesystem), Node.js doesn’t waste CPU cycles waiting.
Instead, it resumes operations when the response arrives.
 Concurrency Handling: Node.js efficiently handles thousands of
concurrent connections using a single server. It avoids the complexities
of managing thread concurrency, which can lead to bugs.
 JavaScript Everywhere: Frontend developers familiar with JavaScript
can seamlessly transition to writing server-side code using Node.js. You
don’t need to learn a different language.
 ECMAScript Standards: Node.js supports the latest ECMAScript
standards. You can choose the version you want to use, independent of
users’ browser updates.
58

Getting Started with Express 1. Install Node.js:


If you haven't already, you'll need to install Node.js on your system. You can download and
install it from the official Node.js website: nodejs.org.

2. Create a New Project Directory:

Create a new directory for your Express.js project. You can do this using the command line:

bash
Copy code
mkdir my-express-app
cd my-express-app

3. Initialize a Node.js project:

Initialize a new Node.js project by running the following command in your project directory:

bash
Copy code
npm init -y

This command creates a package.json file in your project directory, which will hold
information about your project and its dependencies.

4. Install Express.js:

Install Express.js as a dependency for your project using npm:

bash
Copy code
npm install express

This will download and install the Express.js framework in your project directory and add it to
your package.json file as a dependency.

5. Create Your First Express App:

Create a new JavaScript file (e.g., app.js) in your project directory and import the Express.js
module:

javascript
Copy code
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {


59

res.send('Hello World!');
});

app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});

This code creates a simple Express.js application that listens for HTTP GET requests on the root
URL (/) and responds with "Hello World!".

6. Run Your Express App:

Run your Express.js application by executing the following command in your project directory:

bash
Copy code
node app.js

This will start your Express.js server, and you should see a message indicating that the server is
running on http://localhost:3000.

7. Test Your Express App:

Open your web browser and navigate to http://localhost:3000 to see your Express.js
application in action. You should see the "Hello World!" message displayed in the browser.

Congratulations! You've now created and run your first Express.js application. From here, you
can continue to explore and learn more about the features and capabilities of Express.js to build
more complex web applications and APIs.

Express is a web application framework for Node.js that allows you to spin up robust
APIs and web servers in a much easier and cleaner way. It is a lightweight package that
does not obscure the core Node.js features.

In this article, you will install and use Express to build a web server.

Prerequisites
If you would like to follow along with this article, you will need:

 A local development environment for Node.js. Follow How to Install Node.js and Create
a Local Development Environment.
This tutorial was verified with Node v15.14.0, npm v7.10.0, express v4.17.1, and serve-
index v1.9.1.
Step 1 — Setting Up the Project
First, open your terminal window and create a new project directory:
60

1. mkdir express-example
2.
Copy

Then, navigate to the newly created directory:


1. cd express-example
2.
Copy

At this point, you can initialize a new npm project:


1. npm init -y
2.
Copy

Next, you will need to install the express package:


1. npm install express@4.17.1
2.
Copy

At this point, you have a new project ready to use Express.

Step 2 — Creating an Express Server


Now that Express is installed, create a new server.js file and open it with your code
editor. Then, add the following lines of code:
server.js
const express = require('express');

const app = express();


Copy
The first line here is grabbing the main Express module from the package you installed.
This module is a function, which we then run on the second line to create
our app variable. You can create multiple apps this way, each with its own requests and
responses.
server.js
const express = require('express');

const app = express();

app.get('/', (req, res) => {


res.send('Successful response.');
});

These lines of code is where we tell our Express server how to handle a GET request to
our server. Express includes similar functions for POST, PUT, etc.
using app.post(...), app.put(...), etc.
61

These functions take two main parameters. The first is the URL for this function to act
upon. In this case, we are targeting '/', which is the root of our website: in this
case, localhost:3000.
The second parameter is a function with two arguments: req, and res. req represents
the request that was sent to the server; We can use this object to read data about what
the client is requesting to do. res represents the response that we will send back to the
client.
Here, we are calling a function on res to send back a response: 'Successful
response.'.
server.js
const express = require('express');

const app = express();

app.get('/', (req, res) => {


res.send('Successful response.');
});

app.listen(3000, () => console.log('Example app is listening on port


3000.'));
Copy
Finally, once we’ve set up our requests, we must start our server! We are
passing 3000 into the listen function, which tells the app which port to listen on. The
function passed in as the second parameter is optional and runs when the server starts
up. This provides us some feedback in the console to know that our application is
running.

Revisit your terminal window and run your application:


1. node server.js
2.
Copy

Then, visit localhost:3000 in your web browser. Your browser window will
display: 'Successful response'. Your terminal window will display: 'Example app is
listening on port 3000.'.

And there we have it, a web server! However, we definitely want to send more than just
a single line of text back to the client. Let’s briefly cover what middleware is and how to
set this server up as a static file server!

Step 3 — Using Middleware


With Express, we can write and use middleware functions, which have access to all
HTTP requests coming to the server. These functions can:
 Execute any code.
 Make changes to the request and the response objects.
 End the request-response cycle.
62

 Call the next middleware function in the stack.

We can write our own middleware functions or use third-party middleware by importing
them the same way we would with any other package.

Let’s start by writing our own middleware, then we’ll try using some existing middleware
to serve static files.

To define a middleware function, we call app.use() and pass it a function. Here’s a


basic middleware function to print the current time in the console during every request:
server.js
const express = require('express');

const app = express();

app.use((req, res, next) => {


console.log('Time: ', Date.now());
next();
});

app.get('/', (req, res) => {


res.send('Successful response.');
});

app.listen(3000, () => console.log('Example app is listening on port


3000.'));
Copy

The next() call tells the middleware to go to the next middleware function if there is
one. This is important to include at the end of our function - otherwise, the request will
get stuck on this middleware.

We can optionally pass a path to the middleware, which will only handle requests to that
route. For example:

server.js
const express = require('express');

const app = express();

app.use((req, res, next) => {


console.log('Time: ', Date.now());
next();
});

app.use('/request-type', (req, res, next) => {


console.log('Request type: ', req.method);
next();
});

app.get('/', (req, res) => {


res.send('Successful response.');
63

});

app.listen(3000, () => console.log('Example app is listening on port


3000.'));
Copy

By passing '/request-type' as the first argument to app.use(), this function will only
run for requests sent to localhost:3000/request-type.

Revisit your terminal window and run your application:

1. node server.js
2.
Copy

Then, visit localhost:3000/request-type in your web browser. Your terminal window


will display the timestamp of the request and 'Request type: GET'.
Now, let’s try using existing middleware to serve static files. Express comes with a built-
in middleware function: express.static. We will also use a third-party middleware
function, serve-index, to display an index listing of our files.
First, inside the same folder where the express server is located, create a directory
named public and put some files in there.
Then, install the package serve-index:
1. npm install serve-index@1.9.1
2.
Copy

First, import the serve-index package at the top of the server file.
Then, include the express.static and serveIndex middlewares and tell them the path
to access from and the name of the directory:
server.js
const express = require('express');
const serveIndex = require('serve-index');

const app = express();

app.use((req, res, next) => {


console.log('Time: ', Date.now());
next();
});

app.use('/request-type', (req, res, next) => {


console.log('Request type: ', req.method);
next();
});

app.use('/public', express.static('public'));
app.use('/public', serveIndex('public'));

app.get('/', (req, res) => {


res.send('Successful response.');
64

});

app.listen(3000, () => console.log('Example app is listening on port


3000.'));
Copy

Now, restart your server and navigate to localhost:3000/public. You will be


presented with a listing of all your files!
Conclusion
In this article, you installed and used Express to build a web server. You also used built-
in and third-party middleware functions.

Your first Express App


First, ensure you have Node.js installed on your system. Then, follow these steps:

1. Create a project directory: Open your terminal and create a new directory for your
Express app. You can name it whatever you like:

bash
Copy code
mkdir my-express-app
cd my-express-app

2. Initialize a new Node.js project: Run the following command to create a package.json
file:

bash
Copy code
npm init -y

3. Install Express.js: Install Express.js as a dependency for your project:

bash
Copy code
npm install express

4. Create your Express app: Now, create a new file named app.js (or any other name you
prefer) in your project directory, and add the following code:

javascript
Copy code
// Import the Express module
const express = require('express');

// Create an Express application


const app = express();

// Define a route handler for the root URL


65

app.get('/', (req, res) => {


res.send('Hello World!');
});

// Start the Express server


const port = 3000;
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});

5. Run your Express app: Run the following command in your terminal to start the
Express server:

bash
Copy code
node app.js

You should see the message Server is running on http://localhost:3000 in your


terminal, indicating that the server is running.

6. Test your Express app: Open your web browser and navigate to
http://localhost:3000. You should see the text "Hello World!" displayed in the
browser window.

That's it! You've successfully created your first Express.js application. From here, you can
continue to explore and build more complex web applications and APIs using Express.js.

Creating an Express.js application involves several steps that guide you


through setting up a basic server to handle complex routes and middleware.
Express.js is a minimal and flexible Node.js web application framework that
provides a robust set of features for web and mobile applications. Here’s a
comprehensive guide to get you started with your Express.js application

Steps to Create an Express.js Application


Step 1: Write this command to create a NodeJS application in your terminal because
our express server will work inside the node application.
npm init
This will ask you for a few configurations about your project you can fill them
in accordingly, also you can change them later from the package.json file.
Note: Use ‘npm init -y’ for default initialization
66

Step 2: Install the necessary dependencies for our application. In this, we will install
express.js dependency.
npm install express
Something like this will be shown on successful installation.

Step 4: Create an app.js (or server.js) file. This will serve as the main entry point for
your application.
Project Structure:
67

The updated dependencies in package.json file will look like:


"dependencies": {
"express": "^4.19.2",
"mongoose": "^8.4.0"
}
Approach
 Use require('express') to import the Express module.
 Call express() to create an Express application instance.
 Define the port for the application, typically 3000.
 Set up a basic GET route with app.get('/', (req, res) => res.send('Hello
World!')).
 Use app.listen method to listen to your desired PORT and to start the
server.
Example: Implementation to setup the express application.
Node

const express = require('express');

const app = express();


const PORT = 3000;

app.listen(PORT, (error) =>{


if(!error)
console.log("Server is Successfully Running,
and App is listening on port "+ PORT)
else
console.log("Error occurred, server can't start", error);
}
);
Step to Run Application: Run the application using the following command
from the root directory of the project
node app.js
Output: You will see something like this on the terminal.

Now with all of this, we have created and run the server successfully, if your
server is not starting then there may be some error, try to analyze and read
68

that error and resolve it accordingly.


Finally, after a successful run if you try to open the URL (localhost:3000) on
the browser it will show you cannot GET / because we have not configured
any route on this application yet.
Step 5: Now we will set all the routes for our application.
Routes are the endpoints of the server, which are configured on our backend
server and whenever someone tries to access those endpoints they respond
accordingly to their definition at the backend. If you’re a beginner you can
consider route as a function that gets called when someone requests the
special path associated with that function and return the expected value as a
response. We can create routes for HTTP methods like get, post, put, and so
on.
Syntax:
The basic syntax of these types of routes looks like this, the given function
will execute when the path and the request method resemble.
app.anyMethod(path, function)
Setting GET request route on the root URL
 Use app.get() to configure the route with the path '/' and a callback
function.
 The callback function receives req (request) and res (response) objects
provided by Express.
 req is the incoming request object containing client data, and res is the
response object used to send data back to the client.
 Use res.status() to set the HTTP status code before sending the
response.
 Use res.send() to send the response back to the client. You can send a
string, object, array, or buffer. Other response methods
include res.json() for JSON objects and res.sendFile() files.
Example: Implementation to set up a basic request route on the root URL.
Node

//app.js

const express = require('express');

const app = express();


const PORT = 3000;

app.get('/', (req, res)=>{


res.status(200);
res.send("Welcome to root URL of Server");
});
69

app.listen(PORT, (error) =>{


if(!error)
console.log("Server is Successfully Running,
and App is listening on port "+ PORT)
else
console.log("Error occurred, server can't start", error);
}
);

Step to run the application: Save this code, restart the server, and open the
localhost on the given port. When a client requests with the appropriate
method on the specified path ex: GET request on ‘/’ path, our function returns
the response as plain text If we open the network section in Chrome
developers tools (press Ctrl+Shift+I to open) we will see the response
returned by the localhost along with all information.
Output:

Setting up one more get request route on


the ‘/hello’ path.
 Most of the things are the same as in the previous example.
 The set() function is used to set the HTTP header’s content type as HTML.
When the browser receives this response it will be interpreted as HTML
instead of plain text.
 Also in this example, we are not explicitly setting status, it is now
concatenated with the statement of sending the response. This is another
way to send status along with a response.
Example: Implementation to setup the one more route.
Node

//app.js

const express = require('express');


70

const app = express();


const PORT = 3000;

app.get('/hello', (req, res)=>{


res.set('Content-Type', 'text/html');
res.status(200).send("<h1>Hello GFG Learner!</h1>");
});

app.listen(PORT, (error) =>{


if(!error)
console.log("Server is Successfully Running, and App is
listening on port "+ PORT)
else
console.log("Error occurred, server can't start", error);
}
);

Step to run the application: Save this code, restart the server, and open the
localhost on the given port. Now access the ‘/hello’ route from the browser,
The h1 text inside HTML will be shown as a response.
Output:

Step 5: Now we will see how to send data to the server.


Sometimes we have to send our data to the server for processing, for
example when you try to log in on Facebook you send a password and email
to the server, Here we will see how to receive data from the user request.
We can send data with the request object on the specified path with
appropriate HTTP methods. Till now we were using the browser to interact
with the server, but in this step, any tool or frontend form is must be needed
to send data because the browser search bar can only send get requests to
receive resources from the server.
Setting route to be accessed by users to send data
with post requests.
71

 Before creating a route for receiving data, we are using an inbuilt


middleware, Middleware is such a broad and more advanced topic so we
are not going to discuss it here, just to understand a little bit you can think
of this as a piece of code that gets executed between the request-
response cycles.
 The express.json() middleware is used to parse the incoming request object
as a JSON object. The app. use() is the syntax to use any middleware.
 After that, we have created a route on path ‘/’ for post request.
 const {name}, which is the syntax in ES6 to extract the given property/es
from the object. Here we are extracting the name property that was sent
by the user with this request object.
 After that, we are simply sending a response to indicate that we have
successfully received data. If this `${} ` is looking weird to you then let me
tell you that it is the syntax in ES6 to generate strings with javascript
expression in ES6. We can inject any javascript expression inside ${}.
Example: Implementation to Setup route to be accessed by users to send
data with post requests.
Node

// app.js

const express = require('express');


const app = express();
const PORT = 3000;

app.use(express.json());
app.post('/', (req, res)=>{
const {name} = req.body;

res.send(`Welcome ${name}`);
})

app.listen(PORT, (error) =>{


if(!error)
console.log("Server is Successfully Running, and
App is listening on port "+ PORT)
else
console.log("Error occurred, server can't start", error);
}
);

Step to run the application: We are Accessing the route with Postman. It is a
tool to test APIs, we can use any other things like Axios, fetch, or any other
thing from the frontend or cURL from the terminal, but that will make you
divert from the topic, just keep in mind that our express server only demands
72

a path with request object it doesn’t matter from where it is coming. We


have sent the data as a JSON object with the request body and express is
sending a response back to us along with the data. It indicates that our goal
to send data to the server succeeded.
Output:

Step 5: Sending Files from Server


Step 6: Now we will see how to send files from the server.
Several times we need to transfer the resources from the server as per user
request, there are majorly two methods to send files one is sending static
files using middleware and the other one is sending a single file on a route.
This is our folder structure and we want to serve the files from the Static
Files directory as static files, and the image.jpg on a separate route.

Example 1: Serving entire directory using middleware


In Express, we use the middleware express.static() function, which takes two
arguments. The first argument is the absolute root path of the directory
containing the files we want to serve. We can easily serve static files by
using app.use() and providing the express.static() middleware.
Syntax:
app.use(path, express.static(root, [options]));
73

 First of all, we are importing an inbuilt module `path`, because later we


are going to use one of the functions provided by this module.
 We are simply mounting a middleware at the ‘/static’ route.
 The static() middleware requires an absolute path so we use the path
module’s join method.
 The join() method takes two parameters and joins them as a path, in
NodeJS we have a global attribute __dirname which contains the path of
the directory in which the current file exists.
 We are providing that joined path to middleware so that it can start
serving the files inside that directory on the given path.
Example: Implementation to show the use of middleware in Express.
app.js

// app.js

const express = require('express');


const app = express();
const PORT = 3000;

const path = require('path')


app.use('/static', express.static(path.join(__dirname, 'Static Files')))

app.listen(PORT, (error) =>{


if(!error)
console.log("Server is Successfully Running,
and App is listening on port "+ PORT)
else
console.log("Error occurred, server can't start", error);
}
);

Step to run the application: This will be the returned response when we
request some static file from the directory that we are serving as static. Here
you can see we have received an HTML file as a response
for ‘/static/random.html’. The same things happen when we request
for ‘/static/1.jpg’.
Output:
74

Example 2: Sending a single file on a route with the sendFile()


function.
This function accepts an absolute URL of the file and whenever the route
path is being accessed the server provides the file as an HTTP response.
This process can be thought of as a single endpoint of the express.static(). It
can be useful when we have to do some kind of processing before sending
the file.
Syntax:
res.sendFile(fileUrl)
 We are creating a get request route on the ‘/file’ path
 After that we create the absolute path by joining the path of the current
__dirname and the name of the file we want to send and then passing it to
sendFile().
 The route sends the image.jpg file to the user as an HTTP response.
Example: Implementation to show Sending a single file on a route with the
sendFile() function.
app.js

// app.js

const express = require('express');


const path = require('path');

const app = express();


const PORT = 3000;

app.get('/file', (req, res)=>{


res.sendFile(path.join(__dirname,'image.jpg'));
});

app.listen(PORT, (error) =>{


if(!error)
console.log("Server is Successfully Running, and App is listening on port
"+ PORT)
else
console.log("Error occurred, server can't start", error);
}
);
Output: After running the server, When we request the route ‘/file’ the server
sends the image.jpg file as a response.
75

Express Routing
Express express.Router() Function

The express.Router() function is used to create a new router object. This function is
used when you want to create a new router object in your program to handle requests.
Syntax:
express.Router( [options] )
Optional Parameters:
 case-sensitive: This enables case sensitivity.
 mergeParams: It preserves the req.params values from the parent router.
 strict: This enables strict routing.
Return Value: This function returns the New Router Object.
Steps to Install the express module:
Step 1: You can install this package by using this command.
npm install express
Step 2: After installing the express module, you can check your express version in the
command prompt using the command.
npm version express
Step 3: After that, you can just create a folder and add a file, for example, index.js. To
run this file you need to run the following command.
node index.js
Project Structure:

Project Structure

The updated dependencies in package.json file will look like:


"dependencies": {
"express": "^4.18.2",
}
Example 1: Below is the code of express.Router() Function implementation.
 javascript
76

const express = require('express');


const app = express();
const PORT = 3000;

// Single routing
const router = express.Router();

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


console.log("Router Working");
res.end();
})

app.use(router);

app.listen(PORT, function (err) {


if (err) console.log(err);
console.log("Server listening on PORT", PORT);
});

Steps to run the program: Run the index.js file using the below command:
node index.js
Output:
Console Output:
Server listening on PORT 3000
Browser Output:
Now open your browser and go to http://localhost:3000/, you will see the following
output on your screen:
Server listening on PORT 3000
Router Working
Example 2: Below is the another code example of express.Router() Function
implementation.
 javascript
const express = require('express');
const app = express();
const PORT = 3000;

// Multiple routing
const router1 = express.Router();
const router2 = express.Router();

const router3 = express.Router();


router1.get('/user', function (req, res, next) {
77

console.log("User Router Working");


res.end();
});

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


console.log("Admin Router Working");
res.end();
});

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


console.log("Student Router Working");
res.end();
});

app.use(router1);
app.use(router2);
app.use(router3);
app.listen(PORT, function (err) {
if (err) console.log(err);
console.log("Server listening on PORT", PORT);
});

Steps to run the program: Run the index.js file using the below command:
node index.js
Now make a GET request
to http://localhost:3000/user, http://localhost:3000/admin, and
http://localhost:3000/student, then you will see the following output on your console:
Output:
Server listening on PORT 3000
User Router Working
Admin Router Working
Student Router Working

Routing refers to how an application’s endpoints (URIs) respond to client requests. For an
introduction to routing, see Basic routing.

You define routing using methods of the Express app object that correspond to HTTP methods; for
example, app.get() to handle GET requests and app.post to handle POST requests. For a full
list, see app.METHOD. You can also use app.all() to handle all HTTP methods and app.use() to
specify middleware as the callback function (See Using middleware for details).

These routing methods specify a callback function (sometimes called “handler functions”) called
when the application receives a request to the specified route (endpoint) and HTTP method. In other
words, the application “listens” for requests that match the specified route(s) and method(s), and
when it detects a match, it calls the specified callback function.
78

In fact, the routing methods can have more than one callback function as arguments. With multiple
callback functions, it is important to provide next as an argument to the callback function and then
call next() within the body of the function to hand off control to the next callback.

The following code is an example of a very basic route.


const express = require('express')
const app = express()

// respond with "hello world" when a GET request is made to the homepage
app.get('/', (req, res) => {
res.send('hello world')
})

Route methods
A route method is derived from one of the HTTP methods, and is attached to an instance of
the express class.

The following code is an example of routes that are defined for the GET and the POST methods to
the root of the app.
// GET method route
app.get('/', (req, res) => {
res.send('GET request to the homepage')
})

// POST method route


app.post('/', (req, res) => {
res.send('POST request to the homepage')
})

Express supports methods that correspond to all HTTP request methods: get, post, and so on. For
a full list, see app.METHOD.

There is a special routing method, app.all(), used to load middleware functions at a path
for all HTTP request methods. For example, the following handler is executed for requests to the
route “/secret” whether using GET, POST, PUT, DELETE, or any other HTTP request method
supported in the http module.
app.all('/secret', (req, res, next) => {
console.log('Accessing the secret section ...')
79

next() // pass control to the next handler


})

Route paths
Route paths, in combination with a request method, define the endpoints at which requests can be
made. Route paths can be strings, string patterns, or regular expressions.

The characters ?, +, *, and () are subsets of their regular expression counterparts. The hyphen ( -)
and the dot (.) are interpreted literally by string-based paths.

If you need to use the dollar character ( $) in a path string, enclose it escaped within ([ and ]). For
example, the path string for requests at “/data/$book”, would be “/data/([\$])book”.

Express uses path-to-regexp for matching the route paths; see the path-to-regexp documentation for all the
possibilities in defining route paths. Express Route Tester is a handy tool for testing basic Express routes, although it
does not support pattern matching.
Query strings are not part of the route path.

Here are some examples of route paths based on strings.

This route path will match requests to the root route, /.


app.get('/', (req, res) => {
res.send('root')
})

This route path will match requests to /about.


app.get('/about', (req, res) => {
res.send('about')
})

This route path will match requests to /random.text.


app.get('/random.text', (req, res) => {
res.send('random.text')
})

Here are some examples of route paths based on string patterns.

This route path will match acd and abcd.


app.get('/ab?cd', (req, res) => {
res.send('ab?cd')
80

})

This route path will match abcd, abbcd, abbbcd, and so on.
app.get('/ab+cd', (req, res) => {
res.send('ab+cd')
})

This route path will match abcd, abxcd, abRANDOMcd, ab123cd, and so on.
app.get('/ab*cd', (req, res) => {
res.send('ab*cd')
})

This route path will match /abe and /abcde.


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

Examples of route paths based on regular expressions:

This route path will match anything with an “a” in it.


app.get(/a/, (req, res) => {
res.send('/a/')
})

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

Express routing allows you to define routes to handle different HTTP requests and URLs in your
application. Routing is a fundamental aspect of building web applications and APIs with
Express.js. Here's how you can use routing in Express:

Basic Routing:
81

1. Defining Routes: In Express, you define routes using the HTTP methods ( GET, POST,
PUT, DELETE, etc.) and URL patterns. For example:

javascript
Copy code
// Respond to GET requests on the root URL
app.get('/', (req, res) => {
res.send('Hello from Express!');
});

// Respond to POST requests on the '/login' URL


app.post('/login', (req, res) => {
// Handle login logic
});

2. Route Parameters: You can define route parameters in the URL pattern, which are
placeholders for dynamic values. For example:

javascript
Copy code
// Route with a parameter
app.get('/users/:userId', (req, res) => {
const userId = req.params.userId;
// Fetch user data based on userId
});

You can access route parameters using req.params.

3. Route Handlers: Route handlers are callback functions that execute when a matching
route is accessed. They take two arguments: req (the request object) and res (the
response object). For example:

javascript
Copy code
app.get('/about', (req, res) => {
res.send('About Us');
});

Route Methods:

Express supports all standard HTTP methods ( GET, POST, PUT, DELETE, etc.) for defining routes.
Here's how you can use them:

javascript
Copy code
app.get('/products', (req, res) => {
// Handle GET request for retrieving products
});

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


// Handle POST request for creating a new product
});
82

app.put('/products/:id', (req, res) => {


// Handle PUT request for updating a product
});

app.delete('/products/:id', (req, res) => {


// Handle DELETE request for deleting a product
});

Middleware in Routing:

You can use middleware functions in routing to perform tasks like authentication, logging, and
error handling. Middleware functions are executed in the order they are defined. For example:

javascript
Copy code
// Middleware function
function authenticate(req, res, next) {
// Check authentication
if (authenticated) {
next(); // Call the next middleware function
} else {
res.status(401).send('Unauthorized');
}
}

// Route with middleware


app.get('/profile', authenticate, (req, res) => {
// Handle request after authentication
});

Route Chaining:

You can chain multiple route handlers together for a single route. This is useful for reusing
middleware across multiple routes. For example:

javascript
Copy code
app.get('/admin', authenticate, (req, res, next) => {
// Middleware for admin routes
// ...
next();
}, (req, res) => {
// Route handler for admin route
// ...
});

Express routing provides a flexible and powerful way to define the behavior of your web
application or API endpoints. By defining routes, handling requests, and using middleware
functions, you can create robust and scalable applications with Express.js.

What is Model-View-Controller (MVC)?


83

MVC is simply a design or architectural pattern used in software engineering. Its main goal is to
split large applications into specific sections that each have their own purpose.

MVC also allows developers to logically structure applications in a secure way, which we will
demonstrate in this tutorial. But first, let’s break down what each layer of the pattern provides.

Model

As the name implies, a model is a design or structure that typically bounds with an OOP entity of
a specific software system.

In the case of MVC, the model determines how a database is structured, defining a section of the
application that interacts with the database. The model layer holds the database
connection/manipulation logic and exposes methods that only use model objects by putting an
abstraction layer over raw data formats used by the database. The ORM libraries help us define
models without worrying about database-to-model mapping.

View

The view is where end users interact within the application. Simply put, this is where all the
HTML template files go in MVC-architectured web apps. The view layer never communicates
directly with the model — it communicates with the model layer strictly through the controller.

Controller

The controller interacts with the model and serves the response and functionality to the view.
When an end user makes a request, it’s sent to the controller, which interacts with the database.

You can think of the controller as a waiter in a restaurant that handles customers’ orders, which
in this case is the view. The waiter then goes to the kitchen, which is the model/database and gets
food to serve the customers, which is the controller handling the request.

Now, let’s build a sample Node.js web app using the MVC pattern!

Setting up the application

To understand how to use MVC, we will build a simple login and registration system with a
dashboard page that only authenticated users can access. However, this tutorial is more about
structure than about the application we are building.

Open up your terminal in an empty folder and run the following command to
create a new Node.js project:
npm init -y
# --- or ---
yarn init -y
84

This command creates a package.json file with some default configuration


according to the package manager you used.

For this project, we will need to install some packages to get started:
npm install express express-session pug sequelize sqlite3 bcryptjs passport
passport-local
# --- or ---
yarn add express express-session pug sequelize sqlite3 bcryptjs passport passport-
local
These packages provide the following facilities:
o express is used to implement the app’s HTTP endpoints and render
app views
o express-session is used to create an HTTP cookie-based user session
for Express routes
o pug is used to render server-side HTML views using Pug-based
templates
o sequelize implements ORM logic and helps define models with less
code
o sqlite3 works as the primary database system with
the sequelize package
o bycrptjs handles hashing passwords before saving them in the
database
o passport and passport-local handle authentication
After this is complete, you should see a node_modules folder (this is where
all the packages are downloaded to).

Now create three folders to represent MVC layers: models, views,


and controllers:
mkdir models views controllers
Setting up the server
While we’ve created our folders, they can’t do anything without a server. To
create our server, let’s create a file called server.js in our root directory:
touch server.js
After creating the server.js file, go to the package.json file and edit
the scripts like so:
"scripts": {
"start": "node server.js"
}
Now, we can run the start script to run our web app.
85

Let’s create our Express server instance that helps process and return HTTP
messages. Copy and paste the following code into the server.js file:
const express = require('express');
const app = express();
const PORT = 8080;

app.get('/', (req, res) => res.send('<h1>Hello Express</h1>'));

app.listen(PORT, console.log('Server is running on port: ' + PORT));


Remember that we already installed Express. Now, we are simply creating an
Express app with one sample endpoint on GET /.

On line seven, we are now using the listen() method to start up a server
that runs at http://localhost:8080. To confirm that our server works
properly, run the following:
npm start
# --- or ---
yarn start
Open the server endpoint from the browser. You’ll see a greeting message as
follows confirming that the Express server works:

Now, our server is ready. Let’s add views, controllers, and routes!

Creating views, controllers, and routes


With our server up and running, let’s create some .pug template files in our views folder.
Because we are following the MVC pattern, we need all our views — that is, what the end users
see — to be in one folder.

Designing views with Pug

Inside the views folder, create the following


files: login.pug, register.pug, dashboard.pug, and layout.pug.

The layout.pug code is included across all .pug files in the views folder.
First, add the following contents to the layout.pug file:
86

doctype html
head
meta(charset='utf-8')
title Node.js MVC Demo
meta(name='viewport' content='width=device-width, initial-scale=1')

link(href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css
' rel='stylesheet' integrity='sha384-
QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH'
crossorigin='anonymous')
nav.navbar.navbar-expand-lg.navbar-dark.bg-dark
.container-fluid
a.navbar-brand(href='#') Node.js MVC Demo
button.navbar-toggler(type='button' data-bs-toggle='collapse' data-bs-
target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-
expanded='false' aria-label='Toggle navigation')
span.navbar-toggler-icon
if name
#navbarSupportedContent.collapse.navbar-collapse.justify-content-end
form.d-flex
span.navbar-text.text-light.pe-2 Hello #{name}
a.btn.btn-outline-light(href='/logout') Logout
.py-2
block content

script(src='https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.
min.js' integrity='sha384-
MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM'
crossorigin='anonymous')
We used the block content statement here to inject child template contents
from other .pug files.

Add the following code to the login.pug file:


extends layout.pug
block content
.container
.row.justify-content-center
.col-md-8
.card
.card-header Login
.card-body
form.form-horizontal(method='post' action='/login')
.mb-3
label.form-label.control-label(for='email') Email
input#email.form-control(type='email' name='email')
.mb-3
label.form-label.control-label(for='password') Password
input#password.form-control(type='password' name='password')
.mb-3.py-3
button.btn.btn-primary(type='submit') Login
a(href='/register').ps-2 Register
Here we used the extends keyword and the block content statement to
inject the login view contents into the common layout.pug content’s block
content area. So, whenever the user requests the login view, the Express
87

server will create a complete HTML page that contains the login interface by
injecting login.pug into the layout.pug file with the help of the Pug
templating engine.

Create the register view by adding the following contents to


the register.pug file:
extends layout.pug
block content
.container
.row.justify-content-center
.col-md-8
if error
.alert.alert-warning= error
.card
.card-header Register
.card-body
form.form-horizontal(method='post' action='/register')
.mb-3
label.form-label.control-label(for='name') Name
input#name.form-control(type='text' name='name')
.mb-3
label.form-label.control-label(for='email') E-mail
input#email.form-control(type='email' name='email')
.mb-3
label.form-label.control-label(for='password') Password
input#password.form-control(type='password' name='password')
.mb-3.py-3
button.btn.btn-primary.login-button(type='submit') Register
a(href='/login').ps-2 Login
Finally, create the last view, the dashboard view, by adding the following
contents to the dashboard.pug file:
extends layout.pug

block content
.container
h4 Dashboard
span Only authenticated users can view this dashboard view.
We need to render these Pug templates from controllers by following MVC
project structuring practices, but let’s render them directly through
the server.js to test the views, as shown in the following code snippet:
const express = require('express');
const app = express();
const PORT = 8080;

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

app.get('/', (req, res) => res.render('dashboard'));


app.get('/login', (req, res) => res.render('login'));
app.get('/register', (req, res) => res.render('register'));

app.listen(PORT, console.log('Server is running on port: ' + PORT));


88

Run the app. Now you can see the dashboard, login, and register views from
your web browser:

These views are not dynamic and form post actions won’t work yet, so we need to complete the
MVC app by creating controllers and models.

Creating controllers

A controller is responsible for generating a specific view by fetching data objects from models.
Controllers are usually mapped with routes/endpoints through handlers. For example,
the /login route will return the login.pug view by communicating with the login view
controller’s loginView handler.

Let’s create a new file to implement controller handlers related to login/register routes. Create a
file named auth.js inside the controllers folder and add the following code:

module.exports = {
registerView: (req, res) => {
res.render('register');
},

loginView: (req, res) => {


res.render('login');
},

registerUser: (req, res) => {


// TODO: complete
res.redirect('register');
},

loginUser: (req, res) => {


// TODO: complete
res.redirect('login');
},

logoutUser: (req, res) => {


// TODO: complete
res.redirect('login');
89

}
}
Here, registerView and loginView functions/handlers render
the register.pug and login.pug views, respectively. We’ll
use registerUser and loginUser functions for registering and authenticating
users after implementing models.

Create a controller for the dashboard page by adding the following contents
to the controllers/dashboard.js file:
module.exports = {
dashboardView: (req, res) => {
res.render('dashboard');
}
}

Defining routes using controllers and views

In large-scale apps, we can simplify the complex MVC app structure by linking controllers via
router modules. For example, the invoices router module can map all invoice-related controllers
with the /invoices router path.
Let’s use this practice in this MVC app too, so you can use this as a template for creating large-
scale apps. Create a new folder to store router modules:
mkdir routes
Create a new file named auth.js inside the routes folder and link log-in/register related controller
handlers with routes, as shown in the following code:
const express = require('express');
const authController = require('../controllers/auth');
const dashboardController = require('../controllers/dashboard');

const router = express.Router();


router.get('/register', authController.registerView);
router.get('/login', authController.loginView);
router.get('/logout', authController.logoutUser);
router.post('/register', authController.registerUser);
router.post('/login', authController.loginUser);

module.exports = router;
Do the same for the dashboard controller by creating
the routes/dashboard.js router module:
const express = require('express');
const dashboardController = require('../controllers/dashboard');

const router = express.Router();


router.get('/', dashboardController.dashboardView);

module.exports = router;
Update the server.js file to use newly created router modules:
const express = require('express');
const authRoutes = require('./routes/auth');
90

const dashboardRoutes = require('./routes/dashboard');

const app = express();


const PORT = 8080;

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


app.use('/', authRoutes);
app.use('/', dashboardRoutes);

app.listen(PORT, console.log('Server is running on port: ' + PORT));


Now, our routes and controllers are properly structured. Run the app. You’ll see all three views
rendered on the browser properly, but views are still not dynamic and not functioning as
expected, so now we need to implement the database layer by creating models.

Creating models using Sequelize.js


This MVC app will use an SQLite database via the Sequelize ORM library that supports multiple
database systems like MySQL, OracleDB, etc.

Connecting to the database

If you use an ORM library, you undoubtedly don’t need to run database-specific queries and
handle connection management logic in normal use cases because ORMs internally do these as
inbuilt core features for you. We only have to define models and manipulate/query them with
methods provided by the ORM library.

Create a new file named db.js in the root of the project directory and add the following code to
set the database connection configuration for Sequelize.js:

const path = require('path');


const { Sequelize } = require('sequelize');

module.exports = new Sequelize({


dialect: 'sqlite',
storage: path.join(__dirname, 'mvc_demo.sqlite')
});
The above Sequelize.js setup instructs us to use SQLite as the underlying
database engine and save the database into the mvc_demo.sqlite file. Now,
we can use the above exported Sequelize instance to define models in any
part of the project codebase.
Creating a model for users

Models are what communicate directly to our database. Let’s create a new
model for users in the models/User.js. file using the following code:
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = require('../db');

module.exports = sequelize.define(
91

'User',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
},
email: {
type: DataTypes.STRING,
unique: true,
},
password: {
type: DataTypes.STRING,
},
}
);
These are the fields we want to insert into the database whenever a new user registers through
the registration page. We can store a name, unique email address, hashed password, and auto-
generated incremental integer as the unique user identifier.
Update the server.js source file as follows to synchronize models with the SQLite and activate
HTTP-body-parser to fetch form data from post requests:
const express = require('express');
const authRoutes = require('./routes/auth');
const dashboardRoutes = require('./routes/dashboard');
const db = require('./db.js');

const app = express();


const PORT = 8080;

app.use(express.urlencoded({extended: false}));
app.set('view engine', 'pug');
app.use('/', authRoutes);
app.use('/', dashboardRoutes);

db.sync({ force: false })


.then(() => {
app.listen(PORT, console.log('Server is running on port: ' + PORT));
});
Now, the MVC app tests the database connection before running the server when you run
the start script, as shown in the following preview:
92

Implementing user registration

We have created a schema to store our user information in our database inside the User.js file
within the models folder. Now, we can insert a new user into the database from a controller using
the User model.
Whenever an end user hits the Register button in the register view, a POST request is sent to
the /register route (remember what we did before was a GET request). To make this work, we
must go to controllers/auth.js and require the User.js model and bcryptjs because we must hash
the password:
const bcrypt = require('bcryptjs');
const User = require('../models/User');
Next, update the registerUser handler in the controllers/auth.js with
the following implementation:
registerUser: async (req, res) => {
const { name, email, password } = req.body;
if(!name || !email || !password) {
return res.render('register', { error: 'Please fill all fields' });
}

if(await User.findOne({where: {email}})) {


return res.render('register', { error: 'A user account already exists with
this email' });
}

await User.create({name, email, password: bcrypt.hashSync(password, 8)});

res.redirect('login?registrationdone');
},
On line two, we get all the inputs submitted into the form by users:
const { name, email, password } = req.body;
req.body is an Express API object that holds the submitted form data through the frontend of our
application.
After line two, we validate incoming data fields with an if condition and send an error message
to register.pug if all fields are not properly filled.
Also, we check whether a user account already exists with the given email address by using
the User.findOne() Sequelize.js library method. If the specific email already exists on the
database, we send another error message to the register.pug template.
Note that here, we hash the password with bcryptjs before saving it in the database to improve
app security factors.
Run the app. Now when ever a user selects the Register button, if everything checks out, the
form will create a user instance in the database and redirect them to the login page, as shown in
the following preview:
93

Integrating user authentication with bcrypt.js and


Passport.js
We have made the user registration process work. Now let’s work on the login flow of our
application.To ensure our login page works, we must authenticate users using Passport.js. If
there is a user in the database with the specified email, we’ll compare the user-entered password
using bcryptjs and let Passport.js redirect the user to the protected sample dashboard view.For
better codebase organization, let’s create a new file named auth.js in the root of the project folder
to write user authentication-related logic.
Add the following code to the auth.js file:
const passport = require('passport');
const LocalStrategy = require('passport-local');
const bcrypt = require('bcryptjs');
const User = require("./models/User");

module.exports = {
init: () => {
passport.use(
new LocalStrategy({ usernameField: 'email' }, async (email, password, done)
=> {
const user = await User.findOne({where: { email }});
if(!user) return done(null, false);
if(!bcrypt.compareSync(password, user.password)) return done(null, false);
return done(null, user);
})
);

passport.serializeUser((user, done) => {;


done(null, user.id);
});

passport.deserializeUser(async (id, done) => {


const user = await User.findOne({where: { id }});
done(null, user);
});

},
protectRoute: (req, res, next) =>{
if(req.isAuthenticated()) {
94

return next();
}
res.redirect('/login?next=' + req.url);
}
};
The above code implements two exported functions:
o init(): This function is responsible for activating username and password-based
authentication strategy for Passport.js. This Passport.js configuration strategy uses email
as the username and the password field as the login password. The init() function returns
the User model if the user with the given email exists and the password comparison
process succeeds
o protectedRoute(): This handler works as an Express route protection middleware that
redirects unauthenticated users to the login page. We’ll use this handler to protect the
dashboard page of the sample MVC app
Now, we need to implement the loginUser handler of the controllers/auth.js file to complete the
authentication process. Update the loginUser handler as follows. Make sure to import passport:
loginUser: (req, res) => {
passport.authenticate('local', {
successRedirect: '/?loginsuccess',
failureRedirect: '/login?error'
})(req, res);
},
The above loginUser function authenticates users using Passport.js by
calling the passport.authenticate() function.

Next, protect the dashboard view from unauthenticated users by using


the protectRoute handler by updating the routes/dashboard.js as follows:
const express = require('express');
const dashboardController = require('../controllers/dashboard');
const { protectRoute } = require('../auth');

const router = express.Router();

router.get('/', protectRoute, dashboardController.dashboardView);

module.exports = router;
Finally, configure the Express session and initialize Passport.js from
your server.js file, as shown in the following source code:
const express = require('express');
const passport = require('passport');
const session = require('express-session');
const authRoutes = require('./routes/auth');
const dashboardRoutes = require('./routes/dashboard');
const db = require('./db.js');
const { init: initAuth } = require('./auth');

const app = express();


const PORT = 8080;

app.use(express.urlencoded({extended: false}));
app.set('view engine', 'pug');
95

initAuth();
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));

app.use(passport.initialize());
app.use(passport.session());

app.use('/', authRoutes);
app.use('/', dashboardRoutes);

db.sync({ force: false })


.then(() => {
app.listen(PORT, console.log('Server is running on port: ' + PORT));
});
Now, you can test the login feature by entering a valid username and
password:

You won’t see the logout button and greeting text yet in the navigation bar area when you are on
the dashboard page because we haven’t passed the name data field to the layout.pug template file
yet.

Implementing the logout feature

Pass the name data field to the layout.pug file to display the logout button and greeting line for
authenticated users. You can do so by updating the controllers/dashboard.js as
follows:
module.exports = {
dashboardView: (req, res) => {
res.render('dashboard', { name: req.user.name });
}
}
Here, we used only one data field called name to detect the login state from Pug templates, but in
production apps, you can pass a user details object to the template that contains their first name,
96

last name, username, etc.Passport.js’s internal middleware automatically attaches a logout


function to every Express request, so you can easily complete the logout flow by adding the
following logoutUser handler into the controllers/auth.js exports:
logoutUser: (req, res) => {
req.logout(() => res.redirect('/login?loggedout'));
}
Now, you will see the logout button and greeting message when you visit the dashboard page
and be able to log out from the app by clicking on the logout button, as shown in the following
preview:

Also, when you visit the protected dashboard page without logging in, you will be redirected to
the login page. Don’t forget to test that, too.Now, the sample Node.js MVC is ready. You can
even use this structure for developing large-scale apps as we properly decomposed the project
into several folders and files.

Implementing the Model-View-Controller (MVC) pattern in an Express.js application helps


organize your code into separate modules for better maintainability and scalability. Here's a basic
guide on how to implement MVC in an Express.js application:

1. Project Structure:

Create a project structure that separates your code into model, view, and controller directories:

go
Copy code
my-express-app/
├── controllers/
│ └── UserController.js
├── models/
│ └── User.js
├── views/
│ └── index.ejs
├── routes/
│ └── index.js
├── app.js
└── package.json
97

2. Model:

Define your data models in the models directory. These models represent the structure of your
application's data. For example, let's create a User model in models/User.js:

javascript
Copy code
// models/User.js
class User {
constructor(id, name, email) {
this.id = id;
this.name = name;
this.email = email;
}
}

module.exports = User;

3. View:

Create your views using template engines like EJS or Pug in the views directory. For example,
let's create an index.ejs file in views:

html
Copy code
<!-- views/index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User List</title>
</head>
<body>
<h1>User List</h1>
<ul>
<% users.forEach(user => { %>
<li><%= user.name %> (<%= user.email %>)</li>
<% }); %>
</ul>
</body>
</html>

4. Controller:

Define your route handlers in the controllers directory. These controllers handle the logic for
handling HTTP requests and rendering views. For example, let's create a UserController in
controllers/UserController.js:

javascript
Copy code
// controllers/UserController.js
98

const User = require('../models/User');

const users = [
new User(1, 'John Doe', 'john@example.com'),
new User(2, 'Jane Doe', 'jane@example.com')
];

exports.getAllUsers = (req, res) => {


res.render('index', { users });
};

5. Routes:

Define your routes in the routes directory. These routes map HTTP requests to controller
actions. For example, let's create an index.js file in routes:

javascript
Copy code
// routes/index.js
const express = require('express');
const router = express.Router();
const UserController = require('../controllers/UserController');

router.get('/', UserController.getAllUsers);

module.exports = router;

6. App Setup:

In your app.js file, set up Express and configure routes, views, and middleware:

javascript
Copy code
// app.js
const express = require('express');
const app = express();
const indexRoutes = require('./routes/index');

// Set up view engine


app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');

// Routes
app.use('/', indexRoutes);

// Start the server


const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});

7. Run the Application:


99

Start your Express application:

bash
Copy code
node app.js

Visit http://localhost:3000 in your browser to see the list of users rendered using the EJS
template.

This setup demonstrates a basic implementation of MVC in an Express.js application. As your


application grows, you can further modularize your code by adding more models, views,
controllers, and routes.

Middleware in Express

Express serves as a routing and Middleware framework for handling the different routing of the
webpage and it works between the request and response cycle.
Middleware gets executed after the server receives the request and before the controller actions
send the response. Middleware has and access to the request object, responses object, and next,
it can process the request before the server sends a response. An Express-based application is a
series of middleware function calls. In this article, we will discuss what is middleware in
express.js.

Middleware working

What is Middleware in Express JS


Middleware is a request handler that allows you to intercept and manipulate requests and
responses before they reach route handlers. They are the functions that are invoked by the
Express.js routing layer.
It is a flexible tool that helps in adding functionalities like logging, authentication, error
handling, and more to Express applications.
Middleware Syntax
The basic syntax for the middleware functions is:
app.get(path, (req, res, next) => {}, (req, res) => {})
100

Middleware functions take 3 arguments: the request object, the response object, and the next
function in the application’s request-response cycle, i.e., two objects and one function.
Middleware functions execute some code that can have side effects on the app and usually add
information to the request or response objects. They are also capable of ending the cycle by
sending a response when some condition is satisfied. If they don’t send the response when they
are done, they start the execution of the next function in the stack. This triggers calling the 3rd
argument, next().
The middle part (req,res,next)=>{} is the middleware function. Here we generally perform the
actions required before the user is allowed to view the webpage or call the data and many other
functions. So let us create our own middleware and see its uses.
Using Middleware in Express
Follow the steps below to use Middleware in Express.js:
Step 1: Go to your project directory and enter the following command to create a NodeJs
project. Make sure that NodeJs is installed in your machine.
npm init -y
Step 2: Install two dependencies using the following command.
npm install express nodemon
Step 3: In the scripts section of the package.json file, add the following code line.
"start": "nodemon index.js",
Step 4: Create an index.js file in the directory. Make sure that it is not inside any subdirectories
of the directory you are working in.
Project Structure:

Project Structure

The updated dependencies in package.json file will look like:


"dependencies": {
"express": "^4.18.2",
}
Step 5: Now we will set up our express app and send a response to our server. Here
is the code for the index.js file.
 Javascript

const express = require("express");


101

const app = express();


const port = process.env.port || 3000;
app.get("/", (req, res) => {
res.send(`<div>
<h2>Welcome to GeeksforGeeks</h2>
<h5>Tutorial on Middleware</h5>
</div>`);
});
app.listen(port, () => {
console.log(`Listening to port ${port}`);
});

Step to run the application: Run the code by entering the following command on the
terminal.
npm start
Output:

Example
Creating a Middleware in the app.get() function, modify accordingly to the following
code.
 Javascript
app.get(
"/",
(req, res, next) => {
console.log("hello");
next();
},
(req, res) => {
res.send(
`<div>
<h2>Welcome to GeeksforGeeks</h2>
<h5>Tutorial on Middleware</h5>
</div>`
);
}
);
102

Output:

Middleware

Types of Middleware
Express JS offers different types of middleware and you should choose the middleware on the
basis of functionality required.
 Application-level middleware: Bound to the entire application
using app.use() or app.METHOD() and executes for all routes.
 Router-level middleware: Associated with specific routes
using router.use() or router.METHOD() and executes for routes defined within that router.
 Error-handling middleware: Handles errors during the request-response cycle. Defined
with four parameters (err, req, res, next).
 Built-in middleware: Provided by Express (e.g., express.static, express.json, etc.).
 Third-party middleware: Developed by external packages (e.g., body-parser, morgan, etc.).
Middleware Chaining
Middleware can be chained from one to another, Hence creating a chain of functions that are
executed in order. The last function sends the response back to the browser. So, before sending
the response back to the browser the different middleware processes the request.
The next() function in the express is responsible for calling the next middleware function if there
is one.
Modified requests will be available to each middleware via the next function

Middleware chaining example


103

In the above case, the incoming request is modified and various operations are
performed using several middlewares, and middleware is chained using the next
function. The router sends the response back to the browser.
Advantages of using Middleware
 Middleware can process request objects multiple times before the server works for
that request.
 Middleware can be used to add logging and authentication functionality.
 Middleware improves client-side rendering performance.
 Middleware is used for setting some specific HTTP headers.
 Middleware helps with Optimization and better performance

Middleware in Express.js allows you to execute code during the request-response cycle. It can
modify request and response objects, terminate the request-response cycle, or call the next
middleware function in the stack. Middleware functions are essential for tasks like
authentication, logging, error handling, and data parsing. Here's how you can use middleware in
Express:

Built-in Middleware:

Express provides several built-in middleware functions that you can use in your application:

1. express.json(): This middleware parses incoming requests with JSON payloads and
populates the req.body property with the parsed JSON data.
2. express.urlencoded(): This middleware parses incoming requests with URL-encoded
payloads and populates the req.body property with the parsed data.
3. express.static(): This middleware serves static files (e.g., HTML, CSS, images) from
a specified directory.

Custom Middleware:

You can also create custom middleware functions to perform specific tasks. Middleware
functions take three arguments: req (the request object), res (the response object), and next (a
function to call the next middleware function in the stack).

javascript
Copy code
// Custom middleware function
const myMiddleware = (req, res, next) => {
// Perform tasks here
console.log('Middleware executed');
next(); // Call the next middleware function
};

// Use custom middleware


app.use(myMiddleware);
104

Using Middleware in Routes:

You can apply middleware to specific routes or groups of routes using the app.use() or
router.use() methods.

javascript
Copy code
// Middleware function
const authenticate = (req, res, next) => {
// Check authentication
if (authenticated) {
next(); // Call the next middleware function
} else {
res.status(401).send('Unauthorized');
}
};

// Apply middleware to specific route


app.get('/profile', authenticate, (req, res) => {
// Handle request after authentication
});

// Apply middleware to group of routes


app.use('/admin', authenticate);
app.get('/admin/dashboard', (req, res) => {
// Handle dashboard request
});

Error Handling Middleware:

Express allows you to define error-handling middleware functions to catch and handle errors that
occur during the request-response cycle.

javascript
Copy code
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something went wrong!');
});

Third-party Middleware:

You can also use third-party middleware packages in your Express application to add additional
functionality. Some popular middleware packages include morgan for logging HTTP requests
and helmet for securing HTTP headers.

javascript
Copy code
const morgan = require('morgan');
const helmet = require('helmet');
105

// Use third-party middleware


app.use(morgan('combined'));
app.use(helmet());

Middleware in Express.js provides a flexible and powerful mechanism for handling requests and
responses in your application. By using built-in, custom, and third-party middleware, you can
add functionality, improve security, and enhance the performance of your Express.js
applications.

Using Template Engines


Template engines in Express.js enable dynamic generation of HTML content by combining data
with HTML templates. Some popular template engines used with Express.js include EJS, Pug
(formerly known as Jade), Handlebars, and Mustache. Here's how you can use template engines
in your Express.js application:

1. Installing a Template Engine:

First, you need to install the desired template engine using npm. For example, to install EJS, you
would run:

bash
Copy code
npm install ejs

Similarly, you can install other template engines like Pug (npm install pug), Handlebars (npm
install express-handlebars), or Mustache (npm install mustache-express).

2. Setting Up the Template Engine:

In your Express application, you need to set up the template engine by configuring the view
engine and views directory:

javascript
Copy code
const express = require('express');
const app = express();

// Set the view engine to EJS


app.set('view engine', 'ejs'); // For EJS

// Set the views directory


app.set('views', __dirname + '/views');

Replace 'ejs' with the name of the template engine you are using (e.g., 'pug', 'handlebars',
'mustache', etc.). Also, make sure to specify the directory where your template files are
located.
106

3. Creating a Template File:

Create a template file in the specified views directory. For example, if you are using EJS, create
a file named index.ejs:

html
Copy code
<!-- views/index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Express Template Engine Example</title>
</head>
<body>
<h1>Welcome to <%= title %></h1>
</body>
</html>

4. Rendering Templates:

In your route handler, render the template using res.render() and pass data as an object:

javascript
Copy code
app.get('/', (req, res) => {
res.render('index', { title: 'My Express App' });
});

5. Handling Dynamic Data:

You can pass dynamic data to your templates by interpolating variables or using control
structures provided by the template engine. For example, in EJS, you can use <%= %> to output
data and <% %> for control structures:

html
Copy code
<!-- views/user.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User Profile</title>
</head>
<body>
<h1>User Profile</h1>
<p>Name: <%= user.name %></p>
<p>Email: <%= user.email %></p>
</body>
</html>
107

Conclusion:

Using template engines in Express.js allows you to generate dynamic HTML content easily by
combining data with HTML templates. By following these steps, you can configure and use
template engines like EJS, Pug, Handlebars, or Mustache in your Express.js application to create
dynamic and interactive web pages.

Error Handling
Error handling in Express.js involves capturing errors that occur during the request-response
cycle and responding to them appropriately. Express provides built-in error handling
mechanisms and middleware functions to handle errors efficiently. Here's how you can handle
errors in an Express.js application:

Built-in Error Handling Middleware:

Express provides a default error-handling middleware function that catches errors thrown by
route handlers and middleware functions. You can define error-handling middleware using the
app.use() method with four parameters: err, req, res, and next.

javascript
Copy code
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Internal Server Error');
});

Custom Error Handling Middleware:

You can also define custom error-handling middleware functions to handle specific types of
errors. These middleware functions typically have three parameters: err, req, and res.

javascript
Copy code
app.use((err, req, res, next) => {
// Custom error handling logic
res.status(500).send('Internal Server Error');
});

Handling Errors in Route Handlers:

In route handlers, you can handle errors by passing them to the next() function or using try-
catch blocks.

javascript
Copy code
app.get('/example', (req, res, next) => {
try {
108

// Code that may throw an error


throw new Error('Something went wrong');
} catch (err) {
// Pass the error to the next middleware
next(err);
}
});

Async/Await Error Handling:

When using async/await syntax, you can handle errors using try-catch blocks or by passing
errors to the next() function.

javascript
Copy code
app.get('/example', async (req, res, next) => {
try {
const result = await someAsyncFunction();
res.json(result);
} catch (err) {
next(err);
}
});

Sending Errors to the Client:

When handling errors, you can send appropriate error responses to the client using the
res.status() and res.send() methods.

javascript
Copy code
app.get('/example', (req, res, next) => {
try {
// Code that may throw an error
throw new Error('Something went wrong');
} catch (err) {
res.status(500).send('Internal Server Error');
}
});

Conclusion:

Error handling in Express.js is essential for handling unexpected errors that may occur during the
request-response cycle. By using built-in error handling middleware, custom error handling
middleware, and handling errors in route handlers, you can ensure that your Express.js
application responds gracefully to errors and maintains robustness and reliability.

Error handling in Express.js refers to the process of capturing and responding to errors that
occur during the execution of an Express application. In Express, you can handle errors using
middleware functions, which are functions that have access to the request and response objects,
as well as the next middleware function in the application’s request-response cycle.
109

Express has built-in error handling middleware, such as the app.use(function(err, req, res, next)
{}) function, which can be used to handle errors that are thrown or passed to the next()
function. You can also create your own error-handling middleware functions to handle specific
errors in your application.
It’s important to note that in Express, the order of middleware functions is important. Error-
handling middleware should be placed at the end of the middleware stack, after all, other
middleware functions, so that it can catch any errors that are not handled by the other
middleware.
In addition, it’s important to handle errors properly and provide a proper error message to the
user, rather than returning stack traces to the client in production.
Reason for using error handling used in express.js:
 To prevent application crashes: Without error handling, unhandled errors can cause an
application to crash, leading to poor user experience and potential data loss. Error handling
allows you to capture and respond to errors, preventing them from causing a crash and
keeping the application running smoothly.
 To provide meaningful error messages: Error handling allows you to provide meaningful
and user-friendly error messages to your users, rather than leaving them with a blank
screen or a default error message. This can help to improve the overall user experience and
prevent confusion or frustration.
 To improve debugging: Error handling allows you to capture and log errors, making it
easier to debug your application and identify the root cause of any issues. This can save
time and effort when troubleshooting problems with your application.
 To comply with standards and regulations: Proper error handling is often a requirement
for compliance with security standards and regulations. By handling errors correctly, you
can ensure that your application meets these standards and regulations.
Ways to Perform Error Handling:
1. Middleware function: Express.js has built-in support for error-handling middleware, which
allows you to handle errors that occur during the execution of the application.
Syntax:
app.use(function(error, request, response, next) {
// Handle the error
response.status(500).send('Internal Server Error');
});
2. Try-Catch statements: you can use try-catch statements to handle errors
that occur within specific blocks of code. This ensures that any errors that
occur are caught and handled in a controlled manner.
Syntax:
app.get('/', function (req, res) {
try {
// Code that might throw an error
110

} catch (error) {
// Handle the error
res.status(500).send('Internal Server Error');
}
});
3. Error logging: You can set up error logging so that any errors that occur
during the execution of the application are logged to a file or a database for
later analysis.
Syntax:
app.get('/', function (req, res) {
try {
throw new Error('Something went wrong');
} catch (error) {
console.error(error);
}
});
Error codes: You can set up error codes for different types of errors that occur during the
execution of the application. This makes it easier to identify and handle specific errors.
 Error codes in Node.js are symbolic values that represent specific types of errors that can
occur during the execution of a program. Error codes are usually represented as strings and
are used to help identify and categorize different types of errors.
 For example, the Node.js fs module uses error codes such as ‘ENOENT’ (no such file or
directory) or ‘EACCES’ (permission denied) to represent specific types of file system
errors.
 When an error occurs in your Node.js application, you can access the error code by
checking the code property of the error object. For example, if you are using the fs.readFile
function, you can check the code property of the error object that is passed to the callback
to determine the type of error that has occurred.
Example:
const fs = require('fs');

fs.readFile('nonexistent-file.txt', (error, data) => {


if (error) {
console.error(error.code);
} else {
console.log(data.toString());
111

}
});
4. HTTP status codes: You can use HTTP status codes to indicate the type of error that
occurred. For example, a status code of 400 (Bad Request) can indicate a validation error,
while a status code of 500 (Internal Server Error) can indicate a server-side error.
Syntax:
const http = require('http');

const server = http.createServer((request, response) => {


response.statusCode = 200;
response.end('OK');
});

server.listen(8080);
 By using any of the above, you can handle errors in a controlled and efficient manner, and
ensure that your application is robust and stable.
Let’s see some basic examples and explanations for Error Handling in Express.js:
Example 1: Using a middleware function: You can use a middleware function to handle
errors that occur during the execution of an application. The middleware function should have
four arguments: error, request, response, and next.
Javascript
const express = require('express');
const app = express();

// Custom error handling middleware


const errorHandler = (err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something went wrong!');
};
app.use((req, res, next) => {
throw new Error('Something broke!');
});

// Use the custom error handling middleware


app.use(errorHandler);

app.listen(3000, () => {
console.log('App is listening on port 3000');
});
112

Steps to run the application: Write the below code in the terminal to run
the application:
node index.js
Output:

Explanation:
 In this example, we define a custom error-handling middleware function errorhandler that
logs the error stack and sends a response with a status code of 500 and the message
“Something went wrong!”.
 We then use the custom error handling middleware by adding the app.use(errorhandler)
after defining it.
 This error-handling middleware will catch any errors thrown in the previous middleware or
routes, and handle them according to the logic defined in the errorHandler function.
 The first line App is listening on port 3000 is logged when the Express app starts listening
on port 3000.
 If you make a request to the app, the custom middleware will throw an error, which will
then be caught by the error-handling middleware. The error stack trace will be logged to
the console, and the response sent to the client will have a status code of 500 and the
message “Something went wrong!”.
Example 2: Using the try-catch statement: You can use the try-catch statement to handle
errors that occur within a specific block of code.
Javascript
const express = require('express');
const app = express();
113

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


try {
// Some code that might throw an error
const data = someFunctionThatMightThrowError();
res.status(200).json(
{ message: 'Data retrieved successfully', data });
} catch (error) {
next(error);
}
});

// Custom error handling middleware


app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json(
{ message: 'Something went wrong!' });
});

app.listen(3000, () => {
console.log('App is listening on port 3000');
});

Explanation:
 In this example, we wrap the code that might throw an error in a try block.
If an error is thrown, it will be caught by the corresponding catch block,
which logs the error stack and sends a response with a status code of
500 and the message “Something went wrong!”.
 This approach allows for more fine-grained error handling, as the try-
catch statement can be used multiple times in different middleware
functions or routes.
Steps to run the application: Write the below code in the terminal to run
the application:
node index.js
Output:
114

Explanation:
 If you make a request to the app, the custom middleware will throw an error, which will
then be caught by the try-catch statement. The error stack trace will be logged to the
console, and the response sent to the client will have a status code of 500 and the message
“Something went wrong!”.
 Note that the [ERROR STACK TRACE] part of the output will vary depending on the
exact error that was thrown. It will contain details about the error, such as the error
message and the location in the code where the error was thrown.
 his output will be displayed if you make a request to the app and an error is thrown by the
custom middleware. The error stack trace will be logged to the console and the response
sent to the client will have a status code of 500 and the message “Something went wrong!”.
 This output will be displayed when the Express app starts listening on port 3000. No error
will be thrown if you do not make any requests to the app.
Example 3: Using the next() function: You can use the next() function to pass errors to
the next middleware function in the chain.
Javascript
const express = require('express');
const app = express();

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


// Some code that might throw an error
const data = someFunctionThatMightThrowError();
if (!data) {
return next(new Error('Error retrieving data'));
}
res.status(200).json(
{ message: 'Data retrieved successfully', data });
});

// Custom error handling middleware


app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json(
{ message: 'Something went wrong!' });
});

app.listen(3000, () => {
console.log('App is listening on port 3000');
});

Explanation:
 In this example, we have two middleware functions. The first middleware function throws
an error, and the second middleware function is used for error handling. If an error is
thrown in the first middleware function, the control flow is passed to the second
middleware function using the next() function. The error is then logged to the console and a
response with a status code of 500 and the message “Something went wrong!” is sent to the
client.
115

 This approach allows for error handling to be handled separately from the middleware
functions that perform the core functionality of the application.
Steps to run the application: Write the below code in the terminal to run the application:
node index.js
Here’s an example using curl:
 Open a terminal or command prompt.
 Navigate to the directory where the program is located.
 Start the application by running node app.js.
 In another terminal window, run the following command to make a request to the ‘/’
endpoint:
curl http://localhost:3000
Output:

 If you make a request to the app, the first middleware function will throw an error. The
error will be passed to the second middleware function using the next() function, where it
will be logged to the console and a response with a status code of 500 and the message
“Something went wrong!” will be sent to the client.
 Note that the [ERROR STACK TRACE] part of the output will vary depending on the
exact error that was thrown. It will contain details about the error, such as the error
message and the location in the code where the error was thrown.
Advantages of error handling used in express.js:
1. Improved user experience: Error handling allows you to provide meaningful and user-
friendly error messages to your users, rather than leaving them with a blank screen or a
default error message. This improves the overall user experience and can help to prevent
confusion or frustration.
2. Better debugging: When errors occur in an application, it can be difficult to identify the
cause without proper error handling. By capturing and logging errors, you can more easily
debug your application and identify the root cause of any issues.
116

3. Increased application stability: Error handling helps to prevent unhandled errors from
crashing your application, which can lead to increased stability and fewer downtime
incidents.
4. Better maintainability: Error handling makes it easier to maintain your application by
providing a clear and consistent way to handle errors. This can make it easier to identify
and fix bugs, as well as to add new features.
Disadvantages of error handling used in express.js:
1. Increased complexity: Error handling can add complexity to your application, as it
requires you to anticipate and plan for potential errors. This can make your code more
difficult to understand and maintain.
2. Overhead: Error handling can add overhead to your application, as it requires additional
logic and processing to capture and respond to errors. This can impact the performance of
your application.
3. False alarms: If error handling is not implemented correctly, it can lead to false alarms or
unnecessary error messages being displayed to users. This can create confusion and
damage user trust.
4. Security risks: Improper error handling can create security risks, as it can reveal sensitive
information or provide attackers with clues about potential vulnerabilities in your
application.

API Handling in express


Handling APIs in Express, a popular Node.js web application framework, involves creating
routes and middleware to handle incoming requests, interact with external APIs, and send
responses. Here's a basic guide to API handling in Express:
1. Setup Express Application: First, create an Express application by installing
Express and setting up a basic server file (app.js or server.js).
117

2. Define Routes: Define routes for your API endpoints. These routes will handle incoming
requests and execute the appropriate logic.

3. Handle Requests: Implement the logic to handle incoming requests inside route
handlers. This may involve interacting with external APIs, processing data, and sending
responses.

4. Middleware: Use middleware functions to perform tasks such as authentication,


request validation, error handling, etc.
118

5. Error Handling: Implement error handling middleware to catch and handle errors that
occur during request processing.

6. Testing: Test your API endpoints using tools like Postman or by writing automated tests using
libraries like Jest or Mocha.
7. Documentation: Document your API endpoints, request/response formats, and any
authentication requirements for developers who will be consuming your API.

By following these steps, you can effectively handle APIs in Express and build robust web applications
that interact with external services.

Debugging
In express, there is a module present called DEBUG that gives log information. It tells about
middleware functions, application mode, their status, and also about the requests and responses
made to the server.
To use this module while running the express app, set the DEBUG environment variable to
express:*
$ DEBUG=express:* node index.js
119

The output generated on running the command is shown below:

These logs help in finding any bug in the program and tell which part of the program is
creating the problem.
Sometimes you may not want the entire log but only the logs from a specific part of the
program, for example, only the logs of the router or application, then you can do so by setting
the DEBUG environment variable as express:* and then running the command:
$ DEBUG=express:router node index.js
This gives logs only of the router part. Similarly, you can do for application as well.
$ DEBUG=express:application node index.js
If you want for both of them you can do so by running the code:
DEBUG = express:application,express:router node index.js
In the example above, whose image is shown we have set DEBUG to express:* . Here, *
indicates that all the areas are included and all the logs will be shown.
For windows
The above-shown method is for Linux. For Windows, you need to edit the package.json file. In
the package.json file set your start command as shown and run npm start.
"scripts": {
"start": "set DEBUG=express:* & node index.js"
}
You can also use more than one option at a time to debug them together by separating them by
commas. Example:
$ DEBUG=mail,express:* node index.js
Debug environment variables
120

Suppose you want the logs to be visible in a different manner. Suppose you don’t want the
colors to appear or you want to see some hidden information, you can do that by setting
environment variables. Some of these variables are:
1. DEBUG: Select the namespaces for which you want to see the logs.
2. DEBUG_COLORS: By setting this to either 1 or 0 you can decide whether the logs that
will be visible will be in different colors or the same white color. If you set
DEBUG_COLORS to 0 the logs will appear in white plain text. By default, it is set to 0.
3. DEBUG_HIDE_DATE: This can hide the date from debug output.
4. DEBUG_SHOW_HIDDEN: This shows hidden properties on inspected objects.
Example: You don’t want the log output to be displayed in different colors, set
DEBUG_COLORS =1
$ DEBUG=express:* DEBUG_COLORS=0 node gfg1.js
Its output is shown below:

Debugging in Express involves identifying and resolving issues in your application code,
middleware, routes, and configurations. Here are some debugging techniques you can use in
Express:

1. Console Logging: One of the simplest and most effective ways to debug Express
applications is by using console.log() statements. You can place these statements
throughout your code to print variables, object properties, and messages to the console,
helping you understand the flow of execution and the values of variables at different
points.

javascript
Copy code
app.get('/route', (req, res) => {
console.log('Received GET request');
// Other logic
});

2. Debug Middleware: Express provides a built-in middleware called express-debug,


which can be used to debug your routes and middleware stack. It logs information about
each request and the corresponding middleware that is executed.

javascript
Copy code
const expressDebug = require('express-debug');
121

// Enable debug middleware


app.use(expressDebug);

3. Error Handling Middleware: Implement custom error handling middleware to catch


and handle errors that occur during request processing. This middleware should be placed
at the end of your middleware stack to catch errors from downstream middleware and
route handlers.

javascript
Copy code
app.use((err, req, res, next) => {
console.error('Error:', err);
res.status(500).send('Internal Server Error');
});

4. Logging Middleware: Use logging middleware like morgan to log HTTP requests and
responses. This can help you track the flow of requests through your application and
identify any issues with request handling or response generation.

javascript
Copy code
const morgan = require('morgan');

// Log HTTP requests


app.use(morgan('dev'));

5. Debugger: You can use Node.js's built-in debugger or a debugger like VS Code's
debugger to set breakpoints in your code and inspect variables, call stack, and execution
flow during runtime.
6. Error Stack Trace: When an error occurs, pay attention to the error stack trace printed
in the console. It provides valuable information about the location and cause of the error,
helping you identify the source of the problem.
7. Environment Variables: Use environment variables to control the behavior of your
application in different environments (e.g., development, staging, production). This
allows you to isolate and debug issues specific to a particular environment.

javascript
Copy code
if (process.env.NODE_ENV === 'development') {
// Enable additional debugging features
}

8. Testing: Write unit tests and integration tests for your Express application using testing
frameworks like Mocha, Chai, or Jest. Automated tests help identify and fix issues early
in the development process.

By using these debugging techniques, you can effectively identify and resolve issues in your
Express application, ensuring that it runs smoothly and handles requests correctly.
122

Developing template engines for Express


Use the app.engine(ext, callback) method to create your own template engine. ext refers to the file
extension, and callback is the template engine function, which accepts the following items as parameters: the
location of the file, the options object, and the callback function.

The following code is an example of implementing a very simple template engine for rendering .ntl files.

const fs = require('fs') // this engine requires the fs module


app.engine('ntl', (filePath, options, callback) => { // define the template engine
fs.readFile(filePath, (err, content) => {
if (err) return callback(err)
// this is an extremely simple template engine
const rendered = content.toString()
.replace('#title#', `<title>${options.title}</title>`)
.replace('#message#', `<h1>${options.message}</h1>`)
return callback(null, rendered)
})
})
app.set('views', './views') // specify the views directory
app.set('view engine', 'ntl') // register the template engine

Your app will now be able to render .ntl files. Create a file named index.ntl in the views directory with the
following content.

#title#
#message#

Then, create the following route in your app.

app.get('/', (req, res) => {


res.render('index', { title: 'Hey', message: 'Hello there!' })
})

Developing a template engine specifically for Express involves integrating your template engine
with Express's view rendering system. Express supports multiple template engines out of the
box, such as Pug (formerly Jade), EJS, Handlebars, and more. However, if you want to develop
your own template engine for Express, you can follow these general steps:
123

1. Understand Express View Rendering: Understand how Express renders views. Express
uses the res.render() function to render views. It looks for templates in a specified
directory and uses a template engine to render them.
2. Choose a Syntax: Decide on the syntax for your template engine. It should be easy to
read and write for developers. Consider common features like variables, conditionals,
loops, and partials.
3. Implement Template Engine: Implement your template engine logic. This involves
parsing the template files and rendering them into HTML. You'll need to create a
function that takes the template file path, data, and callback, and returns the rendered
HTML.
4. Integrate with Express: Integrate your template engine with Express. You'll need to
register your engine with Express using the app.engine() method, specify the file
extension associated with your engine, and set the directory where your templates are
located using app.set('views', 'views-directory').
5. Render Views: Use res.render() in your route handlers to render views using your
template engine. Pass data to your views as needed.

Here's a basic example of how you might implement a custom template engine for Express:

javascript
Copy code
// Custom template engine for Express
const fs = require('fs');

function customEngine(filePath, options, callback) {


fs.readFile(filePath, (err, content) => {
if (err) return callback(new Error(err));
// Implement your template rendering logic here
const rendered = content.toString().replace('{{name}}', options.name
|| '');
return callback(null, rendered);
});
}

// Register the engine with Express


app.engine('custom', customEngine);
app.set('views', './views'); // Directory where your templates are located
app.set('view engine', 'custom'); // File extension associated with your
engine

// Example route
app.get('/', (req, res) => {
res.render('index', { name: 'John' }); // Renders index.custom
});

In this example, the customEngine function reads the template file, replaces placeholders with
data from the options object, and invokes the callback with the rendered HTML. The engine is
registered with Express using app.engine() and associated with the .custom file extension.

Keep in mind that this is a simplified example. Depending on your requirements, you may need
to implement additional features such as layout support, partials, caching, and error handling.
124

NodeJS Process Managers

Node.js process manager is a tool, which provides an ability to control application lifecycle, monitor
the running services and facilitate common system admin tasks to maintain your project operability.
The platform provides three pre-configured process managers by default, which can be selected in
the following ways:
 by selecting the appropriate tag during the environment creation or container redeploy

 by editing the PROCESS_MANAGER Docker environment variable in the already created container(s)
with the forever, npm, or pm2 value (restart is needed to apply the new options)

Below, we’ll consider each of the available managers to help you select one:
 Process Manager (npm)
 PM2
 Forever

Process Manager (npm)


Alongside package management, the NPM provides the ability to start the application. The “npm
start” (which is the “npm run start” alias) is performed if NPM is chosen as a value for
125

the PROCESS_MANAGER variable on the NodeJS container. As a result, the script defined in “start”
of package.json is launched.
Refer to the official documentation for additional information.

PM2
PM2 provides a huge variety of application management features, including the launched NodeJS
processes monitoring. You can get acquainted with the list of commands for pm2, which can be
executed directly via SSH.
For example, after Node.js server creation, you can list the running processes with the following
command:
1 pm2 list

As you can see it shows the default draw-game application is running.


Next, you can remove this app with the pm2 delete command and deploy your own project (e.g., the
default Hello Word application):

Also, PM2 provides users the ability to create the configuration files where all the run options are
listed, which is useful for microservice-based applications deployment, as several apps can be
described in a single file. The appropriate config file reference can be found by following the
provided link (e.g. the default ecosystem.config.js file is used to launch the server.js application file
as the “draw game” application).

Forever
The forever process manager is the simple CLI tool, which allows to make your NodeJS processes run
continuously. It permanently keeps a child process (such as your project on the Node.js web server)
and automatically restart it upon failure.
Run the next command to get the main information on the forever manager usage, actions, usage,
etc.:
1 forever --help
126

Also, using forever you can specify the application options in a JSON file. For example, for the default
Draw game (available after Node.js server installation), this /home/jelastic/ROOT/forever.json file
looks like:

1 {
2 "uid": "app1",
3 "append": true,
4 "watch": true,
5 "script": "server.js",
6 "sourceDir": "/home/jelastic/ROOT"
7 }

where:
 uid - sets unique name for your app
 append - selects if logs should be supplemented (true) or overwritten (false)
 watch - allows enabling or disabling automatic restart of a child process upon the appropriate
application code changes; set to “false”, if you want to avoid unexpected restart after deployment
from VCS (including auto-deploy)
 script - defines a name of the executable .js file
 sourceDir - provides an absolute path to the specified script

Security & Deployment in express


Securing and deploying Express.js applications involves a multi-faceted approach to ensure your
application is both robust and protected from potential threats. Here's a comprehensive guide on
how to handle security and deployment in Express.js:

Security Measures:

1. Input Validation: Always validate user input to prevent injection attacks like SQL
injection, XSS (Cross-Site Scripting), and other forms of attacks. You can use libraries
like express-validator for this purpose.
2. Authentication: Implement user authentication using robust techniques like JWT (JSON
Web Tokens), OAuth, or Passport.js. Ensure passwords are hashed securely using bcrypt
or similar libraries.
127

3. Authorization: After authentication, authorize users to access specific resources or


perform certain actions within your application. Implement role-based access control
(RBAC) or similar mechanisms.
4. HTTPS: Always use HTTPS to encrypt data transmitted between the client and server.
You can achieve this by configuring SSL/TLS certificates on your server.
5. Helmet: Use the Helmet middleware to set HTTP headers securely and prevent common
vulnerabilities like XSS, CSRF (Cross-Site Request Forgery), and clickjacking.
6. Rate Limiting: Implement rate limiting to prevent brute force attacks and DoS (Denial of
Service) attacks. You can use libraries like express-rate-limit for this purpose.
7. Content Security Policy (CSP): Implement CSP to mitigate XSS attacks by specifying
the sources from which content can be loaded on your web application.
8. Session Management: If you're using sessions, ensure they are managed securely. Use
libraries like express-session and store session data securely, preferably using a
database.
9. Error Handling: Implement proper error handling to prevent leaking sensitive
information to attackers. Use middleware like errorhandler to handle errors gracefully.

Deployment:

1. Choose a Hosting Provider: Select a hosting provider that supports Node.js


applications. Popular choices include AWS, Heroku, DigitalOcean, and Azure.
2. Setup Environment Variables: Store sensitive information like database credentials,
API keys, and secret keys as environment variables. This prevents them from being
exposed in your codebase.
3. Configure Nginx or Apache: Use a reverse proxy like Nginx or Apache to forward
requests to your Express.js application. This adds an extra layer of security and improves
performance.
4. Set up Logging: Configure logging for your application to monitor errors, access logs,
and application behavior. Tools like Winston or Morgan can help with this.
5. Continuous Integration/Continuous Deployment (CI/CD): Set up CI/CD pipelines to
automate the deployment process. Services like GitHub Actions, CircleCI, or Jenkins can
help you achieve this.
6. Monitoring and Alerting: Implement monitoring and alerting for your application to
detect and respond to issues promptly. Tools like Prometheus, Grafana, or New Relic can
help with this.
7. Backup and Recovery: Regularly backup your application data and ensure you have a
recovery plan in place in case of failures or data loss.
8. Security Updates: Stay

You might also like