Friday 8 March 2024

Nodejs Drag & Drop Multiple File Upload using Multer


Introduction:


In today's digital world, file uploading is a common functionality for web applications. Node.js, with its asynchronous and event-driven architecture, offers an excellent platform for handling file uploads efficiently. Multer, a middleware for Express.js, simplifies the process of handling multipart/form-data, making it perfect for handling multiple file uploads.

In this tutorial, we will explore how to implement drag and drop multiple file uploads using Node.js and Multer, ensuring the content is optimized for search engines.


Node.js Drag & Drop Multiple File Upload using Multer


Table of Contents:


  1. Setting up the Project Environment
  2. Installing Dependencies
  3. Configuring Multer Middleware
  4. Creating the Frontend Interface
  5. Implementing Drag and Drop Functionality
  6. Handling File Uploads on the Server
  7. Run Application
  8. Conclusion

1. Setting up the Project Environment:


Before diving into the code, let's ensure we have Node.js installed on our system. If not, download and install it from the official Node.js website.

	
	mkdir drag-drop
	cd drag-drop
	

2. Installing Dependencies:


Initialize a new Node.js project and install the required dependencies using npm:

	
	npm init -y
	npm install express multer
	

3. Configuring Multer Middleware:


Create an Express.js server under server.js and configure Multer middleware to handle file uploads:

server.js
	
	const express = require('express');
	const multer = require('multer');
	const path = require('path');
	const app = express();
	const PORT = 3000;
	app.use(express.static(__dirname));

	// Set up Multer storage
	const storage = multer.diskStorage({
		destination : function(request, file, callback) {
			callback(null, 'uploads/');
		},
		filename : function(request, file, callback) {
			callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
		}
	});

	// Initialize Multer upload
	const upload = multer({storage : storage});
	
	app.get('/upload', async (request, response) => {
		response.sendFile(__dirname + '/upload.html');
	});
	
	app.listen(PORT, () => {
		console.log(`Server is running on port ${PORT}`);
	});
	

4. Creating the Frontend Interface:


Design a simple HTML page with name upload.html file with drag and drop functionality for uploading files:

upload.html
	
	<!doctype html>
	<html lang="en">
		<head>
			<!-- Required meta tags -->
			<meta charset="utf-8">
			<meta name="viewport" content="width=device-width, initial-scale=1">

			<!-- Bootstrap CSS -->
			<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

			<title>Drag and Drop File Upload</title>
		</head>
		<body>
			
			<div class="container">
				<h1 class="text-center mb-5 mt-5"><b>Drag and Drop File Upload in Node.js</b></h1>

				<div id="drop_zone">
					<p>Drag and drop files here</p>
				</div>
				<br />
				<div class="card mb-5">
					<div class="card-header">
						<div class="row">
							<div class="col col-6">Uploaded File</div>
							<div class="col col-6"></div>
						</div>
					</div>
					<div id="uploadedImage" class="card-body">

					</div>
				</div>
			</div>
			<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"></script>
		</body>
	</html>

	<style>
	#drop_zone {
			width: 100%;
			min-height: 200px;
			border: 2px dashed #ccc;
			border-radius: 10px;
			padding: 20px;
			box-sizing: border-box;
			display: flex;
			justify-content: center;
			align-items: center;
			flex-direction: column;
		}
		#drop_zone.hover {
			background-color: #f0f0f0;
		}
	</style>
	

5. Implementing Drag and Drop Functionality:


Write JavaScript code in uplode.html file to handle drag and drop functionality:

upload.html
	
	<script>

	var dropZone = document.getElementById('drop_zone');

	dropZone.addEventListener('dragover', (event) => {
		event.preventDefault();
		dropZone.classList.add('hover');
	});

	dropZone.addEventListener('dragleave', (event) => {
		event.preventDefault();
		dropZone.classList.remove('hover');
	});

	dropZone.addEventListener('drop', (event) => {
		event.preventDefault();
		dropZone.classList.remove('hover');
		var files = event.dataTransfer.files;
		handlesFiles(files);
	});

	function handlesFiles(files){
		for(var count = 0; count < files.length; count++){
			var file = files[count];
			uploadFile(file);
		}
	}

	function uploadFile(file){
		var formData = new FormData();
		formData.append('file', file);
		fetch('/upload', {
			method : 'POST',
			body : formData
		})
		.then(response => response.json())
		.then(data => {
			const gallery = document.getElementById('uploadedImage');
			let html = `<img src="/uploads/${data.filename}" class="img-thumbnail" />`;
			gallery.innerHTML = gallery.innerHTML + html;
		});
	}

	</script>
	

6. Handling File Uploads on the Server:


Now in server.js, we have to handle file uploads on the server-side using Express.js:

server.js
	
	app.post('/upload', upload.single('file'), (request, response) => {
		response.json({ filename : request.file.filename });
	});
	

7. Run Application


After writing all above code, for run this node application in browser, we have to start node server, so we have goes to terminal window, and there we have to run node server.js command which will start node development server.

And at browser, we have to open http://localhost:3000 url, then it will open this Node Drag and Drop application in browser.

8. Conclusion:


Congratulations! You've successfully implemented drag and drop multiple file uploads using Node.js and Multer. This tutorial covered the setup of the project environment, installation of dependencies, configuration of Multer middleware, creation of the frontend interface, implementation of drag and drop functionality, handling file uploads on the server, and displaying upload progress.

Complete Source Code


server.js
	
	const express = require('express');
	const multer = require('multer');
	const path = require('path');
	const app = express();
	const PORT = 3000;
	app.use(express.static(__dirname));

	// Set up Multer storage
	const storage = multer.diskStorage({
		destination : function(request, file, callback) {
			callback(null, 'uploads/');
		},
		filename : function(request, file, callback) {
			callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
		}
	});

	// Initialize Multer upload
	const upload = multer({storage : storage});

	app.get('/upload', async (request, response) => {
		response.sendFile(__dirname + '/upload.html');
	});

	app.post('/upload', upload.single('file'), (request, response) => {
		response.json({ filename : request.file.filename });
	});

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

upload.html
	
	<!doctype html>
	<html lang="en">
		<head>
			<!-- Required meta tags -->
			<meta charset="utf-8">
			<meta name="viewport" content="width=device-width, initial-scale=1">

			<!-- Bootstrap CSS -->
			<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

			<title>Drag and Drop File Upload</title>
		</head>
		<body>
			
			<div class="container">
				<h1 class="text-center mb-5 mt-5"><b>Drag and Drop File Upload in Node.js</b></h1>

				<div id="drop_zone">
					<p>Drag and drop files here</p>
				</div>
				<br />
				<div class="card mb-5">
					<div class="card-header">
						<div class="row">
							<div class="col col-6">Uploaded File</div>
							<div class="col col-6"></div>
						</div>
					</div>
					<div id="uploadedImage" class="card-body">

					</div>
				</div>
			</div>
			<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"></script>
		</body>
	</html>

	<style>
	#drop_zone {
			width: 100%;
			min-height: 200px;
			border: 2px dashed #ccc;
			border-radius: 10px;
			padding: 20px;
			box-sizing: border-box;
			display: flex;
			justify-content: center;
			align-items: center;
			flex-direction: column;
		}
		#drop_zone.hover {
			background-color: #f0f0f0;
		}
	</style>

	<script>

	var dropZone = document.getElementById('drop_zone');

	dropZone.addEventListener('dragover', (event) => {
		event.preventDefault();
		dropZone.classList.add('hover');
	});

	dropZone.addEventListener('dragleave', (event) => {
		event.preventDefault();
		dropZone.classList.remove('hover');
	});

	dropZone.addEventListener('drop', (event) => {
		event.preventDefault();
		dropZone.classList.remove('hover');
		var files = event.dataTransfer.files;
		handlesFiles(files);
	});

	function handlesFiles(files){
		for(var count = 0; count < files.length; count++){
			var file = files[count];
			uploadFile(file);
		}
	}

	function uploadFile(file){
		var formData = new FormData();
		formData.append('file', file);
		fetch('/upload', {
			method : 'POST',
			body : formData
		})
		.then(response => response.json())
		.then(data => {
			const gallery = document.getElementById('uploadedImage');
			let html = `<img src="/uploads/${data.filename}" class="img-thumbnail" />`;
			gallery.innerHTML = gallery.innerHTML + html;
		});
	}

	</script>
	

