Building an HTTP Server
Node.js was built with server-side JavaScript in mind, and its built-in http module makes creating web servers straightforward. In this tutorial, you’ll build HTTP servers from scratch, handle different routes, and process client requests.
Your First HTTP Server
The http module provides everything you need to create a server. Here’s a minimal example:
import { createServer } from 'http';
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World!');
});
server.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});
Run this with node server.js and visit http://localhost:3000 in your browser. The server responds with “Hello, World!” for every request.
The callback function receives two objects:
req(request) — contains details about the incoming requestres(response) — lets you send data back to the client
Understanding the Request Object
The req object contains all the information about what the client asked for:
import { createServer } from 'http';
const server = createServer((req, res) => {
console.log('Method:', req.method); // GET, POST, PUT, DELETE
console.log('URL:', req.url); // The path requested
console.log('Headers:', req.headers); // All request headers
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Request received');
});
server.listen(3000);
Common req properties:
req.method— HTTP verb (GET, POST, etc.)req.url— The path and query stringreq.headers— Object containing all headers
Handling Different Routes
Most applications need to handle multiple routes. Here’s how to do it:
import { createServer } from 'http';
const server = createServer((req, res) => {
const pathname = req.url.split('?')[0];
if (pathname === '/' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>Welcome Home</h1>');
}
else if (pathname === '/about' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>About Us</h1>');
}
else if (pathname === '/api/users' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ users: [] }));
}
else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});
server.listen(3000);
This handles three routes plus a 404 fallback.
Reading Request Body Data
For POST and PUT requests, you need to read the request body:
import { createServer } from 'http';
const server = createServer(async (req, res) => {
if (req.method === 'POST' && req.url === '/submit') {
// Collect chunks of data
const chunks = [];
for await (const chunk of req) {
chunks.push(chunk);
}
const body = JSON.parse(Buffer.concat(chunks).toString());
console.log('Received:', body);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ success: true, received: body }));
} else {
res.writeHead(404);
res.end();
}
});
server.listen(3000);
Test it with curl:
curl -X POST http://localhost:3000/submit \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "age": 30}'
Setting Response Headers
Proper headers are essential for correct behavior:
import { createServer } from 'http';
const server = createServer((req, res) => {
// JSON response
if (req.url === '/api/data') {
res.writeHead(200, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
res.end(JSON.stringify({ message: 'Here is your data' }));
}
// HTML with custom headers
else if (req.url === '/') {
res.writeHead(200, {
'Content-Type': 'text/html',
'Cache-Control': 'no-cache'
});
res.end('<html><body><h1>Hello!</h1></body></html>');
}
// Redirect
else if (req.url === '/old-page') {
res.writeHead(301, { 'Location': '/new-page' });
res.end();
}
else {
res.writeHead(404);
res.end('Not Found');
}
});
server.listen(3000);
Working with HTTPS
For secure servers, use the https module with SSL certificates:
import { createServer } from 'https';
import { readFileSync } from 'fs';
const options = {
key: readFileSync('private-key.pem'),
cert: readFileSync('certificate.pem')
};
const server = createServer(options, (req, res) => {
res.writeHead(200);
res.end('Secure connection established');
});
server.listen(443, () => {
console.log('HTTPS server running on port 443');
});
Summary
You’ve learned how to:
- Create a basic HTTP server with
createServer() - Access request method, URL, and headers
- Handle different routes with conditional logic
- Read POST request bodies
- Set response headers for JSON, HTML, and redirects
- Set up HTTPS for secure connections
The http module is powerful enough for many applications, but for production use, frameworks like Express provide nicer APIs and more features.