0% found this document useful (0 votes)
126 views55 pages

UNIT-II-NODEJS

This document provides an overview of working with JSON, Buffers, and Streams in Node.js. It covers how to parse and stringify JSON, handle files using the fs module, and manage data streams for efficient processing. Additionally, it explains error handling and flow control in streams, along with examples of file operations like opening, reading, and writing files.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
126 views55 pages

UNIT-II-NODEJS

This document provides an overview of working with JSON, Buffers, and Streams in Node.js. It covers how to parse and stringify JSON, handle files using the fs module, and manage data streams for efficient processing. Additionally, it explains error handling and flow control in streams, along with examples of file operations like opening, reading, and writing files.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 55

UNIT -II

NODEJS WORKING WITH JSON

In Node.js, working with JSON (JavaScript Object Notation) is quite simple because JSON is
natively supported. Here are a few basic operations you can perform when working with JSON data
in Node.js:

1. Parsing JSON from a String

You can use JSON.parse() to convert a JSON string into a JavaScript object.

const jsonString = '{"name": "Sridhar", "age": 30, "city": "Warangal"}';


const obj = JSON.parse(jsonString);
console.log(obj.name);
console.log(obj.age); // 30

2. Converting JavaScript Object to JSON

To convert a JavaScript object into a JSON string, use JSON.stringify().

const obj = { name: "Nagarajy", age: 25, city: "London" };


const jsonString = JSON.stringify(obj);
console.log(jsonString); // {"name":"Nagaraju","age":25,"city":"London"}

3. Working with JSON Files

Node.js provides a built-in module called fs (File System) to read from and write to files. You can
use this to read and write JSON files.

Reading a JSON file

const fs = require('fs');

// Read the JSON file asynchronously


fs.readFile('data.json', 'utf8', (err, data) => {
if (err) {
console.log('Error reading file:', err);
return;
}
const jsonData = JSON.parse(data);
console.log(jsonData);
});
Writing to a JSON file
const fs = require('fs');
const data = {
name: "Bob",
age: 40,
city: "Warangal"
};
// Convert JavaScript object to JSON string
const jsonData = JSON.stringify(data);

// Write JSON data to file


fs.writeFile('output.json', jsonData, (err) => {
if (err) {
console.log('Error writing file:', err);
} else {
console.log('File has been saved!');
}
});

4. Example: Using JSON with an Express Server

If you’re using Express.js, you can easily handle JSON data in request and response objects.

Handling JSON request body

Ensure that the Express app is set up to handle JSON requests.

const express = require('express');


const app = express();

// Middleware to parse JSON request body


app.use(express.json());
app.post('/user', (req, res) => {
const user = req.body; // Assuming request body is JSON
console.log(user);
res.send({ message: 'User received', user });
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});

In this case, when you send a POST request with JSON data to /user, it will be parsed and logged.

5. Error Handling with JSON

Sometimes, when working with JSON, parsing errors can occur, especially if the JSON data is
malformed. Here's how you can handle such errors:

const jsonString = '{"name": "John", "age": 30'; // Incorrect JSON


try {
const obj = JSON.parse(jsonString);
console.log(obj);
} catch (error) {
console.log('Error parsing JSON:', error.message);
}

This will catch and log the error if the JSON is malformed.
USING BUFFER MODULE TO BUFFER DATA

In Node.js, the Buffer module is used to handle raw binary data directly. Buffers are especially
useful when working with binary streams, files, or any other kind of raw data that doesn’t naturally
fit into JavaScript's typical string encoding.

1. Creating Buffers

You can create a buffer in a few ways, such as from a string, an array, or allocating a new buffer
with a specific size.

Example 1: Creating a buffer from a string

const buffer = Buffer.from('Hello, world!', 'utf-8');


console.log(buffer); // <Buffer 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21>

In this example, the string 'Hello, world!' is converted to a buffer using the UTF-8 encoding.

Example 2: Creating a buffer from an array

const buffer = Buffer.from([1, 2, 3, 4, 5]);


console.log(buffer); // <Buffer 01 02 03 04 05>

This creates a buffer from an array of numbers, where each number represents a byte in the buffer.

Example 3: Allocating a buffer of a specific size

const buffer = Buffer.alloc(10); // Allocates a buffer of 10 bytes


console.log(buffer); // <Buffer 00 00 00 00 00 00 00 00 00 00>

This creates a buffer of 10 bytes, initialized with 0x00.

2. Reading Data from a Buffer

You can access the individual bytes of a buffer using its indices, just like an array.

Example:
const buffer = Buffer.from('Hello, world!');
console.log(buffer[0]); // 72 (ASCII code for 'H')
console.log(buffer[1]); // 101 (ASCII code for 'e')
3. Writing Data to a Buffer

You can modify data inside the buffer, as buffers are mutable.

Example:const buffer = Buffer.alloc(10);

buffer[0] = 72; // ASCII for 'H'


buffer[1] = 101; // ASCII for 'e'
buffer[2] = 108; // ASCII for 'l'
buffer[3] = 108; // ASCII for 'l'
buffer[4] = 111; // ASCII for 'o'
console.log(buffer.toString()); // "Hello"
4. Buffer Slicing

Buffers can be sliced into smaller buffers without copying the data.

Example:

const buffer = Buffer.from('Hello, world!');


const slicedBuffer = buffer.slice(0, 5);
console.log(slicedBuffer.toString()); // "Hello"

5. Concatenating Buffers

You can concatenate multiple buffers into a single buffer using Buffer.concat().

Example:

const buffer1 = Buffer.from('Hello');


const buffer2 = Buffer.from(' World');
const buffer3 = Buffer.concat([buffer1, buffer2]);

console.log(buffer3.toString()); // "Hello World"

6. Buffer Methods

Here are a few commonly used buffer methods:

 buffer.toString([encoding], [start], [end]): Converts the buffer to a string (default encoding is


UTF-8).
 buffer.copy(targetBuffer, targetStart, sourceStart, sourceEnd): Copies data from one buffer
to another.
 buffer.fill(value, [start], [end]): Fills the buffer with a specific value.
 buffer.includes(value, [byteOffset], [encoding]): Checks if a buffer contains a specific value.

Example of copy():

const buffer1 = Buffer.from('Hello, ');


const buffer2 = Buffer.from('world!');
buffer1.copy(buffer2, 0, 0, buffer1.length); // Copy "Hello, " into buffer2

console.log(buffer2.toString()); // "Hello, world!"

7. Working with Binary Data (Examples)

Buffers are commonly used in scenarios involving file I/O, streams, or binary protocols. For
example, when reading files in binary mode, fs.readFile() returns a buffer.

Example of reading a file as a buffer:

const fs = require('fs');

fs.readFile('example.txt', (err, data) => {


if (err) throw err;
console.log(data); // This is a buffer with raw binary data of the file
});
USING STREAM MODULE TO STREAM DATA

The stream module in Node.js provides a powerful and flexible way to handle streaming data.
Streams allow you to process data piece-by-piece, which is particularly useful when working with
large amounts of data that may not fit into memory all at once, such as reading and writing files or
handling HTTP requests and responses.

Types of Streams in Node.js

1. Readable Streams: Streams that you can read from. Example: fs.createReadStream(),
HTTP requests.
2. Writable Streams: Streams that you can write to. Example: fs.createWriteStream(), HTTP
responses.
3. Duplex Streams: Streams that are both readable and writable. Example: a network socket.
4. Transform Streams: A special type of duplex stream that can modify the data as it is being
read or written. Example: zlib.createGzip() for compression.

1. Reading Data with Readable Streams

Readable streams allow you to read data in chunks, which can be processed as the data is received
(avoiding the need to load the entire file into memory).

Example: Using fs.createReadStream()

const fs = require('fs');

// Create a readable stream


const readableStream = fs.createReadStream('example.txt', 'utf8');

// Read the data chunk by chunk


readableStream.on('data', (chunk) => {
console.log('Received chunk:', chunk);
});

// Handle stream end


readableStream.on('end', () => {
console.log('End of stream reached');
});

// Handle errors
readableStream.on('error', (err) => {
console.error('Error reading stream:', err);
});

2. Writing Data with Writable Streams

Writable streams allow you to write data to a destination. Example: writing to a file, sending HTTP
responses.

Example: Using fs.createWriteStream()


const fs = require('fs');
// Create a writable stream
const writableStream = fs.createWriteStream('output.txt');

// Write data to the stream


writableStream.write('Hello, world!\n');
writableStream.write('Writing more data...\n');

// End the stream


writableStream.end(() => {
console.log('Finished writing to file');
});

// Handle stream errors


writableStream.on('error', (err) => {
console.error('Error writing stream:', err);
});

3. Piping Streams Together

One of the most common use cases for streams is piping data from one stream to another. You can
use the .pipe() method to send data from a readable stream to a writable stream. This is particularly
useful for tasks like file copying, or reading from a network socket and sending the data to a file.

Example: Copying a file using streams

const fs = require('fs');

// Create a readable stream (from input file)