Wednesday 28 February 2024

Node.js CRUD Application with Mongo DB Database

Node.js CRUD Application with Mongo DB Database

Introduction:


In this tutorial, we'll walk through the process of building a CRUD (Create, Read, Update, Delete) application using Node.js and MongoDB. CRUD applications are fundamental in web development as they facilitate the basic operations for managing data in a database. We'll leverage the power of Node.js for the backend logic and MongoDB as the database to store our data. By the end of this tutorial, you'll have a solid understanding of how to create a fully functional CRUD application.





Prerequisites:


Before we begin, make sure you have the following installed on your system:

  1. Node.js
  2. MongoDB

Step 1: Setting Up Your Project:


Start by creating a new directory for your project and navigate into it using your terminal or command prompt.

	
	mkdir node-crud-app
	cd node-crud-app
	

Initialize a new Node.js project using npm.

	
	npm init -y
	

Step 2: Installing Dependencies:


Next, we need to install the necessary dependencies for our project. We'll use Express.js as our web framework and Mongoose as the MongoDB ODM (Object Data Modeling) library.

	
	npm install express mongoose body-parser
	

Step 3: Setting Up MongoDB:



In this tutorial, we have use Cloud Mongo DB Database. So in below video tutorial, you can find step by step guide for how to create Mongo DB Schema or Database in the Cloud.

Step 4: Creating the Server:


Create a file named server.js in your project directory and set up a basic Express server.

server.js
	
	const express = require('express');
	const bodyParser = require('body-parser');
	const mongoose = require('mongoose');

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

	app.use(bodyParser.json());

	app.use(express.static(__dirname));
	

Step 5: Connecting to MongoDB:


Add the code to connect your Node.js application to MongoDB using Mongoose.

server.js
	
	const express = require('express');
	const bodyParser = require('body-parser');
	const mongoose = require('mongoose');

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

	app.use(bodyParser.json());

	app.use(express.static(__dirname));

	mongoose.connect('mongodb+srv://johnsmith174:xxxxx@cluster0.8dbkdwt.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0');

	const connect = mongoose.connection;

	connect.on('error', console.error.bind(console, 'MongoDB connection error:'));

	connect.once('open', () => {
		console.log('Connected to MongoDB');
	});
	

Step 6: Creating Models:


Define a schema for your MongoDB documents and create models using Mongoose.

server.js
	
		const userSchema = new mongoose.Schema({
			name : String,
			email : String,
			age : Number
		});

		const User = mongoose.model('User', userSchema);
	

Step 7: Implementing CRUD Operations:


Now, let's implement the CRUD operations for our application - Create, Read, Update, and Delete.

Create Operation (POST):


The create operation involves adding new items to our database. We'll define a route to handle incoming POST requests to create new items.

So first we have to create one get route in server.js file for load HTML file in the browser.

server.js
	
		app.get('/', async (request, response) => {
			response.sendFile(__dirname + '/user.html');
		});
	

Next we have to create one user.html file and under this file, we have to create one button and when we have click on button then bootstrap modal must be pop up on web page and under modal we will make user form for insert data into MongoDB.

user.html
	
<!doctype html>
<html lang="en">
    <head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <!-- Bootstrap CSS -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

        <title>Build a CRUD App with Node.js and MongoDB</title>
    </head>
    <body>
        
        <div class="container">
            <h1 class="text-center mb-5 mt-5 text-danger"><b>Build a CRUD App with Node.js and MongoDB - Insert Data into MongoDB Database - 2</b></h1>
            <div class="card mb-5">
                <div class="card-header">
                    <div class="row">
                        <div class="col col-6">Sample Data</div>
                        <div class="col col-6">
                            <button type="button" class="btn btn-primary btn-sm float-end" onclick="makeModal('Add User', 'Add', 'insertData')">Add</button>
                        </div>
                    </div>
                </div>
                <div class="card-body">
                    <div class="table-responsive">
                        
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>
<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"></script>
<div id="modalArea"></div>

<script>

var userModalElement;

function makeModal(title, button_value, callback)
{
    let html = `
    <div class="modal" tabindex="-1" id="userModal">
        <div class="modal-dialog">
            <div class="modal-content">
                <form id="userform">
                    <div class="modal-header">
                        <h5 class="modal-title">${title}</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <div class="mb-3">
                            <label>Name</label>
                            <input type="text" name="name" id="name" class="form-control" />
                        </div>
                        <div class="mb-3">
                            <label>Email</label>
                            <input type="email" name="email" id="email" class="form-control" />
                        </div>
                        <div class="mb-3">
                            <label>Age</label>
                            <input type="number" name="age" id="age" class="form-control" />
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                        <button type="button" class="btn btn-primary" onclick="${callback}()">${button_value}</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    `;

    document.querySelector('#modalArea').innerHTML = html;

    userModalElement = new bootstrap.Modal(document.getElementById('userModal'));

    userModalElement.show();
}

function insertData()
{
    let formElement = document.getElementById('userform');
    const formData = new FormData(formElement);
    // Convert formData to JSON
    const jsonData = {};
    formData.forEach((value, key) => {
        jsonData[key] = value;
    });
    // Make a POST request using Fetch API
    fetch('/users', {
        method : 'POST',
        body : JSON.stringify(jsonData),
        headers : {
            'Content-Type': 'application/json'
        }
    })
    .then(response => {
        return response.json();
    })
    .then(data => {
        userModalElement.hide();
        getData();
    });
}

</script>


Next we have goes to server.js file and here we have to create one POST route for handle form data for insert data into MongoDB.

server.js
	
	app.post('/users', async (request, response) => {
		const user = new User({
			name : request.body.name,
			email : request.body.email,
			age : request.body.age
		});
		const newItem = await user.save();
		response.status(201).json({scuccess:true});
	});
	

Read Operation (GET):


So for read data operation, first we have goest to user.html file and here we have to create one HTML table and then after we have goes to JavaScript code part, and here we have to create one getData() function which will send fetch data request to node application route and display on web page, and call this function into insertData() function, so when new data has been inserted then it will display last inserted data on web also.

