The Journey of an API Request
๐ญ The Story of a Digital Conversation
Imagine you're telling the story of how two programs talk to each other.
Our characters are:
The Server (index.js) - A helpful librarian managing a clothing store database The Client (pure-node-client.js) - A customer wanting to browse and buy clothes The Database (MongoDB) - The warehouse storing all the products Let's follow a single product's journey through the system!
๐ Chapter 1: The Server Wakes Up
javascript
// In index.js
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
What's happening: The server opens its doors at address 3000, like a shop putting up an "OPEN" sign. It's now ready to receive customers.
The server sets up different "departments":
Web Department: Serves HTML pages to browsers API Department: Serves JSON data to programs ๐ Chapter 2: The Client Knocks on the Door
javascript
// In pure-node-client.js
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/products',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
What's happening: The client prepares its request like writing a formal letter:
Address: localhost:3000 (where to send it) Department: /api/products (who should handle it) Type: POST (what kind of request) Format: JSON (what language to speak) ๐ Chapter 3: Creating a Product (The POST Request)
Client Side - Sending the Request:
javascript
// pure-node-client.js
async function createProduct() {
const newProduct = {
name: 'Classic Leather Jacket',
category: 'outer wear',
price: 299.99
};
const req = http.request(options, (res) => {
// Wait for response...
});
req.write(JSON.stringify(newProduct));
req.end();
}
The Journey:
Client packages the product data in a JSON "envelope" Sends it through the internet "postal service" Waits by the mailbox for a response Server Side - Receiving and Processing:
javascript
// index.js
app.post('/api/products', async (req, res) => {
try {
const { category, name, price } = req.body; // Open the envelope
const product = new Product({ category, name, price }); // Create product object
await product.save(); // Store in database
res.status(201).json({ // Send success response
success: true,
data: product
});
} catch (error) {
res.status(500).json({ success: false, error: 'Server Error' });
}
});
What happens here:
Doorbell rings - Server receives POST request at /api/products Opens envelope - Extracts product data from req.body Creates record - Makes a new Product using Mongoose Stores in warehouse - Saves to MongoDB with product.save() Sends receipt - Returns success response with the new product's ID Client Side - Receiving the Response:
javascript
// Back in pure-node-client.js
res.on('end', () => {
const result = JSON.parse(data);
if (result.success) {
console.log('โ
Created product with ID:', result.data._id);
// Product ID: 507f1f77bcf86cd799439011
}
});
The client celebrates: "Great! My jacket was added to the store with ID 507f1f77bcf86cd799439011"
๐ Chapter 4: Finding the Product (The GET Request)
Client Side - Asking for Information:
javascript
// pure-node-client.js
async function getProductById(productId) {
const options = {
hostname: 'localhost',
port: 3000,
path: `/api/products/${productId}`, // "I want product 507f1f77bcf86cd799439011"
method: 'GET'
};
http.get(options, (res) => {
// Process response...
});
}
Server Side - Finding and Returning:
javascript
// index.js
app.get('/api/products/:id', async (req, res) => {
try {
const product = await Product.findById(req.params.id); // Search warehouse
if (!product) {
return res.status(404).json({ // Not found!
success: false,
error: 'Product not found'
});
}
res.json({ success: true, data: product }); // Found it!
} catch (error) {
res.status(500).json({ success: false, error: 'Server Error' });
}
});
The process:
Client asks: "Do you have product 507f1f77bcf86cd799439011?" Server searches: Looks in MongoDB using findById() Server responds: "Yes! Here's your Classic Leather Jacket" ๐ Chapter 5: Updating the Price (The PUT Request)
Client Side - Requesting a Change:
javascript
// pure-node-client.js
async function updateProduct(productId) {
const updatedData = {
name: 'Classic Leather Jacket - SALE',
category: 'outer wear',
price: 199.99 // Reduced from 299.99
};
const req = http.request({
method: 'PUT',
path: `/api/products/${productId}`,
// ... other options
});
req.write(JSON.stringify(updatedData));
}
Server Side - Making the Change:
javascript
// index.js
app.put('/api/products/:id', async (req, res) => {
try {
const product = await Product.findByIdAndUpdate(
req.params.id, // Which product
req.body, // New data
{ new: true } // Return updated version
);
res.json({ success: true, data: product });
} catch (error) {
res.status(500).json({ success: false, error: 'Server Error' });
}
});
What's happening:
Client says: "Please change product 507f1f77bcf86cd799439011" Server updates the database record Server confirms: "Done! The jacket is now on sale for $199.99" ๐ Chapter 6: The Shopping Cart (MongoDB Aggregation)
When checking the cart total, something special happens:
javascript
// index.js
const cartTotal = await Cart.aggregate([
{
$lookup: {
from: 'products',
localField: 'productId',
foreignField: '_id',
as: 'product'
}
},
{ $unwind: '$product' },
{
$group: {
_id: null,
total: {
$sum: {
$multiply: ['$product.price', '$quantity']
}
}
}
}
]);
The aggregation pipeline - like an assembly line:
$lookup: "For each cart item, go find its matching product" $unwind: "Flatten the results so they're easier to work with" $group: "Add up all (price ร quantity) to get the total" It's like a cashier:
Scans each item in your cart ๐ Chapter 7: Deleting a Product (The DELETE Request)
Client Side - Requesting Removal:
javascript
// pure-node-client.js
async function deleteProduct(productId) {
const options = {
method: 'DELETE',
path: `/api/products/${productId}`
};
const req = http.request(options, callback);
req.end(); // No body needed for DELETE
}
Server Side - Removing from Database:
javascript
// index.js
app.delete('/api/products/:id', async (req, res) => {
try {
const product = await Product.findByIdAndDelete(req.params.id);
// Clean up: remove from any shopping carts too
await Cart.deleteMany({ productId: req.params.id });
res.json({
success: true,
data: {},
message: 'Product deleted successfully'
});
} catch (error) {
res.status(500).json({ success: false, error: 'Server Error' });
}
});
The cleanup process:
Find and delete the product Remove it from all shopping carts (cascading delete) ๐ฌ The Complete Flow Visualization