Advanced Learning
Node Advanced Learning
Install
npm init -y
npm install express
Example 1
// Import required modules
const express = require('express');
const app = express();
// Define the port
const PORT = 8080;
// Route - Returns simple text data
app.get('/', (req, res) => {
res.send('Welcome to the Node.js API server!');
});
// Route - Returns user data in JSON format
app.get('/api/users', (req, res) => {
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 35 },
];
res.json(users);
});
// Start the server
app.listen(PORT, () => {
console.log(`Server started, access address: http://localhost:${PORT}`);
});
Example 2
// Import modules
const express = require('express');
const app = express();
const PORT = 8080;
// Middleware: Parse JSON data
app.use(express.json());
// Simulated database data
let users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 35 },
];
// Get all users (GET)
app.get('/api/users', (req, res) => {
res.json(users);
});
// Get a user by ID (GET)
app.get('/api/users/:id', (req, res) => {
const userId = parseInt(req.params.id, 10);
const user = users.find(u => u.id === userId);
if (user) {
res.json(user);
} else {
res.status(404).send('User not found');
}
});
// Create a new user (POST)
app.post('/api/users', (req, res) => {
const newUser = {
id: users.length + 1, // Simple ID generation
name: req.body.name,
age: req.body.age,
};
users.push(newUser);
res.status(201).json(newUser); // Return the newly created user
});
// Update a user (PUT)
app.put('/api/users/:id', (req, res) => {
const userId = parseInt(req.params.id, 10);
const user = users.find(u => u.id === userId);
if (user) {
user.name = req.body.name || user.name;
user.age = req.body.age || user.age;
res.json(user);
} else {
res.status(404).send('User not found');
}
});
// Delete a user (DELETE)
app.delete('/api/users/:id', (req, res) => {
const userId = parseInt(req.params.id, 10);
const userIndex = users.findIndex(u => u.id === userId);
if (userIndex !== -1) {
const deletedUser = users.splice(userIndex, 1);
res.json(deletedUser);
} else {
res.status(404).send('User not found');
}
});
// Start the server
app.listen(PORT, () => {
console.log(`Server started, access address: http://localhost:${PORT}`);
});
API test method
Use Postman
-
GET request
-
Get all users:
GET http://localhost:8080/api/users
-
Get a user by ID:
GET http://localhost:8080/api/users/1
-
POST request
-
Create a new user:
POST http://localhost:8080/api/users
-
Request body example:
{
"name": "David",
"age": 40
} -
PUT request
-
Update user information:
PUT http://localhost:8080/api/users/1
-
Request body example:
{
"name": "Alice Updated",
"age": 26
} -
DELETE request
-
Delete a user:
DELETE http://localhost:8080/api/users/1
Middleware - Using JWT Authentication
npm install express jsonwebtoken body-parser
Example 1
const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const crypto = require('crypto');
const express = require('express');
const bodyParser = require('body-parser'); // Import body-parser to parse request bodies
const jwt = require('jsonwebtoken'); // Import jsonwebtoken for JWT handling
const crypto = require('crypto'); // Import crypto for generating a random secret key
const app = express();
const SECRET_KEY = crypto.randomBytes(32).toString('hex'); // Generate a random 32-byte secret key
// Middleware to parse JSON request body data
app.use(bodyParser.json());
// Middleware: Validate JWT token
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization']; // Get the authorization header
const token = authHeader && authHeader.split(' ')[1]; // Extract the token from the header
if (!token) return res.status(401).send('Access Denied'); // If no token, respond with 401
// Verify the token using the secret key
jwt.verify(token, SECRET_KEY, (err, user) => {
if (err) return res.status(403).send('Invalid Token'); // If token is invalid, respond with 403
req.user = user; // Attach the user information to the request
next(); // Proceed to the next middleware or route handler
});
}
// Login route to generate JWT token
app.post('/login', (req, res) => {
const { username, password } = req.body; // Get username and password from request body
// Simulated user validation (in a real application, this should check a database)
if (username === 'testUser' && password === 'password123') {
const user = { username: 'testUser' }; // Create a user object
const token = jwt.sign(user, SECRET_KEY, { expiresIn: '1h' }); // Sign the token with the secret key
res.json({ token }); // Respond with the token
} else {
res.status(403).send('Invalid username or password'); // If invalid, respond with 403
}
});
// Protected route that only authenticated users can access
app.get('/protected', authenticateToken, (req, res) => {
res.send(`Hello ${req.user.username}, you have access to this protected resource!`); // Greet the authenticated user
});
// A public route that does not require authentication
app.get('/public', (req, res) => {
res.send('This is a public resource accessible to anyone.'); // Respond to public access
});
// Start the server
app.listen(8080, () => {
console.log('Server running on port 8080'); // Log the server status
});
Path description
- POST
/login
- Function: User login and obtain JWT token.
- Request body:
{ "username": "testUser", "password": "password123" }
- Return: JWT token.
- GET
/protected
- Function: Protected path, only users with valid JWT can access.
- Request header:
Authorization: Bearer <token>
- Return: Protected resource information.
- GET
/public
- Function: Public path, accessible without authentication.
- Return: Public resource information.
File upload and download - using Multer
npm install express multer
project-directory/
├── uploads/ # Directory for storing uploaded files / create it yourself
├── server.js # Main Server Files
├── package.json
Example 1
const express = require('express');
const multer = require('multer');
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
// Configure the storage for uploaded files
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/'); // Specify the directory to store uploaded files
},
filename: (req, file, cb) => {
cb(null, Date.now() + path.extname(file.originalname)); // Use a timestamp as the file name
}
});
// Create a multer instance with the storage configuration
const upload = multer({ storage });
// Route for uploading files
app.post('/upload', upload.single('file'), (req, res) => {
res.send(`File uploaded successfully: ${req.file.filename}`); // Send a response with the uploaded file's name
});
// Route for downloading files
app.get('/download/:filename', (req, res) => {
const filePath = path.join(__dirname, 'uploads', req.params.filename); // Construct the file path
res.download(filePath, (err) => {
if (err) {
res.status(404).send('File not found'); // Handle errors if the file is not found
}
});
});
// Start the server
app.listen(8080, () => {
console.log('Server running on port 8080'); // Log the server status
});
Html Uploads
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form action="http://localhost:8080/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="file" required />
<button type="submit">Upload</button>
</form>
</body>
</html>
Html Download
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Download</title>
</head>
<body>
<h1>Download File</h1>
<button id="downloadBtn">Download File</button>
<script>
document.getElementById('downloadBtn').addEventListener('click', function() {
window.location.href = 'http://localhost:8080/download/1730343500255.txt';
});
</script>
</body>
</html>
Use Postman to upload a file:
-
Open Postman.
-
Select the request method as
POST
. -
Enter the URL:
http://localhost:8080/upload
. -
In the
Body
tab, selectform-data
. -
In the
Key
field, enterfile
(this is the field name defined in multer). -
In the
Value
field, click the "Select File" button on the right and select the file to upload. -
Click the "Send" button.
Initiate a GET request in Postman:
-
Open Postman.
-
Select the request method as
GET
. -
Enter a URL, for example:
http://localhost:8080/download/your_uploaded_file_name.ext
replace
your_uploaded_file_name.ext
The file name you actually uploaded.
-
Click the "Send" button.
Check Download:
- Postman will prompt you to save the file. If everything is OK, you will be able to download the file.
Routing Description
- POST
/upload
- Function: Receive file uploads.
- File parameter:
file
(should be consistent with the field name uploaded in the front-end request). - Return: Upload success message, including the file name.
- GET
/download/:filename
- Function: Download the specified file.
- Request parameter:
filename
(the file name to be downloaded). - Return: Download the file or 404 error (file not found).
Real-time Communication - Using Socket.IO
npm install express socket.io
project-directory/
├── server.js # Node.js server files
├── public/ # Directory for storing front-end files
│ ├── index.html # Front-end HTML file
│ └── style.css # (Optional) Style file
└── package.json # Project Description File
Example
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const path = require('path');
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
// Import necessary modules
const express = require('express');
const http = require('http');
const path = require('path');
const { Server } = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server);
// Serve static files from the 'public' directory
app.use(express.static(path.join(__dirname, 'public')));
// Handle Socket.IO connections
io.on('connection', (socket) => {
console.log('A user connected');
// Listen for messages from clients
socket.on('chat message', (msg) => {
console.log('Message received: ' + msg);
// Broadcast the message to all clients
io.emit('chat message', msg);
});
// Handle user disconnection
socket.on('disconnect', () => {
console.log('A user disconnected');
});
});
// Start the server
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat App</title>
<link rel="stylesheet" href="style.css"> <!-- Optional styles -->
</head>
<body>
<h1>Chat Room</h1>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" placeholder="Type your message here..." /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
const form = document.getElementById('form');
const input = document.getElementById('input');
const messages = document.getElementById('messages');
form.addEventListener('submit', function(e) {
e.preventDefault();
if (input.value) {
// Send a message to the server
socket.emit('chat message', input.value);
input.value = '';
}
});
// Listen for messages sent by the server
socket.on('chat message', function(msg) {
const item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
</body>
</html>
Css
body {
font-family: Arial, sans-serif;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
li {
padding: 8px;
margin-bottom: 5px;
background-color: #f1f1f1;
border-radius: 4px;
}
form {
display: flex;
margin-top: 10px;
}
input {
flex: 1;
padding: 10px;
}
button {
padding: 10px;
}
Open your browser and visit http://localhost:3000
. You should be able to see the chat interface.
Public Chat Project
npm install mongoose
Using MongoDB Atlas is a very convenient way to host MongoDB databases. Here are the detailed steps to help you set up and use MongoDB Atlas:
1. Sign up for MongoDB Atlas
- Access MongoDB Atlas:
- Go to MongoDB Atlas.
- Create an account:
- Click "Get Started Free" to sign up for an account. If you already have an account, just log in.
2. Create a new cluster
- Create a cluster:
- Once logged in, click "Build a Cluster".
- Select a free cluster configuration (Free Tier).
- Select your cloud provider and region (it is recommended to choose a region closest to you for better performance).
- Click the "Create Cluster" button and wait for the cluster to be created (it may take a few minutes).
3. Configure database users
- Create a database user:
- After the cluster is created, click the "Database Access" option.
- Click "Add New Database User".
- Set the username and password, and select the "Read and write to any database" permission.
- Click "Add User".
4. Set network access
- Allow IP access:
- Click the "Network Access" option.
- Click "Add IP Address".
- Select "Allow Access from Anywhere" to allow any IP access (in a production environment, please limit IP as needed).
- Click "Confirm".
5. Get the connection string
- Get the connection string:
-
Return to the cluster page and click the "Connect" button.
-
Select "Connect your application".
-
Copy the connection string provided, which is in the following format:
mongodb+srv://<username>:<password>@cluster0.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
6. Connect to MongoDB Atlas using Mongoose
In your Node.js project, you need to install Mongoose (if not already installed):
npm install mongoose
Then connect to MongoDB Atlas in your code:
const mongoose = require('mongoose');
// Replace the username and password you created on Atlas with
const username = 'yourUsername';
const password = 'yourPassword';
const dbName = 'yourDatabaseName'; // Customizable database name
const uri = `mongodb+srv://${username}:${password}@cluster0.mongodb.net/${dbName}?retryWrites=true&w=majority`;
mongoose.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log('Connected to MongoDB Atlas');
})
.catch(err => {
console.error('Database connection error:', err);
});
7. Perform operations in the database
Once the connection is successful, you can create models, perform CRUD operations, etc. Here is a simple example:
const messageSchema = new mongoose.Schema({
text: String,
timestamp: { type: Date, default: Date.now },
});
const Message = mongoose.model('Message', messageSchema);
// Insert message example
const newMessage = new Message({ text: 'Hello, MongoDB Atlas!' });
newMessage.save()
.then(() => console.log('Message saved!'))
.catch(err => console.error('Error saving message:', err));
// Query message example
Message.find()
.then(messages => console.log('Messages:', messages))
.catch(err => console.error('Error fetching messages:', err));
8. Clean up resources
If you no longer use it, you can delete the cluster in the Atlas console to avoid unnecessary costs.
Summary
With the above steps, you can create a database on MongoDB Atlas and use it in a Node.js application. Atlas provides a powerful management interface that can easily monitor and manage the database
Example 1
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat App</title>
<link rel="stylesheet" href="style.css"> <!-- Optional styles -->
</head>
<body>
<h1>Chat Room</h1>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" placeholder="Type your message here..." /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
const form = document.getElementById('form');
const input = document.getElementById('input');
const messages = document.getElementById('messages');
// Loading history messages
socket.on('load messages', function(msgs) {
msgs.forEach(msg => {
const item = document.createElement('li');
item.textContent = msg.content; // Displaying messages using msg.content
messages.appendChild(item);
});
window.scrollTo(0, document.body.scrollHeight); // Scroll to the bottom of the page
});
form.addEventListener('submit', function(e) {
e.preventDefault();
if (input.value) {
// Send a message to the server
socket.emit('chat message', input.value);
input.value = '';
}
});
// Listen for messages sent by the server
socket.on('chat message', function(msg) {
const item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
</body>
</html>
css
body {
font-family: Arial, sans-serif;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
li {
padding: 8px;
margin-bottom: 5px;
background-color: #f1f1f1;
border-radius: 4px;
}
form {
display: flex;
margin-top: 10px;
}
input {
flex: 1;
padding: 10px;
}
button {
padding: 10px;
}
server.js
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const path = require('path');
const mongoose = require('mongoose');
const Message = require('./models/Message'); // Import Message model
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
// Replace with your username and password you created on Atlas
const username = 'wengchinbusiness'; // Replace with your username
const password = 'OdelKSTJEWDKD27T'; // Replace with your password
const dbName = 'sample_mflix'; // Use your database name
const uri = `mongodb+srv://${username}:${password}@cluster0.5x4eq.mongodb.net/${dbName}?retryWrites=true&w=majority&appName=Cluster0`;
mongoose.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log('Connected to MongoDB Atlas');
})
.catch(err => {
console.error('Database connection error:', err);
});
// Static file service
app.use(express.static(path.join(__dirname, 'public')));
// API route to get all messages
app.get('/messages', async (req, res) => {
try {
const messages = await Message.find().sort({ createdAt: 'asc' }); // Sort by time
res.json(messages); // Return message data
} catch (err) {
res.status(500).json({ error: 'Error fetching messages' });
}
});
// Handle Socket.IO connection
io.on('connection', (socket) => {
console.log('A user connected');
// Load historical messages when the user connects
Message.find().sort({ createdAt: 'asc' }).then(messages => {
socket.emit('load messages', messages); // Send historical messages to the client
});
// Listen for messages sent by the client
socket.on('chat message', async (msg) => {
console.log('Message received: ' + msg);
// Save message to the database
const message = new Message({ content: msg });
await message.save();
// Broadcast message to all clients
io.emit('chat message', msg);
});
socket.on('disconnect', () => {
console.log('A user disconnected');
});
});
// Start the server
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
models/Message.js
// models/Message.js
const mongoose = require('mongoose');
const messageSchema = new mongoose.Schema({
content: {
type: String,
required: true,
},
createdAt: {
type: Date,
default: Date.now,
},
});
const Message = mongoose.model('Message', messageSchema);
module.exports = Message;