user.html
	
	<!doctype html>
	<html lang="en">
		<head>
			<!-- Required meta tags -->
			<meta charset="utf-8">
			<meta name="viewport" content="width=device-width, initial-scale=1">

			<!-- Bootstrap CSS -->
			<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

			<title>Build a CRUD App with Node.js and MongoDB</title>
		</head>
		<body>
			
			<div class="container">
				<h1 class="text-center mb-5 mt-5 text-danger"><b>Build a CRUD App with Node.js and MongoDB - Insert Data into MongoDB Database - 2</b></h1>
				<div class="card mb-5">
					<div class="card-header">
						<div class="row">
							<div class="col col-6">Sample Data</div>
							<div class="col col-6">
								<button type="button" class="btn btn-primary btn-sm float-end" onclick="makeModal('Add User', 'Add', 'insertData')">Add</button>
							</div>
						</div>
					</div>
					<div class="card-body">
						<div class="table-responsive">
							<table class="table table-bordered table-striped">
								<thead>
									<tr>
										<th>Name</th>
										<th>Email</th>
										<th>Age</th>
										<th>Action</th>
									</tr>
								</thead>
								<tbody id="dataArea"></tbody>
							</table>
						</div>
					</div>
				</div>
			</div>
		</body>
	</html>
	<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"></script>
	<div id="modalArea"></div>

	<script>

	var userModalElement;

	function makeModal(title, button_value, callback)
	{
		let html = `
		<div class="modal" tabindex="-1" id="userModal">
			<div class="modal-dialog">
				<div class="modal-content">
					<form id="userform">
						<div class="modal-header">
							<h5 class="modal-title">${title}</h5>
							<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
						</div>
						<div class="modal-body">
							<div class="mb-3">
								<label>Name</label>
								<input type="text" name="name" id="name" class="form-control" />
							</div>
							<div class="mb-3">
								<label>Email</label>
								<input type="email" name="email" id="email" class="form-control" />
							</div>
							<div class="mb-3">
								<label>Age</label>
								<input type="number" name="age" id="age" class="form-control" />
							</div>
						</div>
						<div class="modal-footer">
							<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
							<button type="button" class="btn btn-primary" onclick="${callback}()">${button_value}</button>
						</div>
					</form>
				</div>
			</div>
		</div>
		`;

		document.querySelector('#modalArea').innerHTML = html;

		userModalElement = new bootstrap.Modal(document.getElementById('userModal'));

		userModalElement.show();
	}

	function insertData()
	{
		let formElement = document.getElementById('userform');
		const formData = new FormData(formElement);
		// Convert formData to JSON
		const jsonData = {};
		formData.forEach((value, key) => {
			jsonData[key] = value;
		});
		// Make a POST request using Fetch API
		fetch('/users', {
			method : 'POST',
			body : JSON.stringify(jsonData),
			headers : {
				'Content-Type': 'application/json'
			}
		})
		.then(response => {
			return response.json();
		})
		.then(data => {
			userModalElement.hide();
			getData();
		});
	}

	getData();

	function getData(){
		fetch('/users')
		.then(response => {
			return response.json();
		})
		.then(data => {
			let html = '';
			if(data.length > 0){
				data.map((row) => {
					html += `
					<tr>
						<td>${row.name}</td>
						<td>${row.email}</td>
						<td>${row.age}</td>
						<td></td>
					</tr>
					`;
				});
			} else {
				html = '<tr><td colspan="4" class="text-center">No Data Found</td></tr>';
			}
			document.getElementById('dataArea').innerHTML = html;
		});
	}

	</script>
	

Next The read operation involves fetching existing items from the database. We'll define a route to handle incoming GET requests to retrieve items in server.js file.

server.js
	
		app.get('/users', async (request, response) => {
			const users = await User.find();
			response.status(200).json(users);
		});
	

Update Operation (PUT/PATCH):


For Update MongoDB data, first we have goes to user.html file and under this file, we have to create edit button in each of data, which will send get request for fetch single user data from MongoDB data and then after we have to create one editData() function which will be called when we have submit form data. So it will send PUT request to node crud application.

user.html
	
	<!doctype html>
	<html lang="en">
		<head>
			<!-- Required meta tags -->
			<meta charset="utf-8">
			<meta name="viewport" content="width=device-width, initial-scale=1">

			<!-- Bootstrap CSS -->
			<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

			<title>Build a CRUD App with Node.js and MongoDB</title>
		</head>
		<body>
			
			<div class="container">
				<h1 class="text-center mb-5 mt-5 text-danger"><b>Build a CRUD App with Node.js and MongoDB - Delete Data from MongoDB Database - 5</b></h1>
				<div class="card mb-5">
					<div class="card-header">
						<div class="row">
							<div class="col col-6">Sample Data</div>
							<div class="col col-6">
								<button type="button" class="btn btn-primary btn-sm float-end" onclick="makeModal('Add User', 'Add', 'insertData')">Add</button>
							</div>
						</div>
					</div>
					<div class="card-body">
						<div class="table-responsive">
							<table class="table table-bordered table-striped">
								<thead>
									<tr>
										<th>Name</th>
										<th>Email</th>
										<th>Age</th>
										<th>Action</th>
									</tr>
								</thead>
								<tbody id="dataArea"></tbody>
							</table>
						</div>
					</div>
				</div>
			</div>
		</body>
	</html>
	<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"></script>
	<div id="modalArea"></div>

	<script>

	var userModalElement;

	function makeModal(title, button_value, callback)
	{
		let html = `
		<div class="modal" tabindex="-1" id="userModal">
			<div class="modal-dialog">
				<div class="modal-content">
					<form id="userform">
						<div class="modal-header">
							<h5 class="modal-title">${title}</h5>
							<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
						</div>
						<div class="modal-body">
							<div class="mb-3">
								<label>Name</label>
								<input type="text" name="name" id="name" class="form-control" />
							</div>
							<div class="mb-3">
								<label>Email</label>
								<input type="email" name="email" id="email" class="form-control" />
							</div>
							<div class="mb-3">
								<label>Age</label>
								<input type="number" name="age" id="age" class="form-control" />
							</div>
						</div>
						<div class="modal-footer">
							<input type="hidden" name="user_id" id="user_id" />
							<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
							<button type="button" class="btn btn-primary" onclick="${callback}()">${button_value}</button>
						</div>
					</form>
				</div>
			</div>
		</div>
		`;

		document.querySelector('#modalArea').innerHTML = html;

		userModalElement = new bootstrap.Modal(document.getElementById('userModal'));

		userModalElement.show();
	}

	function insertData()
	{
		let formElement = document.getElementById('userform');
		const formData = new FormData(formElement);
		// Convert formData to JSON
		const jsonData = {};
		formData.forEach((value, key) => {
			jsonData[key] = value;
		});
		// Make a POST request using Fetch API
		fetch('/users', {
			method : 'POST',
			body : JSON.stringify(jsonData),
			headers : {
				'Content-Type': 'application/json'
			}
		})
		.then(response => {
			return response.json();
		})
		.then(data => {
			userModalElement.hide();
			getData();
		});
	}

	getData();

	function getData(){
		fetch('/users')
		.then(response => {
			return response.json();
		})
		.then(data => {
			let html = '';
			if(data.length > 0){
				data.map((row) => {
					html += `
					<tr>
						<td>${row.name}</td>
						<td>${row.email}</td>
						<td>${row.age}</td>
						<td>
							<button type="button" class="btn btn-warning btn-sm" onclick="fetchSingleData('${row._id}')">Edit</button>
						</td>
					</tr>
					`;
				});
			} else {
				html = '<tr><td colspan="4" class="text-center">No Data Found</td></tr>';
			}
			document.getElementById('dataArea').innerHTML = html;
		});
	}

	function fetchSingleData(id){
		fetch(`/users/${id}`)
		.then(response => {
			return response.json();
		})
		.then(data => {
			makeModal('Edit User', 'Edit', 'editData');
			document.getElementById('name').value = data.name;
			document.getElementById('email').value = data.email;
			document.getElementById('age').value = data.age;
			document.getElementById('user_id').value = data._id;
		});
	}

	function editData(){
		let formElement = document.getElementById('userform');
		const formData = new FormData(formElement);
		let jsonData = {};
		formData.forEach((value, key) => { 
			jsonData[key] = value;
		});
		const userId = document.getElementById('user_id').value;
		fetch(`/users/${userId}`, {
			method : 'PUT',
			body : JSON.stringify(jsonData),
			headers : {
				'Content-Type': 'application/json'
			}
		})
		.then(response => {
			return response.json();
		})
		.then(data => {
			userModalElement.hide();
			getData();
		});
	}

	</script>
	

The update operation involves modifying existing items in the database. We'll define a route to handle incoming PUT or PATCH requests to update items.

server.js
	
	app.get('/users/:id', async (request, response) => {
		const user = await User.findById(request.params.id);
		response.status(200).json(user);
	});

	app.put('/users/:id', async (request, response) => {
		const userId = request.params.id;
		// Fetch the user from the database
		const user = await User.findById(userId);
		user.name = request.body.name;
		user.email = request.body.email;
		user.age = request.body.age;
		const updatedItem = await user.save();
		response.status(200).json(updatedItem);
	});
	