const readableStream = fs.createReadStream('input.txt');

// Create a writable stream (to output file)


const writableStream = fs.createWriteStream('output.txt');

// Pipe the readable stream to the writable stream


readableStream.pipe(writableStream);

writableStream.on('finish', () => {
console.log('File has been copied!');
});

4. Transform Streams

A transform stream is a type of duplex stream where data is transformed as it is read and written.
For example, you could use it to compress data, convert it to a different format, or filter content.

Example: Using zlib to compress a file

const fs = require('fs');
const zlib = require('zlib');

// Create a readable stream (from input file)


const readableStream = fs.createReadStream('input.txt');
// Create a writable stream (to output compressed file)
const writableStream = fs.createWriteStream('output.txt.gz');

// Create a transform stream to gzip the data


const gzipStream = zlib.createGzip();

// Pipe the data through the gzip stream


readableStream.pipe(gzipStream).pipe(writableStream);

writableStream.on('finish', () => {
console.log('File has been compressed!');
});

5. Handling HTTP Requests and Responses with Streams

Streams are often used in web servers, especially when handling large HTTP requests and
responses.

Example: Using Express.js to stream a file

const express = require('express');


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

// Serve a large file using streams


app.get('/download', (req, res) => {
const fileStream = fs.createReadStream('large-file.txt');
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Content-Disposition', 'attachment; filename="large-file.txt"');
fileStream.pipe(res);
});

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

6. Flow Control with Streams

Streams in Node.js also support flow control, meaning you can control when data is read from a
stream. The default behavior is flowing mode, where data is read automatically as it becomes
available.

You can switch to paused mode if you want to control when data is read.

Example: Paused mode

const fs = require('fs');
// Create a readable stream in paused mode
const readableStream = fs.createReadStream('example.txt', { highWaterMark: 16 });

// Manually read chunks when ready


readableStream.on('readable', () => {
let chunk;
while (null !== (chunk = readableStream.read())) {
console.log('Read chunk:', chunk.toString());
}
});

7. Error Handling

Proper error handling is crucial when working with streams. You should listen for the 'error' event
on both readable and writable streams.

Example: Error handling in streams

const fs = require('fs');

// Create a readable stream


const readableStream = fs.createReadStream('nonexistent-file.txt');

// Handle errors in the readable stream


readableStream.on('error', (err) => {
console.error('Stream error:', err.message);
});

Summary of Key Points

 Readable Streams: Used for reading data piece-by-piece (fs.createReadStream(), HTTP


requests).
 Writable Streams: Used for writing data (fs.createWriteStream(), HTTP responses).
 Duplex Streams: Both readable and writable (e.g., network sockets).
 Transform Streams: Modify data as it’s read and written (e.g., compression with
zlib.createGzip()).
 Piping: Use .pipe() to pipe data from a readable stream to a writable stream.
 Flow Control: You can manage data flow with readable and read() for finer control.

Streams are powerful for handling large or continuous data and are a fundamental part of Node.js
for I/O-bound tasks.

ACCESSING THE FILE SYSTEM FROM NODE.JS - OPENING, CLOSING, WRITING,


READING FILES AND OTHER FILE SYSTEM TASKS

Node.js provides a built-in fs (file system) module that allows you to perform various tasks related
to files and directories, such as opening, closing, reading, writing, and manipulating files. The fs
module offers both synchronous and asynchronous methods to handle these tasks, which makes it
highly flexible for different use cases.

1. Importing the fs Module

To interact with the file system, you first need to require the fs module:

const fs = require('fs');
2. Opening a File

Asynchronous File Opening:

The fs.open() method opens a file asynchronously, providing you with a file descriptor that you can
use for reading or writing.

Const fs=require(‘fs’);
fs.open('example.txt', 'r', (err, fd) => {
if (err) {
console.error('Error opening file:', err);
return;
}
console.log('File opened successfully with file descriptor:', fd);
});

In the above example:

 'r' specifies that the file will be opened for reading.


 The callback provides the file descriptor fd for further operations (like reading or writing).

Synchronous File Opening:

If you prefer to use the synchronous version, you can use fs.openSync():

Const fs=require(‘fs’);
try {
const fd = fs.openSync('example.txt', 'r');
console.log('File opened successfully with file descriptor:', fd);
} catch (err) {
console.error('Error opening file:', err);
}

3. Closing a File

Asynchronous File Closing:

You can close an opened file using fs.close(), providing the file descriptor that you got from
fs.open().

Const fs=require(‘fs’);
fs.open('example.txt', 'r', (err, fd) => {
if (err) {
console.error('Error opening file:', err);
return;
}

fs.close(fd, (err) => {


if (err) {
console.error('Error closing file:', err);
} else {
console.log('File closed successfully');
}
});
});

Synchronous File Closing:

For synchronous closing, use fs.closeSync():

Const fs=require(‘fs’);
try {
const fd = fs.openSync('example.txt', 'r');
fs.closeSync(fd);
console.log('File closed successfully');
} catch (err) {
console.error('Error closing file:', err);
}

4. Reading a File

Asynchronous File Reading:

The fs.read() method reads data from an opened file. You must first open the file using fs.open(),
and then you can read from it.

fs.open('example.txt', 'r', (err, fd) => {


if (err) {
console.error('Error opening file:', err);
return;
}

const buffer = Buffer.alloc(1024); // Allocate buffer of 1024 bytes


fs.read(fd, buffer, 0, buffer.length, 0, (err, bytesRead, buffer) => {
if (err) {
console.error('Error reading file:', err);
} else {
console.log('Bytes read:', bytesRead);
console.log('Content:', buffer.toString('utf8', 0, bytesRead));
}

fs.close(fd, (err) => {


if (err) console.error('Error closing file:', err);
});
});
});

Synchronous File Reading:

For synchronous reading, you can use fs.readFileSync():

try {
const data = fs.readFileSync('example.txt', 'utf8');
console.log('File content:', data);
} catch (err) {
console.error('Error reading file:', err);
}
5. Writing to a File

Asynchronous File Writing:

The fs.write() method allows you to write data to a file. You must open the file first.

fs.open('example.txt', 'w', (err, fd) => {


if (err) {
console.error('Error opening file:', err);
return;
}

const data = 'Hello, world!';


fs.write(fd, data, 0, data.length, null, (err, written, string) => {
if (err) {
console.error('Error writing to file:', err);
} else {
console.log(`${written} bytes written to file`);
}

fs.close(fd, (err) => {


if (err) console.error('Error closing file:', err);
});
});
});

Synchronous File Writing:

To write to a file synchronously, use fs.writeFileSync():

try {
fs.writeFileSync('example.txt', 'Hello, world!');
console.log('Data written to file');
} catch (err) {
console.error('Error writing to file:', err);
}

6. Appending Data to a File

Asynchronous File Appending:

To append data to a file (instead of overwriting it), use fs.appendFile():

fs.appendFile('example.txt', 'Appended data.\n', (err) => {


if (err) {
console.error('Error appending data to file:', err);
} else {
console.log('Data appended successfully');
}
});

Synchronous File Appending:

To append data synchronously, use fs.appendFileSync():


try {
fs.appendFileSync('example.txt', 'Appended data.\n');
console.log('Data appended successfully');
} catch (err) {
console.error('Error appending data to file:', err);
}

7. Renaming a File

You can rename a file using fs.rename():

fs.rename('oldName.txt', 'newName.txt', (err) => {


if (err) {
console.error('Error renaming file:', err);
} else {
console.log('File renamed successfully');
}
});

8. Deleting a File

To delete a file, use fs.unlink():

fs.unlink('example.txt', (err) => {


if (err) {
console.error('Error deleting file:', err);
} else {
console.log('File deleted successfully');
}
});

9. Checking if a File Exists

To check if a file exists, use fs.existsSync() (synchronous):

if (fs.existsSync('example.txt')) {
console.log('File exists');
} else {
console.log('File does not exist');
}

For an asynchronous check, you can use fs.access():

fs.access('example.txt', fs.constants.F_OK, (err) => {


if (err) {
console.error('File does not exist');
} else {
console.log('File exists');
}
});
10. Reading Directory Contents

To list the contents of a directory, use fs.readdir():

fs.readdir('.', (err, files) => {


if (err) {
console.error('Error reading directory:', err);
} else {
console.log('Directory contents:', files);
}
});

11. Creating and Removing Directories

 Creating a directory: fs.mkdir() (asynchronous) or fs.mkdirSync() (synchronous):

fs.mkdir('newDir', (err) => {


if (err) {
console.error('Error creating directory:', err);
} else {
console.log('Directory created successfully');
}
});
 Removing a directory: fs.rmdir() (asynchronous) or fs.rmdirSync() (synchronous):

fs.rmdir('newDir', (err) => {


if (err) {
console.error('Error removing directory:', err);
} else {
console.log('Directory removed successfully');
}
});

Summary

