// Methods to send the response
res.writeHead(200, { 'Content-Type': 'text/html' }); // Set status and headers
res.write('Some content'); // Write to body (can call multiple times)
res.end('Final content'); // End the response
Manual Routing
Without a framework, you handle routing manually by checking req.url:
// routing.js
const http = require('http');
const server = http.createServer((req, res) => {
// Check the URL and method
if (req.url === '/' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('
This is a lot of code just to serve files. Express does this in one line:
app.use(express.static('public')); // That's it!
This illustrates Node.js's trade-off: it's less "batteries included" and more DIY. This can be good for performance (you only include what you need) and limiting attack surface (less code = fewer vulnerabilities). But it's a double-edged sword: you can easily forget things that Apache handles automatically.
Reading the Request Body (POST Data)
POST data arrives in chunks. You must collect them:
const server = http.createServer((req, res) => {
if (req.method === 'POST') {
let body = '';
// Collect data chunks
req.on('data', chunk => {
body += chunk.toString();
});
// All data received
req.on('end', () => {
console.log('Received:', body);
res.end('Data received');
});
}
});
Process Management: What Happens When It Crashes?
Unlike PHP running under Apache (where Apache handles process management), if your Node.js server crashes, it's dead. Nobody restarts it automatically.
# Start your server
$ node server.js
Server running on port 3000...
# If an unhandled exception occurs...
TypeError: Cannot read property 'x' of undefined
# Server exits. No more requests are handled.
# Users see "connection refused" until you manually restart.
This is another thing Apache handles for you: if a PHP script crashes, only that request fails. Apache keeps running and handles the next request normally.
Process Managers
In production, you need a process manager to:
Automatically restart the server if it crashes
Start the server on system boot
Monitor memory usage and restart if it gets too high
Provide logging and status monitoring
PM2 is the most popular Node.js process manager:
# Install PM2 globally
$ npm install -g pm2
# Start your app with PM2
$ pm2 start server.js --name my-app
# PM2 keeps it running, restarts on crash
# View status
$ pm2 status
┌─────────┬────────┬──────────┬────────┬─────────┐
│ name │ status │ restarts │ uptime │ memory │
├─────────┼────────┼──────────┼────────┼─────────┤
│ my-app │ online │ 0 │ 2h │ 45.2mb │
└─────────┴────────┴──────────┴────────┴─────────┘
# Make it start on system boot
$ pm2 startup
$ pm2 save
Why Learn This?
You'll probably use Express (next module), not raw http. But understanding this helps you:
Appreciate what Express abstracts away
Debug issues when things go wrong
Understand Node.js's streaming/event-based nature
Write custom middleware or servers when needed
Summary
Node.js creates its own HTTP server with http.createServer()