Delete Operation (DELETE):


For Delete MongoDB Data from Node CRUD Application, so first we have to create Delete button in each row of data in user.html file and then after we have to create deleteData() JavaScript function which will send DELETE data request to node route by using DELETE POST method.

user.html
	
	<!doctype html>
	<html lang="en">
		<head>
			<!-- Required meta tags -->
			<meta charset="utf-8">
			<meta name="viewport" content="width=device-width, initial-scale=1">

			<!-- Bootstrap CSS -->
			<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

			<title>Build a CRUD App with Node.js and MongoDB</title>
		</head>
		<body>
			
			<div class="container">
				<h1 class="text-center mb-5 mt-5 text-danger"><b>Build a CRUD App with Node.js and MongoDB - Delete Data from MongoDB Database - 5</b></h1>
				<div class="card mb-5">
					<div class="card-header">
						<div class="row">
							<div class="col col-6">Sample Data</div>
							<div class="col col-6">
								<button type="button" class="btn btn-primary btn-sm float-end" onclick="makeModal('Add User', 'Add', 'insertData')">Add</button>
							</div>
						</div>
					</div>
					<div class="card-body">
						<div class="table-responsive">
							<table class="table table-bordered table-striped">
								<thead>
									<tr>
										<th>Name</th>
										<th>Email</th>
										<th>Age</th>
										<th>Action</th>
									</tr>
								</thead>
								<tbody id="dataArea"></tbody>
							</table>
						</div>
					</div>
				</div>
			</div>
		</body>
	</html>
	<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"></script>
	<div id="modalArea"></div>

	<script>

	var userModalElement;

	function makeModal(title, button_value, callback)
	{
		let html = `
		<div class="modal" tabindex="-1" id="userModal">
			<div class="modal-dialog">
				<div class="modal-content">
					<form id="userform">
						<div class="modal-header">
							<h5 class="modal-title">${title}</h5>
							<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
						</div>
						<div class="modal-body">
							<div class="mb-3">
								<label>Name</label>
								<input type="text" name="name" id="name" class="form-control" />
							</div>
							<div class="mb-3">
								<label>Email</label>
								<input type="email" name="email" id="email" class="form-control" />
							</div>
							<div class="mb-3">
								<label>Age</label>
								<input type="number" name="age" id="age" class="form-control" />
							</div>
						</div>
						<div class="modal-footer">
							<input type="hidden" name="user_id" id="user_id" />
							<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
							<button type="button" class="btn btn-primary" onclick="${callback}()">${button_value}</button>
						</div>
					</form>
				</div>
			</div>
		</div>
		`;

		document.querySelector('#modalArea').innerHTML = html;

		userModalElement = new bootstrap.Modal(document.getElementById('userModal'));

		userModalElement.show();
	}

	function insertData()
	{
		let formElement = document.getElementById('userform');
		const formData = new FormData(formElement);
		// Convert formData to JSON
		const jsonData = {};
		formData.forEach((value, key) => {
			jsonData[key] = value;
		});
		// Make a POST request using Fetch API
		fetch('/users', {
			method : 'POST',
			body : JSON.stringify(jsonData),
			headers : {
				'Content-Type': 'application/json'
			}
		})
		.then(response => {
			return response.json();
		})
		.then(data => {
			userModalElement.hide();
			getData();
		});
	}

	getData();

	function getData(){
		fetch('/users')
		.then(response => {
			return response.json();
		})
		.then(data => {
			let html = '';
			if(data.length > 0){
				data.map((row) => {
					html += `
					<tr>
						<td>${row.name}</td>
						<td>${row.email}</td>
						<td>${row.age}</td>
						<td>
							<button type="button" class="btn btn-warning btn-sm" onclick="fetchSingleData('${row._id}')">Edit</button>
							<button type="button" class="btn btn-danger btn-sm" onclick="deleteData('${row._id}')">Delete</button>
						</td>
					</tr>
					`;
				});
			} else {
				html = '<tr><td colspan="4" class="text-center">No Data Found</td></tr>';
			}
			document.getElementById('dataArea').innerHTML = html;
		});
	}

	function fetchSingleData(id){
		fetch(`/users/${id}`)
		.then(response => {
			return response.json();
		})
		.then(data => {
			makeModal('Edit User', 'Edit', 'editData');
			document.getElementById('name').value = data.name;
			document.getElementById('email').value = data.email;
			document.getElementById('age').value = data.age;
			document.getElementById('user_id').value = data._id;
		});
	}

	function editData(){
		let formElement = document.getElementById('userform');
		const formData = new FormData(formElement);
		let jsonData = {};
		formData.forEach((value, key) => { 
			jsonData[key] = value;
		});
		const userId = document.getElementById('user_id').value;
		fetch(`/users/${userId}`, {
			method : 'PUT',
			body : JSON.stringify(jsonData),
			headers : {
				'Content-Type': 'application/json'
			}
		})
		.then(response => {
			return response.json();
		})
		.then(data => {
			userModalElement.hide();
			getData();
		});
	}

	function deleteData(id){
		if(confirm("Are you sure you want to delete this?")){
			fetch(`/users/${id}`, {
				method : 'DELETE',
				headers : {
					'Content-Type': 'application/json'
				}
			})
			.then(response => {
				return response.json();
			})
			.then(data => {
				getData();
			});
		}
	}

	</script>
	

The delete operation involves removing items from the database. We'll define a route to handle incoming DELETE requests to delete items.

server.js
	
	app.delete('/users/:id', async (request, response) => {
		const userId = request.params.id;
		// Fetch the user from the database
		const user = await User.findById(userId);
		await user.deleteOne();
		response.status(200).json({ message : 'Deleted item' });
	});
	




Step 8: Testing Your Application:


For test Mongo DB Node.js CRUD application in browser, so we have goes to terminal and run node server.jsthis command which will start Node Development server and provide us http://localhost:3000/ base url of our Node Application.

Conclusion:


Congratulations! You've successfully built a Node.js CRUD application with MongoDB. This tutorial covered the basics, but there's still room for improvement and expansion. Feel free to explore additional features and functionalities to enhance your application further.

Tuesday 20 February 2024

Converting Dynamic HTML to PDF in Node.js with Puppeteer


In this tutorial, we'll learn how to convert HTML content to a PDF file using Puppeteer in a Node.js environment. Puppeteer is a Node library that provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol, making it a powerful tool for automating web tasks, including generating PDF files from HTML content.


Converting Dynamic HTML to PDF in Node.js with Puppeteer


Prerequisites


Before we begin, ensure you have the following installed:

  • Node.js (with npm)
  • MySQL (for the database setup, optional for this tutorial)
  • Basic understanding of Node.js and JavaScript

Setting up the Project


First, let's set up a Node.js project and install the necessary dependencies.

Create a new directory for your project and navigate into it:

	
		mkdir html-to-pdf-nodejs
		cd html-to-pdf-nodejs
	

Initialize a new Node.js project:

	
		npm init -y
	

Install the required dependencies (Express, MySQL, Puppeteer, Open):

	
		npm install express mysql2 puppeteer open
	

Database Structure