The fs module provides both asynchronous and synchronous methods for performing file system
operations. It is highly versatile, allowing you to:

 Open, close, read, and write files


 Append data to files
 Rename and delete files
 Create and remove directories
 Check file existence and read directory contents

For most I/O tasks, the asynchronous methods are preferred, as they avoid blocking the event loop,
making your application more efficient and responsive.

IMPLEMENTING HTTP SERVICES IN NODE.JS-PROCESSING URLS


In Node.js, you can create HTTP services and handle requests using the built-in http module. The
http module allows you to process URLs, handle HTTP methods (GET, POST, PUT, DELETE,
etc.), and send responses to the client.

Setting Up a Basic HTTP Server

To start, let's create a basic HTTP server using Node.js:

const http = require('http');

// Create an HTTP server


const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, World!\n');
});

// Listen on port 3000


server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

This basic server sends a "Hello, World!" message when you visit http://localhost:3000/ in your
browser.

1. Processing URLs in HTTP Requests

When a client makes an HTTP request, it includes a URL that contains important information such
as the path, query parameters, and sometimes fragments. In Node.js, we can process these
components and use them to perform different actions.

Example: Extracting Path and Query Parameters

To handle URLs and extract query parameters, we can use the url module, which provides utility
methods to parse and format URLs.

Here’s an example of how you can process URLs in an HTTP server:

const http = require('http');


const url = require('url');

// Create an HTTP server


const server = http.createServer((req, res) => {
// Parse the incoming request URL
const parsedUrl = url.parse(req.url, true); // 'true' to parse query parameters

const pathname = parsedUrl.pathname;


const query = parsedUrl.query; // Contains query parameters

// Log the path and query parameters to the console


console.log(`Path: ${pathname}`);
console.log(`Query Parameters:`, query);

// Send a response back


res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');

// Example response with query parameters


res.end(JSON.stringify({
message: 'Request received',
path: pathname,
query: query,
}));
});

// Listen on port 3000


server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

Example request:

 Visit http://localhost:3000/products?category=electronics&price=1000

The server will log the following:

Path: /products
Query Parameters: { category: 'electronics', price: '1000' }

And respond with:

{
"message": "Request received",
"path": "/products",
"query": {
"category": "electronics",
"price": "1000"
}
}

2. Handling Different HTTP Methods

The req (request) object contains the HTTP method (GET, POST, PUT, DELETE, etc.) that was
used in the request. We can check the HTTP method and route the request accordingly.

Example: Handling Different Methods

const http = require('http');


const url = require('url');

// Create an HTTP server


const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const pathname = parsedUrl.pathname;

// Handle different HTTP methods


if (req.method === 'GET') {
if (pathname === '/hello') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, GET request received!');
} else {
res.statusCode = 404;
res.end('Not Found');
}
} else if (req.method === 'POST' && pathname === '/hello') {
let body = '';
req.on('data', chunk => {
body += chunk; // Collect the data chunks
});
req.on('end', () => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end(`Received POST data: ${body}`);
});
} else {
res.statusCode = 405; // Method Not Allowed
res.end('Method Not Allowed');
}
});

// Listen on port 3000


server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

Example requests:

 GET request to http://localhost:3000/hello:


o Response: Hello, GET request received!

 POST request to http://localhost:3000/hello with body name=John:


o Response: Received POST data: name=John

3. Dynamic Routing with Parameters

You can use dynamic route matching by processing parts of the URL path. You can extract
variables from the path using regular expressions or by splitting the URL path.

Example: Handling Dynamic Routes

const http = require('http');


const url = require('url');

// Create an HTTP server


const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const pathname = parsedUrl.pathname;

// Extract dynamic parameters from the URL path


const parts = pathname.split('/').filter(Boolean); // Split and remove empty strings
if (parts[0] === 'user' && parts[1]) {
const userId = parts[1]; // Extract user ID from the URL path
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
message: `User details for user ID ${userId}`,
userId: userId,
}));
} else {
res.statusCode = 404;
res.end('Not Found');
}
});

// Listen on port 3000


server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

Example request:

 Visit http://localhost:3000/user/12345

The server will respond with:

{
"message": "User details for user ID 12345",
"userId": "12345"
}

4. Query Parameters in Dynamic Routes

You can combine both dynamic path parameters and query parameters to create more sophisticated
URLs.

Example: Using Query Parameters with Dynamic Paths

const http = require('http');


const url = require('url');

// Create an HTTP server


const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true); // Parse query parameters
const pathname = parsedUrl.pathname;

if (pathname === '/products') {


const category = parsedUrl.query.category || 'all';
const price = parsedUrl.query.price || 'any';

res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
message: `Displaying products in category ${category} with price ${price}`,
category: category,
price: price,
}));
} else {
res.statusCode = 404;
res.end('Not Found');
}
});

// Listen on port 3000


server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

Example request:

 Visit http://localhost:3000/products?category=electronics&price=1000

The server will respond with:

{
"message": "Displaying products in category electronics with price 1000",
"category": "electronics",
"price": "1000"
}

5. Handling 404 and Default Routes

To handle requests for routes that are not defined, you can implement a default route that returns a
404 response.

const http = require('http');

// Create an HTTP server


const server = http.createServer((req, res) => {
if (req.url === '/hello') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, World!');
} else {
// Handle unknown routes with 404
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('404 Not Found');
}
});

// Listen on port 3000


server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

Conclusion
In Node.js, handling HTTP requests and processing URLs is a core part of building HTTP services.
Using the built-in http and url modules, you can:

 Handle different HTTP methods (GET, POST, etc.)


 Extract and process path and query parameters from the URL
 Implement dynamic routing
 Handle 404 errors and default routes

These techniques enable you to build flexible and efficient web services and APIs in Node.js.

PROCESSING QUERY STRINGS AND FORM PARAMETERS

In Node.js, processing query strings (from URLs) and form parameters (from POST requests) is a
common task, especially when building web applications or APIs. We can handle both of these
types of data with the help of built-in modules like url, querystring, and handling request bodies
directly.

Let’s dive into how we can process query strings (GET requests) and form parameters (POST
requests) in Node.js.

1. Processing Query Strings (GET Requests)

Query strings are the part of the URL that comes after the ? character and are used to send data to
the server. They are typically used in GET requests.

Example URL:

http://localhost:3000/search?category=electronics&price=1000

In the above URL:

 category=electronics
 price=1000

These are query parameters that we can extract from the request.

Processing Query Strings with url.parse()

Node.js provides the url module to parse the request URL and extract query parameters.

Here’s how we can extract query parameters:

const http = require('http');


const url = require('url');

// Create HTTP server


const server = http.createServer((req, res) => {
// Parse the incoming request URL
const parsedUrl = url.parse(req.url, true); // 'true' to parse query strings
const query = parsedUrl.query; // Contains query parameters

// Access individual query parameters


const category = query.category || 'all';
const price = query.price || 'any';

// Respond with the query parameters


res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
message: 'Search results',
category: category,
price: price,
}));
});

// Listen on port 3000


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

Example Request:

 URL: http://localhost:3000/search?category=electronics&price=1000

Response:

{
"message": "Search results",
"category": "electronics",
"price": "1000"
}

Query Strings with Default Values

In the example above, the code checks if the query parameters are provided. If they are missing, it
uses default values ('all' for category and 'any' for price).

2. Processing Form Parameters (POST Requests)

Form parameters are typically sent in POST requests, and they contain data submitted from forms
(e.g., login forms, registration forms). When dealing with form parameters, the data is usually sent
in the request body.

Using the querystring Module for Form Parameters

Node.js does not parse the body of a POST request by default. To process form parameters, you
need to read the body and parse it.

You can use the querystring module (or URLSearchParams in newer Node.js versions) to parse
form data, but we’ll first need to collect the data from the request body.

Here’s how you can handle form parameters in a POST request:


const http = require('http');
const querystring = require('querystring');

// Create an HTTP server


const server = http.createServer((req, res) => {
// Handle only POST requests to /submit
if (req.method === 'POST' && req.url === '/submit') {
let body = '';

// Collect the data in chunks as they come in


req.on('data', chunk => {
body += chunk;
});

// Once all the data is received


req.on('end', () => {
// Parse the form data (assuming it's URL-encoded)
const parsedData = querystring.parse(body);

// Access individual form fields


const username = parsedData.username || 'Guest';
const password = parsedData.password || 'No password provided';

// Respond with the form data


res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
message: 'Form submitted successfully',
username: username,
password: password,
}));
});
} else {
// Handle unsupported requests
res.statusCode = 404;
res.end('Not Found');
}
});

// Listen on port 3000


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

Example Request (POST):

 URL: http://localhost:3000/submit
 Form Data (submitted via a form):
o username=alice

o password=secret123

To simulate sending a POST request from a form, you can use curl or an HTML form.
Example with curl:

curl -X POST http://localhost:3000/submit -d "username=alice&password=secret123"

Response:

{
"message": "Form submitted successfully",
"username": "alice",
"password": "secret123"
}

3. Handling JSON Data in POST Requests

