Creating HTTP Servers
NodeJS was designed for building network applications, especially web servers. The built-in http module makes it easy to create HTTP servers without any external dependencies.
Your First HTTP Server
const http = require('http');
// Create server
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World!');
});
// Start listening
server.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});
Save as server.js and run:
node server.js
Visit http://localhost:3000 in your browser!
Understanding the Request/Response Cycle
const http = require('http');
const server = http.createServer((req, res) => {
// req = incoming request from client
// res = outgoing response to client
console.log('Method:', req.method); // GET, POST, etc.
console.log('URL:', req.url); // /about, /api/users
console.log('Headers:', req.headers); // Request headers
// Send response
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end('<h1>Welcome!</h1>');
});
server.listen(3000);
Routing (Different Pages)
const http = require('http');
const server = http.createServer((req, res) => {
const { url, method } = req;
// Set content type
res.setHeader('Content-Type', 'text/html');
// Route based on URL
if (url === '/') {
res.statusCode = 200;
res.end('<h1>Home Page</h1><a href="/about">About</a>');
}
else if (url === '/about') {
res.statusCode = 200;
res.end('<h1>About Page</h1><a href="/">Home</a>');
}
else if (url === '/api/users') {
res.setHeader('Content-Type', 'application/json');
res.statusCode = 200;
res.end(JSON.stringify({ users: ['Alice', 'Bob'] }));
}
else {
res.statusCode = 404;
res.end('<h1>404 - Page Not Found</h1>');
}
});
server.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Serving JSON (API)
const http = require('http');
const server = http.createServer((req, res) => {
if (req.url === '/api/products' && req.method === 'GET') {
const products = [
{ id: 1, name: 'Laptop', price: 999 },
{ id: 2, name: 'Mouse', price: 29 },
{ id: 3, name: 'Keyboard', price: 79 }
];
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(products));
}
else {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Not found' }));
}
});
server.listen(3000);
Reading Request Body (POST Data)
const http = require('http');
const server = http.createServer((req, res) => {
if (req.url === '/api/users' && req.method === 'POST') {
let body = '';
// Collect data chunks
req.on('data', chunk => {
body += chunk.toString();
});
// When all data received
req.on('end', () => {
try {
const user = JSON.parse(body);
console.log('Received user:', user);
res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
message: 'User created',
user
}));
} catch (err) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid JSON' }));
}
});
}
else {
res.writeHead(404);
res.end('Not found');
}
});
server.listen(3000);
Test with curl:
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Alice","email":"alice@example.com"}'
Serving Static Files
const http = require('http');
const fs = require('fs').promises;
const path = require('path');
const server = http.createServer(async (req, res) => {
try {
// Remove query strings and get clean path
const filePath = path.join(__dirname, 'public', req.url);
// Read file
const content = await fs.readFile(filePath);
// Determine content type
const ext = path.extname(filePath);
const contentTypes = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'text/javascript',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpeg'
};
const contentType = contentTypes[ext] || 'text/plain';
res.writeHead(200, { 'Content-Type': contentType });
res.end(content);
} catch (err) {
if (err.code === 'ENOENT') {
res.writeHead(404);
res.end('File not found');
} else {
res.writeHead(500);
res.end('Server error');
}
}
});
server.listen(3000);
Project structure:
project/
├── server.js
└── public/
├── index.html
├── style.css
└── app.js
URL Parsing
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
// Parse URL and query string
const parsedUrl = url.parse(req.url, true);
console.log('Path:', parsedUrl.pathname); // /search
console.log('Query:', parsedUrl.query); // { q: 'nodejs', page: '2' }
if (parsedUrl.pathname === '/search') {
const searchTerm = parsedUrl.query.q;
const page = parsedUrl.query.page || 1;
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
search: searchTerm,
page: page,
results: []
}));
} else {
res.writeHead(404);
res.end('Not found');
}
});
server.listen(3000);
Visit: http://localhost:3000/search?q=nodejs&page=2
Headers and Cookies
const http = require('http');
const server = http.createServer((req, res) => {
// Read request headers
console.log('User-Agent:', req.headers['user-agent']);
console.log('Cookie:', req.headers.cookie);
// Set response headers
res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Powered-By', 'NodeJS');
// Set cookie
res.setHeader('Set-Cookie', 'sessionId=abc123; HttpOnly; Max-Age=3600');
// Multiple headers
res.writeHead(200, {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Access-Control-Allow-Origin': '*'
});
res.end(JSON.stringify({ message: 'Headers set' }));
});
server.listen(3000);
Complete REST API Example
const http = require('http');
// In-memory data store
let users = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
];
let nextId = 3;
const server = http.createServer((req, res) => {
const { method, url } = req;
// Helper to send JSON
const sendJSON = (statusCode, data) => {
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(data));
};
// GET /api/users - List all users
if (url === '/api/users' && method === 'GET') {
sendJSON(200, users);
}
// GET /api/users/:id - Get single user
else if (url.match(/^\/api\/users\/\d+$/) && method === 'GET') {
const id = parseInt(url.split('/')[3]);
const user = users.find(u => u.id === id);
if (user) {
sendJSON(200, user);
} else {
sendJSON(404, { error: 'User not found' });
}
}
// POST /api/users - Create user
else if (url === '/api/users' && method === 'POST') {
let body = '';
req.on('data', chunk => { body += chunk; });
req.on('end', () => {
const newUser = JSON.parse(body);
newUser.id = nextId++;
users.push(newUser);
sendJSON(201, newUser);
});
}
// PUT /api/users/:id - Update user
else if (url.match(/^\/api\/users\/\d+$/) && method === 'PUT') {
const id = parseInt(url.split('/')[3]);
let body = '';
req.on('data', chunk => { body += chunk; });
req.on('end', () => {
const updates = JSON.parse(body);
const index = users.findIndex(u => u.id === id);
if (index !== -1) {
users[index] = { ...users[index], ...updates };
sendJSON(200, users[index]);
} else {
sendJSON(404, { error: 'User not found' });
}
});
}
// DELETE /api/users/:id - Delete user
else if (url.match(/^\/api\/users\/\d+$/) && method === 'DELETE') {
const id = parseInt(url.split('/')[3]);
const index = users.findIndex(u => u.id === id);
if (index !== -1) {
users.splice(index, 1);
sendJSON(200, { message: 'User deleted' });
} else {
sendJSON(404, { error: 'User not found' });
}
}
// Not found
else {
sendJSON(404, { error: 'Endpoint not found' });
}
});
server.listen(3000, () => {
console.log('API server running on http://localhost:3000');
console.log('Try: GET http://localhost:3000/api/users');
});
Test the API:
# Get all users
curl http://localhost:3000/api/users
# Get single user
curl http://localhost:3000/api/users/1
# Create user
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie","email":"charlie@example.com"}'
# Update user
curl -X PUT http://localhost:3000/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"Alice Updated"}'
# Delete user
curl -X DELETE http://localhost:3000/api/users/2
Why Use Express?
The raw http module works but is verbose. Compare:
Raw HTTP:
const server = http.createServer((req, res) => {
if (req.url === '/api/users' && req.method === 'GET') {
// ... 10 lines of code
}
});
Express:
const app = express();
app.get('/api/users', (req, res) => {
res.json(users);
});
Express provides:
- Simpler routing
- Middleware support
- Request parsing built-in
- Template engines
- Static file serving
Summary
| Concept | Code |
|---|---|
| Create server | http.createServer((req, res) => {}) |
| Start server | server.listen(3000) |
| Send text | res.end('Hello') |
| Send JSON | res.end(JSON.stringify(data)) |
| Set status | res.statusCode = 404 |
| Set header | res.setHeader('Content-Type', 'text/html') |
| Read body | req.on('data', chunk => {}) |
| Parse URL | url.parse(req.url, true) |
Next Article: Express Framework Basics