For convert dynamic HTML to PDF we need to fetch data from MySQL table. So run below sql script which will create sampledata table in your database.

	
		CREATE TABLE `sampledata` (
		  `id` mediumint unsigned NOT NULL AUTO_INCREMENT,
		  `name` varchar(255) DEFAULT NULL,
		  `phone` varchar(100) DEFAULT NULL,
		  `email` varchar(255) DEFAULT NULL,
		  `address` varchar(255) DEFAULT NULL,
		  `postalZip` varchar(10) DEFAULT NULL,
		  `region` varchar(50) DEFAULT NULL,
		  `country` varchar(100) DEFAULT NULL,
		  PRIMARY KEY (`id`)
		) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
		
		INSERT INTO `sampledata` VALUES (1,'Stephen Taylor','1-802-830-1866','auctor.nunc@hotmail.com','5659 Luctus Rd.','21408','Dadra and Nagar Haveli','Poland'),(2,'Mason George','1-343-545-7768','mauris@aol.edu','Ap #221-6699 Lacus. St.','921307','FATA','Costa Rica'),(3,'Hasad Donaldson','1-666-557-3187','et.euismod@google.edu','Ap #383-4682 Ornare Av.','818143','Kinross-shire','United Kingdom'),(4,'Hall Holland','(805) 418-1538','tempor.est@icloud.com','P.O. Box 358, 7624 Tincidunt Avenue','486262','Madrid','Indonesia'),(5,'Adam Hampton','1-421-241-5178','cubilia.curae@google.ca','P.O. Box 161, 1859 Iaculis Av.','44837','Brussels Hoofdstedelijk Gewest','South Korea'),(6,'Elizabeth Allison','(538) 834-6212','elit.dictum@hotmail.edu','867-6580 At St.','33668','Jeju','Pakistan'),(7,'Neve Barber','1-552-311-0208','vestibulum.nec.euismod@google.com','224-8122 Donec Road','51174','Santa Catarina','Netherlands'),(8,'Fatima Pope','(619) 278-1176','nulla.integer@hotmail.couk','649-1054 Ipsum Rd.','748321','Bahia','Austria'),(9,'Shad Cobb','1-778-327-3349','dignissim.maecenas.ornare@outlook.edu','6983 Magna. Rd.','2163','Xīběi','Philippines'),(10,'Zephr Ruiz','1-544-316-1144','luctus.ipsum@google.ca','634-2043 Cras Avenue','3845','Mecklenburg-Vorpommern','Sweden'),(11,'Juliet Lynn','(375) 573-6793','proin.dolor.nulla@yahoo.net','Ap #179-6441 Cum Rd.','71829','Calabria','Turkey'),(12,'Candice Medina','1-441-292-1278','integer.vulputate@icloud.org','953-188 Et Rd.','440326','Vorarlberg','Australia'),(13,'Rhea Roach','(635) 768-6867','vitae.velit@icloud.edu','543-5616 Sem Av.','869566','Burgenland','Canada'),(14,'Dean Hendrix','(362) 760-8321','nunc.pulvinar@protonmail.ca','Ap #905-5267 Arcu Street','6755-4242','National Capital Region','Indonesia'),(15,'Malachi Mitchell','1-586-881-4174','eget.lacus.mauris@icloud.ca','P.O. Box 183, 1479 Massa. St.','367458','Västra Götalands län','Indonesia'),(21,'Gabriel Acevedo','1-215-463-4511','dictum.cursus@outlook.com','5681 Sit Rd.','28846','Lombardia','Italy'),(22,'Beau Norris','1-563-287-4004','eros@google.edu','Ap #533-2583 Duis Rd.','R8T 1S4','Eastern Visayas','United States'),(23,'Kylan Mckinney','1-533-833-5567','eleifend.vitae@hotmail.net','333-2972 Nec, Road','72866','Leinster','Australia'),(24,'Stone Parsons','1-584-246-2228','aenean@outlook.com','923-5509 Etiam Street','Y1R 5X7','Zamboanga Peninsula','Nigeria'),(25,'Neve Sweet','(764) 167-2572','tellus.aenean@aol.net','558-1070 Sed, St.','1023 PS','Vienna','United Kingdom');
	

Creating the Server and HTML Template


Now, let's create a basic Express server that serves an HTML page with sample data fetched from a MySQL database. We'll also include a button to trigger the conversion of the HTML to a PDF file.

Create a file named app.js with the following content:

app.js
	
		const express = require('express');
		const mysql = require('mysql2');
		//Add puppeteer library
		const puppeteer = require('puppeteer');
		const app = express();
		const port = 3000;
		app.use(express.json());
		//Serve static files (including index.html) from the root directory
		app.use(express.static(__dirname));
		const database = mysql.createConnection({
			host : 'localhost',
			user : 'root',
			password : '123456789',
			database : 'testing'
		});

		database.connect((error)=> {
			if(error){
				console.error('Error connecting to MySQL : ', error);
			} else{
				console.log('Connected to MySQL database');
			}
		});

		app.get('/data', (request, response) => {
			response.sendFile(__dirname + '/data.html');
		});

		app.post('/getData', (request, response) => {
			database.query('SELECT * FROM sampledata', async (error, results) => {
				response.status(200).json(results);
			});
		});

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

Create a file named data.html with the following content:

	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>How to Convert HTML to PDF in Node.js using Puppeteer</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">How to Convert HTML to PDF in Node.js using Puppeteer</h1>
					<div class="card">
						<div class="card-header">
							<div class="row">
								<div class="col col-6">Sample Data</div>
								<div class="col col-6">
									<a href="/convertPDF" class="btn btn-primary btn-sm float-end">Download in PDF</a>
								</div>
							</div>
						</div>
						<div class="card-body">
							<div class="table-responsive">
								<table class="table table-bordered table-striped">
									<thead>
										<tr>
											<th>Name</th>
											<th>Phone</th>
											<th>Email</th>
											<th>Address</th>
											<th>Zip</th>
											<th>Region</th>
											<th>Country</th>
										</tr>
									</thead>
									<tbody id="dataArea"></tbody>
								</table>
							</div>
						</div>
					</div>
				</div>

				<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"></script>
			</body>
		</html>

		<script>
			getData();
			function getData(){
				fetch('/getData', {
					method: 'POST'
				})
				.then(response => {
					return response.json();
				})
				.then(data => {
					if(data.length > 0){
						let html = '';
						for(let i = 0; i < data.length; i++){
							html += `
							<tr>
								<td>${data[i].name}</td>
								<td>${data[i].phone}</td>
								<td>${data[i].email}</td>
								<td>${data[i].address}</td>
								<td>${data[i].postalZip}</td>
								<td>${data[i].region}</td>
								<td>${data[i].country}</td>
							</tr>
							`;
						}
						document.getElementById('dataArea').innerHTML = html;
					}
				})
				.catch(error => {
					// Handle errors
					//console.error(error);
					alert(error);
				});
			}
		</script>
	

Save this code in the root directory of your project.

HTML to PDF Conversion


We'll define a function convertHTMLToPDF in app.js file that takes HTML content as input, converts it to a PDF file using Puppeteer, and opens the generated PDF file.

app.js
	
		async function convertHTMLToPDF(htmlContent, pdfFilePath, margins = {top: '10mm', right: '10mm', bottom: '10mm', left: '10mm'}){
			const browser = await puppeteer.launch();
			const page = await browser.newPage();
			// Set the page content
			await page.setContent(htmlContent);
			// Generate PDF
			await page.pdf({ path : pdfFilePath, format : 'A4', margin : margins });
			// Open the generated PDF file in the default PDF viewer
			const open = await import('open');
			await open.default(pdfFilePath);
			//close the browser
			await browser.close();
		}
	

Serving HTML and Triggering Conversion


Finally, we'll set up routes to fetch data from MySQL table and convert into HTML and serve the HTML data and trigger the conversion to PDF when the user clicks on Download in PDF button.

app.js
	
		app.get('/convertPDF', async (request, response)=>{
			database.query('SELECT * FROM sampledata', async (error, results) => {
				let html = '';
				if(results.length > 0){
					html += `
					<table width="100%" border="1" cellpadding="5" cellspacing="0">
						<tr>
							<th width="20%">Name</th>
							<th width="10%">Phone</th>
							<th width="20%">Email</th>
							<th width="20%">Address</th>
							<th width="10%">Zip</th>
							<th width="10%">Region</th>
							<th width="10%">Country</th>
						</tr>
					`;
					results.map((row)=>{
						html += `
						<tr>
							<th>${row.name}</th>
							<th>${row.phone}</th>
							<th>${row.email}</th>
							<th>${row.address}</th>
							<th>${row.postalZip}</th>
							<th>${row.region}</th>
							<th>${row.country}</th>
						</tr>
						`;
					});
					html += `
					</table>
					`;
				}
				await convertHTMLToPDF(html, 'data.pdf');
			});
		});
	