In modern web applications, it's common to send JSON data in POST requests, especially when
interacting with APIs. To handle JSON payloads, you need to parse the request body as JSON.

Example: Processing JSON Data (POST)

const http = require('http');

// Create an HTTP server


const server = http.createServer((req, res) => {
// Handle only POST requests to /json
if (req.method === 'POST' && req.url === '/json') {
let body = '';

// Collect data chunks as they come in


req.on('data', chunk => {
body += chunk;
});

// Once all data is collected, parse the JSON


req.on('end', () => {
try {
const parsedData = JSON.parse(body); // Parse JSON data

// Access individual fields from the JSON object


const name = parsedData.name || 'Anonymous';
const age = parsedData.age || 'Not provided';

// Respond with the JSON data


res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
message: 'JSON data received',
name: name,
age: age,
}));
} catch (err) {
res.statusCode = 400; // Bad Request
res.end('Invalid JSON');
}
});
} else {
// Handle unsupported requests
res.statusCode = 404;
res.end('Not Found');
}
});

// Listen on port 3000


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

Example Request (POST with JSON):

To send JSON data via curl, use the following command:

curl -X POST http://localhost:3000/json -H "Content-Type: application/json" -d


'{"name":"John","age":30}'

Response:

{
"message": "JSON data received",
"name": "John",
"age": 30
}

4. URL Encoding and Decoding

Sometimes, form data or query parameters can contain special characters that need to be encoded or
decoded properly. This can be done using encodeURIComponent and decodeURIComponent.

 Encoding: encodeURIComponent('Hello World!') will result in "Hello%20World%21"


 Decoding: decodeURIComponent('Hello%20World%21') will result in "Hello World!"

You can use these functions when constructing or processing URLs to handle special characters
properly.

Conclusion

In Node.js, you can process query strings (GET request parameters) and form parameters (POST
request body) using built-in modules like url, querystring, and http. Here are the main techniques
we covered:

 Query Strings (GET Requests): Extracting data from the URL using url.parse().
 Form Parameters (POST Requests): Parsing form data from the request body using
querystring.parse() for URL-encoded data.
 JSON Data (POST Requests): Handling JSON payloads by parsing the body as JSON with
JSON.parse().
 URL Encoding/Decoding: Using encodeURIComponent and decodeURIComponent to
handle special characters.

These are common tasks when building web services and APIs in Node.js, and these approaches
can be easily extended to handle more complex use cases.

UNDERSTANDING REQUEST, RESPONSE AND SERVER OBJECTS

In Node.js, the http module provides the core functionality to create HTTP servers and process
HTTP requests and responses. The http module's server is built around the request (req) and
response (res) objects, which play crucial roles in handling incoming requests and sending out
responses.

1. The request Object (req)

The request object represents the incoming HTTP request made by a client (e.g., a browser, mobile
app, or any HTTP client). It contains important information about the request such as headers, URL,
HTTP method (GET, POST, etc.), query parameters, request body, and more.

Key Properties of the req Object:

 req.method: The HTTP method used for the request (e.g., 'GET', 'POST', 'PUT',
'DELETE').
 req.url: The full URL of the request, including the path and query string (e.g., /home?
search=query).
 req.headers: An object containing the request headers, such as User-Agent, Content-Type,
Authorization, etc.
 req.body: This contains the body of the request, which is typically populated in POST and
PUT requests. It requires parsing (e.g., JSON or URL-encoded data).
 req.query: Contains the query string parameters from the URL (e.g., ?
name=John&age=30). For parsing query strings, url.parse() can be used or express
framework can parse it automatically.
 req.params: In routes with dynamic path parameters, the req.params object stores those
variables. For example, in a route like /user/:id, req.params.id will contain the value of id.

Example: Inspecting the Request Object

const http = require('http');

const server = http.createServer((req, res) => {


// Log request method, URL, and headers
console.log(`Method: ${req.method}`);
console.log(`URL: ${req.url}`);
console.log(`Headers:`, req.headers);

res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Request details logged.');
});

server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

2. The response Object (res)

The response object represents the HTTP response that the server sends back to the client. It
contains methods and properties for setting the status code, headers, and body of the response.

Key Methods of the res Object:

 res.statusCode: Set the HTTP status code for the response (e.g., 200 for success, 404 for
not found).
 res.setHeader(name, value): Set a specific HTTP header in the response. For example, you
can use res.setHeader('Content-Type', 'application/json') to set the response type to JSON.
 res.end([data]): End the response and optionally send data (e.g., a string or a buffer). If no
data is provided, the response is ended with no body.
 res.write(data): Used to send data in chunks (e.g., for streaming large files). You can call
res.write() multiple times, and finally call res.end() to finish the response.
 res.json(obj) (in frameworks like Express): Sends a JSON response to the client. This is not
available in the core http module but can be implemented by calling
res.end(JSON.stringify(obj)).

Example: Responding with Data

const http = require('http');

const server = http.createServer((req, res) => {


// Set status code and headers
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');

// Send a JSON response


const responseData = {
message: 'Request successful',
method: req.method,
url: req.url,
};

res.end(JSON.stringify(responseData)); // Send the response body


});

server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});
3. The server Object

The server object represents the HTTP server itself. It's an instance of the http.Server class, which is
created using http.createServer().

Creating and Starting the Server

const http = require('http');

// Create an HTTP server


const server = http.createServer((req, res) => {
// Handle requests and send responses here
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, World!');
});

// Start the server and listen on a port


server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

The server.listen() method binds the server to a specific port and makes it listen for incoming
requests.

 server.listen(port, hostname, callback): This method listens on the specified port (e.g.,
3000) and hostname (optional, usually 'localhost'). The callback function is executed once
the server starts.
 server.close(): This method is used to stop the server from accepting new connections.

Example: Creating a Simple Server

const http = require('http');

const server = http.createServer((req, res) => {


res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Server is working!');
});

server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

4. Workflow with req, res, and server Objects

When a request is made to your server, it follows a flow like this:

1. Server receives the request: The server created with http.createServer() listens for
incoming requests. When a request comes in, the callback function you provided is invoked,
and the req (request) and res (response) objects are passed to it.
2. Request processing: Inside the callback function, you inspect the req object to process the
request, including the HTTP method, headers, URL, and body. You can also access
parameters from the query string or URL path (e.g., req.query, req.params).
3. Response generation: After processing the request, you use the res object to build the
response. You can set status codes (e.g., res.statusCode = 200), set headers (e.g.,
res.setHeader('Content-Type', 'application/json')), and send the response body (e.g.,
res.end('Hello, World!')).
4. Server sends the response: Once the response is fully constructed, the res.end() method
sends the response back to the client.

Example with Full Flow

const http = require('http');


const url = require('url');

const server = http.createServer((req, res) => {


const parsedUrl = url.parse(req.url, true); // Parse URL and query parameters
const pathname = parsedUrl.pathname;

if (req.method === 'GET' && pathname === '/greet') {


const name = parsedUrl.query.name || 'Guest'; // Get the query parameter 'name'

res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end(`Hello, ${name}!`); // Respond with a greeting message
} else {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('Not Found'); // Handle unknown routes
}
});

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

Example Request:

 URL: http://localhost:3000/greet?name=John

Response:

Hello, John!

5. Summary of Key Objects

 req (Request Object): Represents the incoming HTTP request. It contains details about the
request, such as the URL, HTTP method, headers, query parameters, and body data.
 res (Response Object): Represents the outgoing HTTP response. You use it to set the status
code, headers, and body of the response.
 server (Server Object): Represents the HTTP server that listens for incoming requests and
manages responses. It's created using http.createServer() and listens on a specified port.
Together, these objects form the core functionality for handling HTTP requests and responses in
Node.js.

IMPLEMENTING HTTP CLIENTS AND SERVERS IN NODE.JS

In Node.js, you can implement both HTTP servers (to handle incoming requests) and HTTP
clients (to make requests to other servers). Node.js provides built-in modules such as http and https
to implement both.

1. Implementing an HTTP Server in Node.js

An HTTP server listens for incoming HTTP requests from clients and sends responses. The http
module allows you to create a simple server by using the http.createServer() method.

Here is a basic example of creating an HTTP server that responds with "Hello, World!" for every
request.

Example: Creating an HTTP Server

const http = require('http');

// Create an HTTP server


const server = http.createServer((req, res) => {
// Set status code and headers for the response
res.statusCode = 200; // HTTP 200 OK
res.setHeader('Content-Type', 'text/plain'); // Set content type as plain text

// Write the response body


res.end('Hello, World!');
});

// Make the server listen on port 3000


server.listen(3000, () => {
console.log('Server is running at http://localhost:3000/');
});

Explanation:

 http.createServer(callback): Creates an HTTP server and the callback is invoked whenever


a request is received.
 req (Request): Contains information about the incoming request (e.g., URL, headers, HTTP
method).
 res (Response): Used to send the response back to the client (e.g., setting status code,
headers, and body).
 server.listen(3000): Tells the server to start listening on port 3000.

2. Implementing an HTTP Client in Node.js

