First HTTP Server — Chai Server Banao
An HTTP server is just a program that listens for requests and sends responses.
An HTTP server is a program that runs continuously, waiting for requests from clients (browsers, mobile apps, other servers) and sending back responses. Think of it as your chai tapri:
- Server = Chai ki dukaan — hamesha khula rehta hai, customers ka wait karta hai
- Request = Customer aaya aur bola "Ek chai dena"
- Response = Chai Wala ne chai banake di
- Port = Dukaan ka address / pata (Gachibowli, 2nd cross)
- URL = Customer ka order (chai, biscuit, samosa)
- HTTP Method = Customer ka style (GET = order lena, POST = naya order dena)
HTTP stands for HyperText Transfer Protocol. It's the language that browsers and servers use to talk to each other. Every time you visit a website, your browser sends an HTTP request to a server, and the server sends back an HTTP response (usually HTML, JSON, or files).
Important: Node.js has a built-in http module. You don't need Express or any framework to create a server. The http module is like your basic chai tapri setup — a stove, a kettle, and some cups. Express is like Paradise Restaurant — fancier, but built on the same foundation.
In this chapter, we'll use the raw http module to understand how servers really work under the hood. In later chapters, we'll upgrade to Express.
The http.createServer() method is how you open your chai tapri. It creates a server that listens for HTTP requests.
Minimal server — just 7 lines:
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Chai piyoge bhai? ☕\n');
});
server.listen(3000, () => {
console.log('☕ Chai server chal raha hai on http://localhost:3000');
});
Let's break this down:
require('http')— Node.js ka built-in http module import karohttp.createServer(callback)— Ek naya server banao. Callback har request pe chalta haires.writeHead(200, ...)— Response ka status code batao (200 = OK, sab theek hai)res.end('Chai piyoge?')— Response bhejo aur connection band karoserver.listen(3000)— Server ko port 3000 pe sunna shuru karo
How to run it:
node server.js
# Output: ☕ Chai server chal raha hai on http://localhost:3000
# Server is now running. Open http://localhost:3000 in your browser.
# Press Ctrl+C to stop the server.
After running, visit http://localhost:3000 and you'll see "Chai piyoge bhai? ☕" in your browser. That's your first web server! 🎉
The callback function in http.createServer() receives two objects: req (request) and res (response). Think of them as:
- req (Request) = Jo customer ne kaha (order, customer ka naam, kaisa aaya)
- res (Response) = Jo chai wale ne diya (chai ka cup, kaise diya, status)
Important properties of req (the customer's order):
const server = http.createServer((req, res) => {
// 🧑 Customer ka order
console.log('Method:', req.method); // GET, POST, PUT, DELETE
console.log('URL:', req.url); // '/', '/menu', '/order/123'
console.log('Headers:', req.headers); // Browser info, cookies, etc.
// 🛠 Now process the request
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>Chai piyoge?</h1>');
});
Important methods of res (the chai wala's response):
// res.writeHead(statusCode, headers) — Status + headers bhejo
res.writeHead(200, { 'Content-Type': 'text/html' });
// res.write(data) — Data likho (multiple calls allowed)
res.write('<h1>Chai ready!</h1>');
res.write('<p>100 rupaiya</p>');
// res.end(data) — Data likho aur connection band karo
res.end();
Common HTTP Status Codes (Chai Tapri Edition):
- 200 OK = "Chai mil jayegi, sab theek hai" ✅
- 201 Created = "Naya order create ho gaya" 🆕
- 301 Moved = "Dukaan ab naye jagah pe hai (redirect)" 🔀
- 400 Bad Request = "Bhai, order sahi se do" 🤨
- 404 Not Found = "Yeh cheez hamare menu mein nahi hai" ❌
- 500 Internal Server Error = "Chai wala beemar hai, kitchen mein aag lag gayi" 🔥
Content-Type ka magic:
res.writeHead(200, { 'Content-Type': 'text/html' }); // Browser HTML samjhega
res.writeHead(200, { 'Content-Type': 'application/json' }); // JSON data
res.writeHead(200, { 'Content-Type': 'text/plain' }); // Simple text
Content-Type browser ko batata hai ki response kaise treat karna hai. HTML ko render kare, JSON ko parse kare, text ko seedha dikhaye.
Now let's build something useful — a server that serves different content based on the URL. Like a chai tapri menu: different items for different orders.
Simple routing — Chai Tapri Menu Server:
const http = require('http');
const server = http.createServer((req, res) => {
const { method, url } = req;
// Basic routing based on URL
if (url === '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>☕ Chai Tapri</h1><p>Menu dekho: /menu, Order karo: /order</p>');
} else if (url === '/menu') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
chai: { price: 10, type: 'ginger, elaichi, special' },
biscuit: { price: 5, type: 'parle, marie, good day' },
samosa: { price: 15, type: 'aloo' }
}));
} else if (url === '/order' && method === 'POST') {
res.writeHead(201, { 'Content-Type': 'text/plain' });
res.end('Order placed! Chai aa rahi hai... ☕');
} else {
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end('<h1>404 — Yeh item menu mein nahi hai! ❌</h1>');
}
});
server.listen(3000, () => console.log('☕ Chai Tapri open on http://localhost:3000'));
Understanding the routing logic:
req.urltells you which path the client requested (/,/menu,/order)req.methodtells you the HTTP method (GET = read, POST = create)- Different URLs can return different content types (HTML, JSON, plain text)
- If no route matches, return 404 — never let the client hang!
Test it:
# Test in terminal using curl:
curl http://localhost:3000 # GET / → Home page
curl http://localhost:3000/menu # GET /menu → JSON menu
curl -X POST http://localhost:3000/order # POST /order → Place order
curl http://localhost:3000/biryani # GET /biryani → 404 Not Found
This is the foundation of ALL web APIs. Express, Koa, Fastify — every framework does this same thing under the hood. They just make it prettier.
Understanding the server lifecycle is crucial. A server is not a one-time script — it's a long-running process that stays alive until you tell it to stop.
Server lifecycle phases:
const http = require('http');
// PHASE 1: Server create karo
const server = http.createServer((req, res) => {
console.log('📥 Request aaya:', req.method, req.url);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Chai mil jayegi! ☕');
});
// PHASE 2: Server ko port pe sunna shuru karo
server.listen(3000, () => {
console.log('✅ PHASE 1: Server listening on port 3000');
console.log('📌 PHASE 2: Waiting for requests...');
console.log('🛑 PHASE 3: Press Ctrl+C to stop server');
});
// PHASE 3: Graceful shutdown (when you press Ctrl+C)
process.on('SIGINT', () => {
console.log('\n🛑 Server band ho raha hai...');
server.close(() => {
console.log('👋 Chai tapri band! Phir aaiyega?');
process.exit(0);
});
});
Key lifecycle concepts:
- Start: server.listen() → Server starts listening on the port
- Running: Server is waiting for requests 24/7. Each request triggers the callback.
- Stop: Ctrl+C sends SIGINT signal. server.close() stops accepting new connections.
- Cleanup: Close database connections, clear intervals, save state before exiting.
Port conflicts — 2 dukaanein same address pe nahi khol sakte:
# Error: Port 3000 already in use
# "Address in use" error aata hai agar koi aur server 3000 pe already chal raha hai
# Solution: Kill the process or use a different port
# Find what's running on port 3000:
lsof -i :3000
# Kill it:
kill -9 <PID>
# Or use a different port when starting:
PORT=3001 node server.js
Just like two chai tapris can't have the same address in Gachibowli, two servers can't listen on the same port. Always check port availability before starting!
Production ports: In production, servers don't use 3000. They use process.env.PORT (usually 80 for HTTP, 443 for HTTPS). Always make your port configurable:
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => console.log('Server on port', PORT));Key Takeaways
- ✅ http.createServer() creates an HTTP server that listens for requests.
- ✅ req contains request data (method, url, headers). res sends the response.
- ✅ res.writeHead() sets status code and headers. res.end() sends the response.
- ✅ 200 = OK, 201 = Created, 404 = Not Found, 500 = Server Error.
- ✅ Simple routing is done by checking req.url and req.method.
- ✅ server.listen(port) starts the server. Ctrl+C or process.on('SIGINT') stops it.
- ✅ Always use process.env.PORT in production — never hardcode 3000.
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login