Running the Server


To run the server, execute the following command:

	
		node app.js
	

Visit http://localhost:3000/data in your web browser to see the sample data table. Click the "Download in PDF" button to convert the HTML table to a PDF file.

Conclusion


Congratulations! You've learned how to convert HTML content to a PDF file in Node.js using Puppeteer. This technique can be useful for generating PDF reports, invoices, or any other printable documents from dynamic HTML content.

Feel free to customize the code to suit your specific requirements and explore additional features offered by Puppeteer for web automation and PDF generation.

Complete Source Code


app.js
	
		const express = require('express');
		const mysql = require('mysql2');
		//Add puppeteer library
		const puppeteer = require('puppeteer');
		const app = express();
		const port = 3000;
		app.use(express.json());
		//Serve static files (including index.html) from the root directory
		app.use(express.static(__dirname));
		const database = mysql.createConnection({
			host : 'localhost',
			user : 'root',
			password : '123456789',
			database : 'testing'
		});

		database.connect((error)=> {
			if(error){
				console.error('Error connecting to MySQL : ', error);
			} else{
				console.log('Connected to MySQL database');
			}
		});

		app.get('/data', (request, response) => {
			response.sendFile(__dirname + '/data.html');
		});

		app.post('/getData', (request, response) => {
			database.query('SELECT * FROM sampledata', async (error, results) => {
				response.status(200).json(results);
			});
		});

		async function convertHTMLToPDF(htmlContent, pdfFilePath, margins = {top: '10mm', right: '10mm', bottom: '10mm', left: '10mm'}){
			const browser = await puppeteer.launch();
			const page = await browser.newPage();
			// Set the page content
			await page.setContent(htmlContent);
			// Generate PDF
			await page.pdf({ path : pdfFilePath, format : 'A4', margin : margins });
			// Open the generated PDF file in the default PDF viewer
			const open = await import('open');
			await open.default(pdfFilePath);
			//close the browser
			await browser.close();
		}

		app.get('/convertPDF', async (request, response)=>{
			database.query('SELECT * FROM sampledata', async (error, results) => {
				let html = '';
				if(results.length > 0){
					html += `
					<table width="100%" border="1" cellpadding="5" cellspacing="0">
						<tr>
							<th width="20%">Name</th>
							<th width="10%">Phone</th>
							<th width="20%">Email</th>
							<th width="20%">Address</th>
							<th width="10%">Zip</th>
							<th width="10%">Region</th>
							<th width="10%">Country</th>
						</tr>
					`;
					results.map((row)=>{
						html += `
						<tr>
							<th>${row.name}</th>
							<th>${row.phone}</th>
							<th>${row.email}</th>
							<th>${row.address}</th>
							<th>${row.postalZip}</th>
							<th>${row.region}</th>
							<th>${row.country}</th>
						</tr>
						`;
					});
					html += `
					</table>
					`;
				}
				await convertHTMLToPDF(html, 'data.pdf');
			});
		});


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

data.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>How to Convert HTML to PDF in Node.js using Puppeteer</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">How to Convert HTML to PDF in Node.js using Puppeteer</h1>
					<div class="card">
						<div class="card-header">
							<div class="row">
								<div class="col col-6">Sample Data</div>
								<div class="col col-6">
									<a href="/convertPDF" class="btn btn-primary btn-sm float-end">Download in PDF</a>
								</div>
							</div>
						</div>
						<div class="card-body">
							<div class="table-responsive">
								<table class="table table-bordered table-striped">
									<thead>
										<tr>
											<th>Name</th>
											<th>Phone</th>
											<th>Email</th>
											<th>Address</th>
											<th>Zip</th>
											<th>Region</th>
											<th>Country</th>
										</tr>
									</thead>
									<tbody id="dataArea"></tbody>
								</table>
							</div>
						</div>
					</div>
				</div>

				<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"></script>
			</body>
		</html>

		<script>
			getData();
			function getData(){
				fetch('/getData', {
					method: 'POST'
				})
				.then(response => {
					return response.json();
				})
				.then(data => {
					if(data.length > 0){
						let html = '';
						for(let i = 0; i < data.length; i++){
							html += `
							<tr>
								<td>${data[i].name}</td>
								<td>${data[i].phone}</td>
								<td>${data[i].email}</td>
								<td>${data[i].address}</td>
								<td>${data[i].postalZip}</td>
								<td>${data[i].region}</td>
								<td>${data[i].country}</td>
							</tr>
							`;
						}
						document.getElementById('dataArea').innerHTML = html;
					}
				})
				.catch(error => {
					// Handle errors
					//console.error(error);
					alert(error);
				});
			}
		</script>
	


Tuesday 13 February 2024

Simplifying User Authentication with JWT Tokens in Node.js


In modern web development, user authentication is a fundamental aspect of building secure applications. Implementing a login and registration system using JSON Web Tokens (JWT) in Node.js offers a robust solution that enhances security and simplifies user management. In this article, we'll explore how to implement user authentication using JWT tokens in a Node.js application.


Simplifying User Authentication with JWT Tokens in Node.js

What are JWT Tokens?


JWT tokens are an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. These tokens can be signed using a secret or a public/private key pair, providing a means of verifying the integrity of the information contained within.

  1. Step 1: Setting Up Your Node.js Environment
  2. Step 2: Creating the Express Server
  3. Step 3: Database Connection
  4. Step 4: Setting Up Routes
  5. Step 5: Implementing User Registration
  6. Step 6: Implementing User Login
  7. Step 7: Protecting Routes
  8. Step 8: Run Application
  9. Step 9: Conclusion

Step 1: Setting Up Your Node.js Environment


Ensure you have Node.js installed on your machine. If not, download and install it from the official Node.js website. Once installed, open your terminal and create a new directory for your project.

	
		mkdir node-jwt-auth
		cd node-jwt-auth
	

Initialize a new Node.js project and install the necessary dependencies.

	
		npm install express jsonwebtoken bcrypt body-parser mongoose
	

Step 2: Creating the Express Server


Create a file named app.js and set up a basic Express server.

app.js
	
		const express = require('express');
		const mysql = require('mysql2');
		const bcrypt = require('bcrypt');
		const jwt = require('jsonwebtoken');
		const app = express();
		const port = 3000;
		app.use(express.json());
		//Serve static files (including index.html) from the root directory
		app.use(express.static(__dirname));
	

Step 3: Database Connection


Under this app.js file we have to make MySQL Database connection. So user registration data will be stored under MySQL database.

app.js
	
		const database = mysql.createConnection({
			host : 'localhost',
			user : 'root',
			password : '123456789',
			database : 'testing'
		});

		database.connect((error)=> {
			if(error){
				console.error('Error connecting to MySQL : ', error);
			} else{
				console.log('Connected to MySQL database');
			}
		});
	

It will make database connection and also check that there is any error has been occured during database connection.

Below you can find MySQL table structure for user table. So you have to copy this .sql code and run in local MySQL database. So it will create user under which registration data will be stored.

	
		CREATE TABLE `user` (
		  `user_id` int NOT NULL AUTO_INCREMENT,
		  `user_email` varchar(70) DEFAULT NULL,
		  `user_password` varchar(70) DEFAULT NULL,
		  `user_name` varchar(45) DEFAULT NULL,
		  `email_verification_status` enum('Not Verified','Verified') DEFAULT NULL,
		  PRIMARY KEY (`user_id`)
		) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
	