An HTTP client in Node.js makes requests to other servers (e.g., sending a GET request to an API
or making a POST request). You can use the http module or the https module, depending on
whether you're connecting to a secure or non-secure server.

Example: Creating an HTTP Client to Make a GET Request


In this example, we will create an HTTP client that makes a GET request to a server.

const http = require('http');

// Define the options for the HTTP GET request


const options = {
hostname: 'jsonplaceholder.typicode.com', // The server URL
path: '/todos/1', // Path of the resource we want to fetch
method: 'GET', // HTTP method
};

// Make the HTTP request


const req = http.request(options, (res) => {
let data = '';

// Collect the response data


res.on('data', (chunk) => {
data += chunk;
});

// Once the response is complete, process the data


res.on('end', () => {
console.log('Response:', data); // Log the response body
});
});

// Handle request errors


req.on('error', (err) => {
console.error('Error:', err.message);
});

// End the request (i.e., actually send it)


req.end();

Explanation:

 http.request(options, callback): Makes an HTTP request to the server. The options object
specifies the hostname, path, and method (GET in this case).
 res.on('data', callback): Listens for chunks of data that the server sends back in response.
 res.on('end', callback): Fires when the entire response is received.
 req.end(): Sends the request to the server.

Example: Making a POST Request with HTTP Client

You can also use the HTTP client to send data using the POST method.

const http = require('http');

// Data to be sent in the POST request


const postData = JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1,
});

// Define the options for the HTTP POST request


const options = {
hostname: 'jsonplaceholder.typicode.com',
path: '/posts',
method: 'POST',
headers: {
'Content-Type': 'application/json', // Set content type to JSON
'Content-Length': Buffer.byteLength(postData), // Set the length of the content
},
};

// Make the HTTP request


const req = http.request(options, (res) => {
let data = '';

// Collect the response data


res.on('data', (chunk) => {
data += chunk;
});

// Once the response is complete, process the data


res.on('end', () => {
console.log('Response:', data); // Log the response body
});
});

// Handle request errors


req.on('error', (err) => {
console.error('Error:', err.message);
});

// Send the POST data


req.write(postData);
req.end();

Explanation:

 method: 'POST': The HTTP method used to send data to the server.
 headers: The Content-Type header tells the server that the body of the request contains
JSON data. The Content-Length header tells the server the length of the data being sent.
 req.write(postData): Writes the data to be sent in the body of the request.
 req.end(): Ends the request, sending the data.

3. Handling Errors in HTTP Client

When making requests with the HTTP client, it is important to handle errors. Errors can occur due
to network issues, timeouts, or server unavailability.

Example: Handling Request Errors

const http = require('http');


const options = {
hostname: 'jsonplaceholder.typicode.com',
path: '/nonexistent', // Invalid path to simulate an error
method: 'GET',
};

const req = http.request(options, (res) => {


let data = '';

res.on('data', (chunk) => {


data += chunk;
});

res.on('end', () => {
console.log('Response:', data);
});
});

req.on('error', (err) => {


console.error('Request failed:', err.message); // Log error message
});

req.end();

4. Using https for Secure Connections

If you are making requests to a secure server (e.g., https:// URLs), you should use the https module
instead of the http module. The usage is the same, but it works for HTTPS connections.

Example: HTTPS Client

const https = require('https');

// Define the options for the HTTPS GET request


const options = {
hostname: 'jsonplaceholder.typicode.com',
path: '/todos/1',
method: 'GET',
};

// Make the HTTPS request


const req = https.request(options, (res) => {
let data = '';

res.on('data', (chunk) => {


data += chunk;
});

res.on('end', () => {
console.log('Response:', data);
});
});
req.on('error', (err) => {
console.error('Error:', err.message);
});

req.end();

5. Using External Libraries for HTTP Requests

For more advanced HTTP client functionality (e.g., handling cookies, retries, redirects), you might
want to use external libraries like axios, node-fetch, or request (deprecated).

Example: Using axios (External HTTP Client Library)

const axios = require('axios');

axios.get('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
console.log('Response:', response.data); // Log the response data
})
.catch(error => {
console.error('Error:', error.message);
});

Conclusion

In Node.js, you can build both HTTP clients and servers using the built-in http and https modules:

 HTTP Server: Use http.createServer() to create a server that listens for incoming requests
and sends responses.
 HTTP Client: Use http.request() or https.request() to send requests to other servers and
handle their responses.
 POST Requests: Send data in the body of the request using req.write() for POST, PUT, or
PATCH methods.

For more advanced scenarios, you may want to explore external libraries like axios, which
simplifies making HTTP requests and handling responses.

IMPLEMENTING HTTPS SERVERS AND CLIENTS

In Node.js, you can implement both HTTPS servers (to handle secure incoming requests) and
HTTPS clients (to make secure requests to other servers). This is accomplished using the https
module, which provides the ability to create secure servers and clients that use SSL/TLS encryption.

1. Implementing an HTTPS Server in Node.js

To implement an HTTPS server in Node.js, you need an SSL/TLS certificate. These certificates are
used to encrypt the communication between the server and the client.

Prerequisites:
1. An SSL certificate (.crt) and a private key (.key). You can generate these using tools like
openssl, or use a service to obtain one.
2. These files will be used to configure the HTTPS server.

Example: Creating an HTTPS Server

const https = require('https');


const fs = require('fs');

// Read the SSL certificate and private key


const options = {
key: fs.readFileSync('path/to/private-key.key'), // Path to private key
cert: fs.readFileSync('path/to/certificate.crt'), // Path to SSL certificate
ca: fs.readFileSync('path/to/ca-certificate.crt'), // (Optional) Path to CA certificate
};

// Create the HTTPS server


const server = https.createServer(options, (req, res) => {
// Set the status code and content type
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');

// Write the response body


res.end('Hello, Secure World!');
});

// Make the server listen on port 3000


server.listen(3000, () => {
console.log('HTTPS server is running at https://localhost:3000/');
});

Explanation:

 SSL/TLS Certificates: The key, cert, and optionally ca are used to configure the HTTPS
server. These files contain the server’s private key, certificate, and optionally the CA
certificate, respectively.
o key: The server's private key.

o cert: The server's public certificate.

o ca: The certificate authority's certificate (if needed).

 https.createServer(options, callback): Creates an HTTPS server with the provided


SSL/TLS options.
 Server listens on HTTPS port (3000): The server is configured to listen on port 3000 for
secure HTTPS connections.

2. Implementing an HTTPS Client in Node.js

An HTTPS client can be used to make secure requests to remote HTTPS servers. The https module
in Node.js is used to make these requests.

Example: Creating an HTTPS Client to Make a GET Request


const https = require('https');

// Define the options for the HTTPS GET request


const options = {
hostname: 'jsonplaceholder.typicode.com', // Server URL
path: '/todos/1', // Path of the resource we want to fetch
method: 'GET', // HTTP method
};

// Make the HTTPS request


const req = https.request(options, (res) => {
let data = '';

// Collect the response data


res.on('data', (chunk) => {
data += chunk;
});

// Once the response is complete, process the data


res.on('end', () => {
console.log('Response:', data); // Log the response body
});
});

// Handle request errors


req.on('error', (err) => {
console.error('Error:', err.message);
});

// End the request (i.e., actually send it)


req.end();

Explanation:

 https.request(options, callback): Sends an HTTPS request to the specified server. The


options object contains the server details, such as the hostname, path, and HTTP method.
 req.end(): Sends the request.
 res.on('data', callback): Collects chunks of data from the server’s response.
 res.on('end', callback): Fires when the entire response has been received.
 req.on('error', callback): Catches any errors that occur during the request (e.g., connection
failure).

3. Handling SSL/TLS Options in HTTPS Client

In some cases, you might need to configure the HTTPS client to accept certain SSL/TLS certificates
(e.g., when dealing with self-signed certificates). You can pass SSL options in the https.request()
function.

Example: Using HTTPS Client with Custom SSL/TLS Certificates

const https = require('https');


const fs = require('fs');
// Define the options for the HTTPS request with custom SSL certificate
const options = {
hostname: 'example.com',
path: '/secure-endpoint',
method: 'GET',
cert: fs.readFileSync('path/to/certificate.crt'), // Client's SSL certificate
key: fs.readFileSync('path/to/private-key.key'), // Client's private key
ca: fs.readFileSync('path/to/ca-certificate.crt'), // Certificate authority's certificate
rejectUnauthorized: false, // Set to false if you want to allow self-signed certificates
};

// Make the HTTPS request with custom certificates


const req = https.request(options, (res) => {
let data = '';

// Collect the response data


res.on('data', (chunk) => {
data += chunk;
});

res.on('end', () => {
console.log('Response:', data); // Log the response body
});
});

// Handle request errors


req.on('error', (err) => {
console.error('Error:', err.message);
});

// End the request


req.end();

Explanation:

 cert: The client's certificate is sent as part of the request.


 key: The client's private key is used to authenticate the client to the server.
 ca: The certificate authority's certificate is used to verify the server’s certificate.
 rejectUnauthorized: false: This option tells the client not to reject connections to servers