Step 4: Setting Up Routes


Create routes under app.js file for handling user authentication and registration.

app.js
	
		app.get('/', (request, response)=>{
		
		});
		
		app.post('/register', async (request, response)=>{
		
		});
	

Define routes for user registration, login, and protected resources in the respective files.

Step 5: Implementing User Registration


First we have goes into '/' get route, and under this we have to write following code which will load index.html file on browser.

app.js
	
		app.get('/', (request, response)=>{
			response.sendFile(__dirname + '/index.html');
		});
	

After this, we have goes to index.html file and under this we have to create register form and then after we have to write JavaScript code for submit register form data using JavaScript fetch API. And here we have also use try catch block of handle error at front end side.

index.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Register</div>
								<div class="card-body">
									<form id="registerForm">
										<div class="mb-3">
											<label><b>Name</b></label>
											<input type="text" name="name" id="name" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>eMail</b></label>
											<input type="text" name="email" id="email" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>Password</b></label>
											<input type="password" name="password" id="password" class="form-control" />
										</div>
										<input type="submit" class="btn btn-primary" value="Register" />
									</form>
								</div>
							</div>
						</div>
					</div>
				</div>

				<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"></script>
			</body>
		</html>

		<script>

		document.getElementById("registerForm").addEventListener('submit', async function(event){
			event.preventDefault();
			const name = document.getElementById("name").value;
			const email = document.getElementById("email").value;
			const password = document.getElementById("password").value;
			let messageArea = document.getElementById("msgArea");
			try{
				const response = await fetch('/register', {
					method : 'POST',
					headers : {
						'Content-Type': 'application/json'
					},
					body : JSON.stringify({name, email, password})
				});
				if(response.ok){
					messageArea.innerHTML = '<div class="alert alert-success">User registered successfully!</div>';
				} else {
					const data = await response.json();
					messageArea.innerHTML = `<div class="alert alert-info">Error : ${data.error}</div>`;
				}

			} catch(error){
				messageArea.innerHTML = '<div class="alert alert-danger">Internal Server Error</div>';
			}
		});

		</script>
	

Now in app.js, implement the route for user registration. Hash the user's password using bcrypt before storing it in the database and here it has also check email is already exists or not also.

app.js
	
		app.post('/register', async (request, response)=>{
			try{
				const {name, email, password} = request.body;
				if(!name || !email || !password){
					return response.status(400).json({error : 'Please provide all required fields'});
				}
				// Check if the email already exists in the database
				database.query('SELECT * FROM user WHERE user_email = ?', [email], async (error, results) =>{
					if(error){
						return response.status(500).json({error : 'Internal Server Error'});
					}
					if(results.length > 0){
						return response.status(400).json({error : 'Email already exists'});
					}
					const hashedPassword = await bcrypt.hash(password, 10);
					//Insert registeration data
					database.query('INSERT INTO user (user_email, user_password, user_name) VALUES (?, ?, ?)', [email, hashedPassword, name], (error) => {
						if(error){
							console.log(error);
							return response.status(500).json({error : 'Internal Server Error'});
						}
						return response.status(201).json({message : 'User registered successfully'});
					});
				});
			} catch(error){
				response.status(500).json({error : 'Internal Server Error'});
			}
		});
		app.listen(port, () => {
			console.log(`Server is running on http://localhost:${port}`);   
		});
	

Step 6: Implementing User Login


Now for create Login in this Node JS Application, first in app.js file we have go create route for load login form in the browser.

app.js
	
		app.get('/login', (request, response) => {
			response.sendFile(__dirname + '/login.html');
		});
	

So it will send login.html file in browser and display login login form on web page.

Next we have to create login.html file and under this file, we will write HTML code for display Login form and JavaScript code for submit login form data to server.

login.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Login</div>
								<div class="card-body">
									<form id="loginForm">
										<div class="mb-3">
											<label><b>eMail</b></label>
											<input type="text" name="email" id="email" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>Password</b></label>
											<input type="password" name="password" id="password" class="form-control" />
										</div>
										<input type="submit" class="btn btn-primary" value="Login" />
									</form>
								</div>
							</div>
						</div>
					</div>
				</div>

				<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"></script>
			</body>
		</html>

		<script>

		document.getElementById('loginForm').addEventListener('submit', async function(event){
			event.preventDefault();
			const email = document.getElementById('email').value;
			const password = document.getElementById('password').value;
			try {
				const response = await fetch('/login', {
					method : 'POST',
					headers : {
						'Content-Type': 'application/json',
					},
					body : JSON.stringify({ email, password })
				});
				const data = await response.json();
				if(response.ok){
					localStorage.setItem('token', data.token);
					window.location.href = '/welcome';
				} else {
					document.getElementById('msgArea').innerHTML = `<div class="alert alert-info">Error : ${data.error}</div>`;
				}
			} catch(error){
				document.getElementById('msgArea').innerHTML = '<div class="alert alert-danger">Internal Server Error</div>';
			}
		});

		</script>
	

Once login form data has been submitted then it will send login data to /login route of app.js file. And under this file it will validate user login data and here it also also compare simple login form password with hashed formatted password which is stored in database by using bcrypt library.

app.js
	
		app.post('/login', async (request, response) => {
			try {
				const {email, password} = request.body;
				if(!email || !password){
					return response.status(400).json({ error : 'Please provide all required fields'});
				}
				database.query('SELECT * FROM user WHERE user_email = ?', [email], async (error, results) => {
					if(results.length > 0){
						const user = results[0];
						if(await bcrypt.compare(password, user.user_password)){
							const token = jwt.sign({ userId : user.user_id }, secretKey, { expiresIn : '1h' });
							response.status(200).json({ token });
						} else {
							response.status(401).json({ error : 'Wrong Password' });
						}
					} else {
						response.status(401).json({ error : 'Wrong Email' });
					}
				});
			} catch(error){
				response.status(500).json({ error : 'Internal Server Error' });
			}
		});
	

Step 7: Protecting Routes


Once we have make login page, when user has been login into system then user data has been stored in JWT token. Now we want to verify that user has been login into system or not. So for this we have to make one middleware to check user is login or not. In middleware it will decode JWT token data and then after it has authenticate that user is login or not.

So for this first we have to create one button, so when we have click on that button then it will send request to Node server route for fetch data from JWT token. So when we have send request to server, then in header it will send encoded JWT token data.

welcome.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Welcome Page</div>
								<div class="card-body">
									<h1 class="text-center">Welcome User</h1>
									<p class="text-center">
										<button type="button" class="btn btn-warning" onclick="getJWTData()">Get User ID</button>
										<button type="button" onclick="logout()" class="btn btn-primary">Logout</button>
									</p>
								</div>
							</div>
						</div>
					</div>
				</div>

				<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"></script>
			</body>
		</html>

		<script>

		const token = localStorage.getItem('token');
		if(!token){
			window.location.href = '/login';
		}

		function logout(){
			localStorage.removeItem('token');
			window.location.href = '/login';
		}

		function getJWTData(){
			fetch('/getJWTData', {
				headers : {
					'Authorization' : token
				}
			})
			.then(response => {
				return response.json();
			})
			.then(data => {
				alert(`Login User ID is - ${data.userId}`);
			})
			.catch(error => {
				alert(error);
			});
		}

		</script>
	

Now at Node backend side code, we have to create getJWTData route and under this route we have to add verifyToken middleware. So this middleware code will be first executed and it will first receive JWT token data from HTTP header. And then after by using JWT library it will again decode that data. If data has been successfully decoded that it will execute other part of code. But Suppose there JWT token not found in HTTP headers then it will directly send error to client without executing next code. But suppose data has been decoded from JWT token then it will send back that data to client which will be pop up on web page. So this way it will fetch data from JWT token under Node JS application.