with invalid certificates (e.g., self-signed certificates).

4. Self-Signed Certificates

If you are using self-signed certificates for local development or testing, you may need to add an
additional option to the client (rejectUnauthorized: false) to allow the connection, as self-signed
certificates are not trusted by default.

Example: Using Self-Signed Certificates (HTTPS Client)

const https = require('https');


const fs = require('fs');
// Define the options for the HTTPS client with self-signed certificate
const options = {
hostname: 'localhost',
port: 3000,
path: '/',
method: 'GET',
ca: fs.readFileSync('path/to/self-signed-ca.crt'), // Path to self-signed CA certificate
rejectUnauthorized: false, // Allow self-signed certificates
};

// Make the HTTPS request


const req = https.request(options, (res) => {
let data = '';

res.on('data', (chunk) => {


data += chunk;
});

res.on('end', () => {
console.log('Response:', data);
});
});

// Handle request errors


req.on('error', (err) => {
console.error('Error:', err.message);
});

req.end();

5. Using HTTPS Server with Node.js (For Local Development)

If you want to test an HTTPS server locally with a self-signed certificate, you can generate one
using OpenSSL and then configure your HTTPS server accordingly.

Example: Creating a Self-Signed Certificate Using OpenSSL

To create a self-signed certificate for local testing, you can run the following OpenSSL command:

openssl req -x509 -newkey rsa:4096 -keyout private-key.key -out certificate.crt -days 365

This will generate:

 private-key.key: Your private key.


 certificate.crt: Your self-signed certificate.

Example: Using a Self-Signed Certificate with HTTPS Server

const https = require('https');


const fs = require('fs');

// Read the self-signed certificate and private key


const options = {
key: fs.readFileSync('private-key.key'),
cert: fs.readFileSync('certificate.crt'),
};

// Create the HTTPS server


const server = https.createServer(options, (req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, Secure World with Self-Signed Certificate!');
});

// Listen on port 3000


server.listen(3000, () => {
console.log('HTTPS server is running at https://localhost:3000/');
});

Conclusion

 HTTPS Server: Use the https module with an SSL/TLS certificate and private key to create
a secure server.
 HTTPS Client: Use the https module to make secure requests to HTTPS servers, passing
SSL/TLS certificates if needed.
 Self-Signed Certificates: If you're using self-signed certificates for local development,
configure both the client and server to allow them (e.g., rejectUnauthorized: false for the
client).

For more advanced use cases, you can also explore features like mutual TLS (client-side
authentication) and configure additional SSL options to enhance security.

USING ADDITIONAL NODE.JS MODULES-USING THE OS MODULE

The os module in Node.js provides a number of operating system-related utility methods that can be
helpful in retrieving information about the system, including CPU, memory, and network-related
data. It's a built-in module, so you don’t need to install anything extra to use it.

Here are some of the commonly used methods in the os module and how you can use them:

1. Getting Information About the System

1.1. os.platform()

This method returns a string identifying the operating system platform. For example, it could return
'darwin' for macOS, 'linux' for Linux, or 'win32' for Windows.

const os = require('os');
console.log('Platform:', os.platform());

1.2. os.arch()
This method returns a string identifying the architecture of the operating system. It could return
'x64', 'arm', 'ia32', etc.

console.log('Architecture:', os.arch());

1.3. os.hostname()

Returns the hostname of the operating system.

console.log('Hostname:', os.hostname());

1.4. os.type()

This method returns a string identifying the operating system name (e.g., 'Linux', 'Darwin', or
'Windows_NT').

console.log('OS Type:', os.type());

1.5. os.release()

Returns the operating system's release version.

console.log('OS Release:', os.release());

1.6. os.uptime()

Returns the system uptime in seconds (how long the system has been running).

console.log('System Uptime:', os.uptime(), 'seconds');

2. Getting Information About System Memory

2.1. os.totalmem()

Returns the total amount of system memory (in bytes).

console.log('Total Memory:', os.totalmem(), 'bytes');

2.2. os.freemem()

Returns the amount of free system memory (in bytes).

console.log('Free Memory:', os.freemem(), 'bytes');

2.3. os.cpus()

Returns an array of objects containing information about each logical CPU core. Each object
contains details like model, speed, and times spent in user, system, and idle modes.

console.log('CPU Info:', os.cpus());

3. Getting Network Interfaces Information

3.1. os.networkInterfaces()
Returns an object containing network interfaces that are available on the system. This is useful for
retrieving IP addresses and other network-related data.

console.log('Network Interfaces:', os.networkInterfaces());

Example output might look like this:

{
"eth0": [
{
"address": "192.168.1.10",
"netmask": "255.255.255.0",
"family": "IPv4",
"mac": "00:1a:2b:3c:4d:5e",
"internal": false,
"cidr": "192.168.1.10/24"
}
],
"lo0": [
{
"address": "127.0.0.1",
"netmask": "255.0.0.0",
"family": "IPv4",
"mac": "00:00:00:00:00:00",
"internal": true,
"cidr": "127.0.0.1/8"
}
]
}

4. Getting User Information

4.1. os.userInfo()

This method returns an object with the current user's information (e.g., username, home directory,
shell).

console.log('User Info:', os.userInfo());

Example output:

{
"username": "your-username",
"uid": 501,
"gid": 20,
"shell": "/bin/bash",
"homedir": "/Users/your-username"
}

5. Getting System Temporary Directory

5.1. os.tmpdir()

Returns the operating system’s default directory for temporary files.


console.log('Temp Directory:', os.tmpdir());

6. Getting System Endianness

6.1. os.endianness()

Returns the endianness of the system’s CPU. It can return 'BE' for big-endian or 'LE' for little-
endian.

console.log('Endianness:', os.endianness());

7. Getting System Load Average

7.1. os.loadavg()

Returns an array with three load averages for the last 1, 5, and 15 minutes. This is usually a measure
of the system's load and how many processes are in the queue for CPU.

console.log('Load Average:', os.loadavg());

Example output:

[ 0.72, 0.58, 0.44 ]

8. Getting System Constants

8.1. os.constants

This provides system constants such as signals, file system flags, and error codes.

Example usage:

console.log('Signal for SIGHUP:', os.constants.signals.SIGHUP);

Example of Using os Module Together

Here’s an example that combines some of the above methods to print a summary of system
information:

const os = require('os');

console.log('Platform:', os.platform());
console.log('Architecture:', os.arch());
console.log('Hostname:', os.hostname());
console.log('OS Type:', os.type());
console.log('OS Release:', os.release());
console.log('Uptime:', os.uptime(), 'seconds');
console.log('Total Memory:', os.totalmem(), 'bytes');
console.log('Free Memory:', os.freemem(), 'bytes');
console.log('CPUs:', os.cpus());
console.log('Network Interfaces:', os.networkInterfaces());
console.log('User Info:', os.userInfo());
console.log('Temporary Directory:', os.tmpdir());
console.log('Endianness:', os.endianness());
console.log('Load Average:', os.loadavg());

Conclusion

The os module is a valuable tool in Node.js for interacting with and retrieving system-related
information. It's commonly used when you need to gather data on the environment your application
is running on, such as CPU details, memory usage, and networking information.

USING THE UTIL MODULE

The util module in Node.js provides a set of utility functions that help in working with objects,
functions, and other built-in JavaScript types. It can be quite useful for tasks such as inspecting
objects, formatting strings, and using inheritance, among other things.

Here’s an overview of the commonly used functions in the util module:

1. util.format()

The util.format() function is similar to printf in other languages like C. It allows you to format
strings with placeholders, which are then replaced by the provided arguments.

Example:

const util = require('util');

const formattedString = util.format('Hello, %s!', 'World');


console.log(formattedString); // Output: Hello, World!

You can use multiple placeholders, like %s for strings, %d for integers, %j for JSON, and more.

Example with multiple placeholders:

const name = 'Alice';


const age = 30;

const formattedString = util.format('%s is %d years old', name, age);


console.log(formattedString); // Output: Alice is 30 years old

2. util.inspect()

The util.inspect() function is used to convert an object to a string representation. It is particularly


useful when you want to inspect an object with a deep structure or with circular references.

Example:

const util = require('util');

const obj = {
name: 'John',
age: 25,
hobbies: ['reading', 'coding'],
};

console.log(util.inspect(obj, { showHidden: false, depth: null, colors: true }));

Options for util.inspect():

 showHidden: If true, it will include non-enumerable properties.


 depth: How many levels of nested objects should be inspected. null means unlimited depth.
 colors: If true, it adds color to the output (useful in the terminal).

3. util.promisify()

The util.promisify() function converts callback-based functions into ones that return a Promise. This
is especially helpful when you want to use async/await syntax with legacy callback-based APIs.

Example:

Suppose you have a function that uses callbacks (like fs.readFile()):

const fs = require('fs');
const util = require('util');

// Convert fs.readFile to return a promise


const readFilePromise = util.promisify(fs.readFile);

async function readFile() {


try {
const data = await readFilePromise('example.txt', 'utf8');
console.log(data);
} catch (error) {
console.error('Error reading file:', error);
}
}

readFile();

This makes fs.readFile() return a promise instead of using a callback, allowing you to use
async/await with it.

4. util.callbackify()

util.callbackify() is the opposite of promisify(). It converts a function that returns a Promise into a
function that uses a callback. This can be useful when you're working with APIs that expect
callback-based functions.

Example:

const util = require('util');

async function getUserData(userId) {


// Simulating an asynchronous operation with Promise
return new Promise((resolve, reject) => {
if (userId === 1) {
resolve({ userId, name: 'John' });
} else {
reject(new Error('User not found'));
}
});
}

// Convert the Promise-based function into a callback-based one


const callbackifiedGetUserData = util.callbackify(getUserData);

// Using the callbackified version


callbackifiedGetUserData(1, (err, data) => {
if (err) {
console.error(err);
} else {
console.log(data); // Output: { userId: 1, name: 'John' }
}
});

5. util.inherits()

The util.inherits() function is used for setting up inheritance in Node.js. It allows one constructor
function to inherit from another.

Example:

const util = require('util');

// Base class (constructor function)


function Animal(name) {
this.name = name;
}

Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};

// Derived class (constructor function)


function Dog(name) {
Animal.call(this, name); // Call the base class constructor
}

// Set up inheritance
util.inherits(Dog, Animal);

// Now Dog instances inherit from Animal


const dog = new Dog('Rex');
dog.speak(); // Output: Rex makes a sound

Here, Dog inherits from Animal. The Dog class can now access methods from Animal.

6. util.deprecate()
The util.deprecate() function allows you to mark a function as deprecated, and it will show a
warning when the function is called.

Example:

const util = require('util');

// A deprecated function
function oldFunction() {
console.log('This function is deprecated');
}

// Wrapping the function with deprecation warning