app.js
	
		// Middleware to check JWT token
		function verifyToken(request, response, next){
			const token = request.headers.authorization;
			if(!token){
				return response.status(401).json({ error : 'Access denied. No token provided.'});
			}
			try {
				const decoded = jwt.verify(token, secretKey);
				request.user = decoded;
				next();
			} catch(error){
				response.status(401).json({ error : 'Invalid token' });
			}
		}

		app.get('/getJWTData', verifyToken, (request, response) => {
			response.status(200).json({ userId : request.user.userId });
		});
	

Step 8: Run Application


Once our code is ready, now for check output in browser, we have goes to terminal and run node app.js command which will start node server.

And in browser we can open this Node application by open http://localhost:3000 this url.

Step 9: Conclusion


You've successfully implemented a login and registration system using JWT tokens in your Node.js application. This provides a secure way to manage user sessions and protect sensitive resources. With the flexibility of Node.js and the simplicity of JWT tokens, you can now build robust authentication systems for your web applications.

Complete Source Code


app.js
	
		const express = require('express');
		const mysql = require('mysql2');
		const bcrypt = require('bcrypt');
		const jwt = require('jsonwebtoken');
		const app = express();
		const port = 3000;
		app.use(express.json());
		//Serve static files (including index.html) from the root directory
		app.use(express.static(__dirname));
		const database = mysql.createConnection({
			host : 'localhost',
			user : 'root',
			password : '123456789',
			database : 'testing'
		});

		database.connect((error)=> {
			if(error){
				console.error('Error connecting to MySQL : ', error);
			} else{
				console.log('Connected to MySQL database');
			}
		});

		const secretKey = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTcwNjg3ODE1MywiaWF0IjoxNzA2ODc4MTUzfQ.i4j208HUwM7JjLJL98o9EkE68Ia87i694iq7r67zRHM';

		app.get('/', (request, response)=>{
			response.sendFile(__dirname + '/index.html');
		});

		app.post('/register', async (request, response)=>{
			try{
				const {name, email, password} = request.body;
				if(!name || !email || !password){
					return response.status(400).json({error : 'Please provide all required fields'});
				}
				// Check if the email already exists in the database
				database.query('SELECT * FROM user WHERE user_email = ?', [email], async (error, results) =>{
					if(error){
						return response.status(500).json({error : 'Internal Server Error'});
					}
					if(results.length > 0){
						return response.status(400).json({error : 'Email already exists'});
					}
					const hashedPassword = await bcrypt.hash(password, 10);
					//Insert registeration data
					database.query('INSERT INTO user (user_email, user_password, user_name) VALUES (?, ?, ?)', [email, hashedPassword, name], (error) => {
						if(error){
							console.log(error);
							return response.status(500).json({error : 'Internal Server Error'});
						}
						return response.status(201).json({message : 'User registered successfully'});
					});
				});
			} catch(error){
				response.status(500).json({error : 'Internal Server Error'});
			}
		});

		app.get('/login', (request, response) => {
			response.sendFile(__dirname + '/login.html');
		});

		app.post('/login', async (request, response) => {
			try {
				const {email, password} = request.body;
				if(!email || !password){
					return response.status(400).json({ error : 'Please provide all required fields'});
				}
				database.query('SELECT * FROM user WHERE user_email = ?', [email], async (error, results) => {
					if(results.length > 0){
						const user = results[0];
						if(await bcrypt.compare(password, user.user_password)){
							const token = jwt.sign({ userId : user.user_id }, secretKey, { expiresIn : '1h' });
							response.status(200).json({ token });
						} else {
							response.status(401).json({ error : 'Wrong Password' });
						}
					} else {
						response.status(401).json({ error : 'Wrong Email' });
					}
				});
			} catch(error){
				response.status(500).json({ error : 'Internal Server Error' });
			}
		});

		app.get('/welcome', (request, response) => {
			response.sendFile(__dirname + '/welcome.html');
		});

		// Middleware to check JWT token
		function verifyToken(request, response, next){
			const token = request.headers.authorization;
			if(!token){
				return response.status(401).json({ error : 'Access denied. No token provided.'});
			}
			try {
				const decoded = jwt.verify(token, secretKey);
				request.user = decoded;
				next();
			} catch(error){
				response.status(401).json({ error : 'Invalid token' });
			}
		}

		app.get('/getJWTData', verifyToken, (request, response) => {
			response.status(200).json({ userId : request.user.userId });
		});


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

index.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Register</div>
								<div class="card-body">
									<form id="registerForm">
										<div class="mb-3">
											<label><b>Name</b></label>
											<input type="text" name="name" id="name" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>eMail</b></label>
											<input type="text" name="email" id="email" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>Password</b></label>
											<input type="password" name="password" id="password" class="form-control" />
										</div>
										<input type="submit" class="btn btn-primary" value="Register" />
									</form>
								</div>
							</div>
						</div>
					</div>
				</div>

				<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"></script>
			</body>
		</html>

		<script>

		document.getElementById("registerForm").addEventListener('submit', async function(event){
			event.preventDefault();
			const name = document.getElementById("name").value;
			const email = document.getElementById("email").value;
			const password = document.getElementById("password").value;
			let messageArea = document.getElementById("msgArea");
			try{
				const response = await fetch('/register', {
					method : 'POST',
					headers : {
						'Content-Type': 'application/json'
					},
					body : JSON.stringify({name, email, password})
				});
				if(response.ok){
					messageArea.innerHTML = '<div class="alert alert-success">User registered successfully!</div>';
				} else {
					const data = await response.json();
					messageArea.innerHTML = `<div class="alert alert-info">Error : ${data.error}</div>`;
				}

			} catch(error){
				messageArea.innerHTML = '<div class="alert alert-danger">Internal Server Error</div>';
			}
		});

		</script>
	

login.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Login</div>
								<div class="card-body">
									<form id="loginForm">
										<div class="mb-3">
											<label><b>eMail</b></label>
											<input type="text" name="email" id="email" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>Password</b></label>
											<input type="password" name="password" id="password" class="form-control" />
										</div>
										<input type="submit" class="btn btn-primary" value="Login" />
									</form>
								</div>
							</div>
						</div>
					</div>
				</div>

				<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"></script>
			</body>
		</html>

		<script>

		document.getElementById('loginForm').addEventListener('submit', async function(event){
			event.preventDefault();
			const email = document.getElementById('email').value;
			const password = document.getElementById('password').value;
			try {
				const response = await fetch('/login', {
					method : 'POST',
					headers : {
						'Content-Type': 'application/json',
					},
					body : JSON.stringify({ email, password })
				});
				const data = await response.json();
				if(response.ok){
					localStorage.setItem('token', data.token);
					window.location.href = '/welcome';
				} else {
					document.getElementById('msgArea').innerHTML = `<div class="alert alert-info">Error : ${data.error}</div>`;
				}
			} catch(error){
				document.getElementById('msgArea').innerHTML = '<div class="alert alert-danger">Internal Server Error</div>';
			}
		});

		</script>
	

welcome.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Welcome Page</div>
								<div class="card-body">
									<h1 class="text-center">Welcome User</h1>
									<p class="text-center">
										<button type="button" class="btn btn-warning" onclick="getJWTData()">Get User ID</button>
										<button type="button" onclick="logout()" class="btn btn-primary">Logout</button>
									</p>
								</div>
							</div>
						</div>
					</div>
				</div>

				<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"></script>
			</body>
		</html>

		<script>

		const token = localStorage.getItem('token');
		if(!token){
			window.location.href = '/login';
		}

		function logout(){
			localStorage.removeItem('token');
			window.location.href = '/login';
		}

		function getJWTData(){
			fetch('/getJWTData', {
				headers : {
					'Authorization' : token
				}
			})
			.then(response => {
				return response.json();
			})
			.then(data => {
				alert(`Login User ID is - ${data.userId}`);
			})
			.catch(error => {
				alert(error);
			});
		}

		</script>