const deprecatedFunction = util.deprecate(oldFunction, 'oldFunction is deprecated and will be
removed in the future');

// Calling the deprecated function


deprecatedFunction();

This will print a warning when the function is called, alerting the developer that the function is
deprecated.

7. util.isArray()

This method checks if the given value is an array. It returns true if the value is an array, otherwise
false.

const util = require('util');

console.log(util.isArray([1, 2, 3])); // Output: true


console.log(util.isArray({})); // Output: false

8. util.isError()

This method checks if the value is an instance of Error. It returns true if the value is an error,
otherwise false.

const util = require('util');

const err = new Error('Something went wrong');


console.log(util.isError(err)); // Output: true
console.log(util.isError('Error message')); // Output: false

Example: Using Multiple util Methods Together

Here's a quick example that demonstrates multiple util methods together:

const util = require('util');

// Create an object
const obj = {
name: 'Alice',
age: 30,
greet: function() { return 'Hello, ' + this.name; },
};

// Format a string using util.format


const formattedString = util.format('Name: %s, Age: %d', obj.name, obj.age);
console.log(formattedString);

// Inspect an object using util.inspect


console.log(util.inspect(obj, { showHidden: true, depth: 2, colors: true }));

// Deprecate a function
const deprecatedFunc = util.deprecate(function() {
console.log('This is deprecated');
}, 'This function is deprecated!');

// Call the deprecated function


deprecatedFunc();

// Promisify a callback-based function


const fs = require('fs');
const readFilePromise = util.promisify(fs.readFile);
readFilePromise('example.txt', 'utf8')
.then(data => console.log(data))
.catch(err => console.error(err));

Conclusion

The util module in Node.js offers a variety of utility functions that simplify working with
asynchronous code, object inspection, formatting, inheritance, and more. It’s a powerful tool for
developers working with Node.js, especially when dealing with legacy callback-based APIs,
debugging, or working with complex data structures.

USING DNS MODULE

The dns module in Node.js provides an API for performing DNS (Domain Name System) lookups
and resolving domain names. This module is essential when you need to interact with DNS records,
perform reverse lookups, or resolve hostnames to IP addresses.

Here’s an overview of how you can use the dns module in Node.js:

1. Getting Started with the dns Module

To use the dns module, you simply need to require it:

const dns = require('dns');

2. Resolving Hostnames to IP Addresses

The dns module provides functions that allow you to resolve domain names into their respective IP
addresses. There are both callback-based and Promise-based versions of these methods.
2.1. dns.lookup()

The dns.lookup() method resolves a hostname (like 'www.google.com') to its corresponding IP


address using the system's DNS resolver.

Example:

const dns = require('dns');

// Resolving a hostname to an IP address


dns.lookup('www.google.com', (err, address, family) => {
if (err) {
console.error('Error:', err);
return;
}
console.log('Address:', address);
console.log('Family:', family); // IPV4 or IPV6
});

Example Output:

Address: 172.217.6.36
Family: 4
 address: The resolved IP address.
 family: Indicates whether the IP is IPv4 (4) or IPv6 (6).

2.2. dns.promises.lookup()

This is the Promise-based version of dns.lookup(). It returns a promise that resolves with the
address and family.

Example:

const dns = require('dns').promises;

async function resolveHostname() {


try {
const { address, family } = await dns.lookup('www.google.com');
console.log('Address:', address);
console.log('Family:', family);
} catch (err) {
console.error('Error:', err);
}
}

resolveHostname();

3. Resolving DNS Records

You can use the dns module to resolve various types of DNS records, such as A records, MX
records, and more.

3.1. dns.resolve()
The dns.resolve() method resolves a domain name into different types of records (like A, AAAA,
MX, etc.).

Example (A records):

const dns = require('dns');

// Resolving A records (IPv4 addresses) for a domain


dns.resolve('www.google.com', 'A', (err, addresses) => {
if (err) {
console.error('Error:', err);
return;
}
console.log('A Records:', addresses);
});

Example Output:

A Records: [ '172.217.6.36', '172.217.6.68' ]

3.2. dns.resolveMx()

The resolveMx() method retrieves the mail exchange (MX) records for a domain.

Example:

const dns = require('dns');

dns.resolveMx('gmail.com', (err, addresses) => {


if (err) {
console.error('Error:', err);
return;
}
console.log('MX Records:', addresses);
});

Example Output:

MX Records: [
{ exchange: 'alt1.gmail-smtp-in.l.google.com', priority: 5 },
{ exchange: 'alt2.gmail-smtp-in.l.google.com', priority: 5 },
{ exchange: 'gmail-smtp-in.l.google.com', priority: 10 },
{ exchange: 'alt3.gmail-smtp-in.l.google.com', priority: 5 },
{ exchange: 'alt4.gmail-smtp-in.l.google.com', priority: 5 }
]

3.3. dns.resolveTxt()

The resolveTxt() method retrieves the TXT records for a domain. TXT records are often used for
various domain-related configurations like SPF (Sender Policy Framework) records.

Example:

const dns = require('dns');


dns.resolveTxt('google.com', (err, records) => {
if (err) {
console.error('Error:', err);
return;
}
console.log('TXT Records:', records);
});

Example Output:

TXT Records: [ [ 'v=spf1 include:_spf.google.com ~all' ] ]

4. Reverse DNS Lookup

You can use the dns.reverse() method to get the hostnames for a given IP address. This is useful
when you want to perform a reverse DNS lookup to find out the domain associated with a given IP.

Example:

const dns = require('dns');

dns.reverse('8.8.8.8', (err, hostnames) => {


if (err) {
console.error('Error:', err);
return;
}
console.log('Hostnames:', hostnames);
});

Example Output:

Hostnames: [ 'dns.google' ]

5. dns.resolveSrv()

This method resolves a domain name to its SRV (Service) records, which are used to define the
location of servers for specified services.

Example:

const dns = require('dns');

dns.resolveSrv('_sip._tcp.google.com', (err, addresses) => {


if (err) {
console.error('Error:', err);
return;
}
console.log('SRV Records:', addresses);
});

Example Output:

SRV Records: [
{ priority: 10, weight: 60, port: 5060, name: 'sipserver.google.com' }
]

6. dns.resolveNs()

The resolveNs() method retrieves the nameserver (NS) records for a domain.

Example:

const dns = require('dns');

dns.resolveNs('google.com', (err, addresses) => {


if (err) {
console.error('Error:', err);
return;
}
console.log('NS Records:', addresses);
});

Example Output:

NS Records: [ 'ns1.google.com', 'ns2.google.com', 'ns3.google.com', 'ns4.google.com' ]

7. dns.resolveCname()

The resolveCname() method resolves a CNAME (Canonical Name) record, which maps an alias
domain name to the canonical domain name.

Example:

const dns = require('dns');

dns.resolveCname('www.google.com', (err, addresses) => {


if (err) {
console.error('Error:', err);
return;
}
console.log('CNAME Records:', addresses);
});

Example Output:

CNAME Records: [ 'www.l.google.com' ]

8. dns.lookupService()

The dns.lookupService() method performs a reverse lookup to get the service for a specific IP
address and port.

Example:

const dns = require('dns');

dns.lookupService('8.8.8.8', 53, (err, hostname, service) => {


if (err) {
console.error('Error:', err);
return;
}
console.log('Hostname:', hostname);
console.log('Service:', service);
});

Example Output:

Hostname: dns.google
Service: domain

9. Using Promises with DNS Methods

Node.js DNS methods also support promise-based versions for cleaner asynchronous code using
async/await.

Here’s an example using dns.promises for resolving MX records:

const dns = require('dns').promises;

async function resolveMX() {


try {
const mxRecords = await dns.resolveMx('gmail.com');
console.log('MX Records:', mxRecords);
} catch (err) {
console.error('Error:', err);
}
}

resolveMX();

Conclusion

The dns module in Node.js provides a rich set of methods to interact with DNS and perform domain
name resolution, reverse lookups, and retrieve various DNS record types. It supports both callback
and promise-based patterns, making it flexible for handling asynchronous operations.

This module is especially useful when building networked applications, setting up custom DNS
queries, or diagnosing DNS issues.

USING THE CRYPTO MODULE

The crypto module in Node.js provides a set of cryptographic functionalities that allow you to
perform tasks such as hashing, encryption, decryption, HMACs (Hash-based Message
Authentication Codes), and more. It's essential when building secure applications that need to
handle sensitive data.

1. Getting Started with the crypto Module

To use the crypto module in Node.js, you can simply require it like this:
const crypto = require('crypto');

2. Creating Hashes

Hashing is the process of converting data into a fixed-length string, typically used for storing
passwords or verifying data integrity. The crypto module supports several hashing algorithms like
SHA-256, SHA-512, MD5, etc.

Example: Creating a Hash

const crypto = require('crypto');

// Create a SHA-256 hash of a string


const hash = crypto.createHash('sha256');
hash.update('Hello, World!');
const result = hash.digest('hex'); // 'hex' gives a hexadecimal output

console.log(result); // Example output:


'a591a6d40bf420404a011733cfb7b190d62c65bf0bcda038098a4fe5a6fcfe5f'

3. Creating HMAC (Hash-based Message Authentication Code)

HMAC is used to verify both the data integrity and authenticity of a message. It uses a
cryptographic key along with a hash function.

Example: Creating an HMAC

const crypto = require('crypto');

const secret = 'mysecretkey';


const message = 'This is a secret message';

const hmac = crypto.createHmac('sha256', secret);


hmac.update(message);
const hmacResult = hmac.digest('hex'); // Returns the HMAC in hexadecimal format

console.log(hmacResult); // Example output:


'e5ba9283f16ab28504ed9e99f7b2800a54a11802fc1a4609d922f2e3b6a6bba1'

4. Encrypting and Decrypting Data

The crypto module can be used to perform symmetric encryption (using the same key for both
encryption and decryption) and asymmetric encryption (using a pair of public and private keys).

4.1. Symmetric Encryption (AES)

AES (Advanced Encryption Standard) is a symmetric encryption algorithm. Both the encryption
and decryption use the same key.

Example: Encrypting with AES


const crypto = require('crypto');

// Encrypt data using AES-256-CBC


const algorithm = 'aes-256-cbc';
const password = 'password123'; // You should use a strong password/key
const iv = crypto.randomBytes(16); // Generate a random initialization vector
const key = crypto.scryptSync(password, 'salt', 32); // Generate a key from the password

const cipher = crypto.createCipheriv(algorithm, key, iv);


let encrypted = cipher.update('Hello, World!', 'utf8', 'hex');
encrypted += cipher.final('hex');

console.log('Encrypted:', encrypted); // Example output: '2c6f91599156d92605e027f2b279232f'

Example: Decrypting with AES


const crypto = require('crypto');

// Decrypt data using AES-256-CBC


const algorithm = 'aes-256-cbc';
const password = 'password123';
const iv = Buffer.from('randomivfromencryption', 'hex'); // The same IV used during encryption
const key = crypto.scryptSync(password, 'salt', 32);

const decipher = crypto.createDecipheriv(algorithm, key, iv);


let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');

console.log('Decrypted:', decrypted); // Output: 'Hello, World!'

4.2. Asymmetric Encryption (RSA)

RSA is a type of asymmetric encryption, where a public key is used for encryption, and a private
key is used for decryption.

Example: Encrypting and Decrypting Data with RSA


1. Generate Keys (this step should ideally be done in advance)

openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048


openssl rsa -pubout -in private.pem -out public.pem
2. Encrypting with the Public Key

const crypto = require('crypto');


const fs = require('fs');

// Read the public key


const publicKey = fs.readFileSync('public.pem', 'utf8');

// Encrypt the data using the public key


const data = 'Hello, this is a secret message!';
const encryptedData = crypto.publicEncrypt(publicKey, Buffer.from(data));

console.log('Encrypted data:', encryptedData.toString('base64')); // Example output:


'MIIBIjANBgkqh...'
3. Decrypting with the Private Key

const crypto = require('crypto');


const fs = require('fs');

// Read the private key


const privateKey = fs.readFileSync('private.pem', 'utf8');
// Decrypt the data using the private key
const decryptedData = crypto.privateDecrypt(privateKey, Buffer.from(encryptedData, 'base64'));

console.log('Decrypted data:', decryptedData.toString('utf8')); // Output: 'Hello, this is a secret


message!'

5. Generating Random Bytes

The crypto module can be used to generate random data for various purposes like generating keys,
salts, or nonces.

Example: Generating Random Bytes

const crypto = require('crypto');

// Generate 16 random bytes


const randomBytes = crypto.randomBytes(16);
console.log(randomBytes.toString('hex')); // Example output:
'f1b35d2a8a98483a92a30297dfc98b39'

You can also use the crypto.randomInt() method to generate a random integer.

const crypto = require('crypto');

// Generate a random integer between 0 and 100


const randomInt = crypto.randomInt(0, 100);
console.log(randomInt); // Example output: 57

6. Key Derivation with PBKDF2

PBKDF2 (Password-Based Key Derivation Function 2) is used to securely derive a key from a
password, making it more resistant to attacks like brute-forcing.

Example: Using PBKDF2 for Key Derivation

const crypto = require('crypto');

// Derive a key from a password using PBKDF2


const password = 'supersecretpassword';
const salt = crypto.randomBytes(16); // Random salt
const iterations = 100000; // Number of iterations
const keyLength = 32; // Length of the generated key
const algorithm = 'sha256'; // Hash algorithm

crypto.pbkdf2(password, salt, iterations, keyLength, algorithm, (err, derivedKey) => {


if (err) throw err;
console.log('Derived key:', derivedKey.toString('hex'));
});

7. Signatures and Verification

The crypto module allows you to sign data using a private key and verify it using a public key,
which is essential for ensuring data authenticity and integrity.
Example: Signing Data

const crypto = require('crypto');


const fs = require('fs');

// Read the private key


const privateKey = fs.readFileSync('private.pem', 'utf8');

// Sign the data with the private key


const data = 'This is a message to be signed.';
const sign = crypto.createSign('SHA256');
sign.update(data);
const signature = sign.sign(privateKey, 'base64');

console.log('Signature:', signature);

Example: Verifying a Signature

const crypto = require('crypto');


const fs = require('fs');

// Read the public key


const publicKey = fs.readFileSync('public.pem', 'utf8');

// Verify the signature using the public key


const verify = crypto.createVerify('SHA256');
verify.update(data);
const isVerified = verify.verify(publicKey, signature, 'base64');

console.log('Signature verified:', isVerified); // Output: true or false

8. Stream-Based Encryption

For larger data (such as encrypting/decrypting files), you can use streams to perform encryption in
chunks without loading the entire file into memory.

Example: Encrypting a File Using Streams

const fs = require('fs');
const crypto = require('crypto');

const algorithm = 'aes-256-cbc';


const password = 'strongpassword';
const iv = crypto.randomBytes(16);
const key = crypto.scryptSync(password, 'salt', 32);

const input = fs.createReadStream('input.txt');


const output = fs.createWriteStream('encrypted.txt');

const cipher = crypto.createCipheriv(algorithm, key, iv);

input.pipe(cipher).pipe(output);

Example: Decrypting a File Using Streams

const fs = require('fs');
const crypto = require('crypto');

const algorithm = 'aes-256-cbc';


const password = 'strongpassword';
const iv = Buffer.from('ivusedduringencryption', 'hex');
const key = crypto.scryptSync(password, 'salt', 32);

const input = fs.createReadStream('encrypted.txt');


const output = fs.createWriteStream('decrypted.txt');

const decipher = crypto.createDecipheriv(algorithm, key, iv);

input.pipe(decipher).pipe(output);

Conclusion

The crypto module in Node.js provides a wide range of cryptographic functions for hashing,
encryption, signing, key derivation, and more. It's essential for building secure applications,
handling sensitive data like passwords, and implementing encryption/decryption mechanisms.

You might also like