Skip to content
Plurafy

HTTP Server and Request Handling

Creating HTTP servers and handling requests/responses efficiently

You need to build an HTTP server that handles multiple concurrent requests, properly manages timeouts, and efficiently streams large responses. How do you do this correctly?

Node.js http module provides low-level APIs for creating HTTP servers. Understanding request/response objects, headers, and streaming is essential for building robust servers.

const http = require('http');
const server = http.createServer((req, res) => {
// Set response headers
res.writeHead(200, { 'Content-Type': 'application/json' });
// Send response
res.write(JSON.stringify({ message: 'Hello' }));
res.end();
});
server.listen(3000, 'localhost', () => {
console.log('Server running on http://localhost:3000');
});
// Handle errors
server.on('error', (err) => {
console.error('Server error:', err);
});
// Graceful shutdown
process.on('SIGTERM', () => {
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});

Solution: Request Routing and Response Streaming

Section titled “Solution: Request Routing and Response Streaming”
const http = require('http');
const fs = require('fs');
const url = require('url');
const server = http.createServer(async (req, res) => {
// Parse URL and query parameters
const parsedUrl = url.parse(req.url, true);
const pathname = parsedUrl.pathname;
const query = parsedUrl.query;
try {
// Route handling
if (pathname === '/' && req.method === 'GET') {
handleHome(req, res);
} else if (pathname === '/api/users' && req.method === 'GET') {
handleGetUsers(req, res, query);
} else if (pathname === '/api/users' && req.method === 'POST') {
handleCreateUser(req, res);
} else if (pathname.match(/^\/file\//) && req.method === 'GET') {
handleFileDownload(req, res, pathname);
} else {
res.writeHead(404);
res.end(JSON.stringify({ error: 'Not Found' }));
}
} catch (err) {
res.writeHead(500);
res.end(JSON.stringify({ error: 'Internal Server Error' }));
}
});
function handleHome(req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>Welcome</h1>');
}
function handleGetUsers(req, res, query) {
const limit = query.limit || 10;
const offset = query.offset || 0;
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
users: [],
pagination: { limit, offset }
}));
}
function handleCreateUser(req, res) {
let body = '';
// Collect request body
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
try {
const user = JSON.parse(body);
res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ id: 1, ...user }));
} catch (err) {
res.writeHead(400);
res.end(JSON.stringify({ error: 'Invalid JSON' }));
}
});
}
function handleFileDownload(req, res, pathname) {
const filePath = `./files${pathname.replace(/^\/file/, '')}`;
// Stream file response
const stream = fs.createReadStream(filePath);
res.writeHead(200, {
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment; filename="file"'
});
stream.pipe(res);
stream.on('error', (err) => {
res.writeHead(404);
res.end('File not found');
});
}
server.listen(3000);
const http = require('http');
const server = http.createServer((req, res) => {
if (req.method === 'POST') {
let body = '';
// Handle data event
req.on('data', chunk => {
body += chunk.toString();
// Prevent large uploads
if (body.length > 1e6) {
req.destroy();
res.writeHead(413); // Payload Too Large
res.end();
}
});
req.on('end', () => {
try {
const data = JSON.parse(body);
res.writeHead(200);
res.end(JSON.stringify({ received: data }));
} catch (err) {
res.writeHead(400);
res.end('Invalid JSON');
}
});
req.on('error', (err) => {
res.writeHead(400);
res.end('Request error');
});
}
});
server.listen(3000);
const http = require('http');
const server = http.createServer((req, res) => {
// Read request headers
console.log(req.headers);
// {
// 'user-agent': 'curl/7.64.1',
// 'accept': '*/*',
// 'host': 'localhost:3000',
// 'cookie': 'session=abc123'
// }
// Parse cookies
const cookies = {};
if (req.headers.cookie) {
req.headers.cookie.split('; ').forEach(cookie => {
const [key, value] = cookie.split('=');
cookies[key] = value;
});
}
// Set response headers
res.setHeader('Content-Type', 'application/json');
res.setHeader('Set-Cookie', 'session=xyz789; Path=/; HttpOnly');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Access-Control-Allow-Origin', '*');
res.writeHead(200);
res.end(JSON.stringify({ cookies }));
});
server.listen(3000);
const http = require('http');
const zlib = require('zlib');
const server = http.createServer((req, res) => {
// Compression based on client support
const acceptEncoding = req.headers['accept-encoding'] || '';
const data = JSON.stringify({ message: 'Hello' * 10000 });
if (acceptEncoding.includes('gzip')) {
res.writeHead(200, {
'Content-Type': 'application/json',
'Content-Encoding': 'gzip'
});
res.pipe(zlib.createGzip()).end(data);
} else {
res.writeHead(200);
res.end(data);
}
});
// Keep-alive connection for better performance
const server2 = http.createServer((req, res) => {
res.writeHead(200, {
'Connection': 'keep-alive',
'Keep-Alive': 'timeout=5, max=100'
});
res.end('OK');
});
// Connection pooling
server.maxConnections = 200;
server.listen(3000);
// Middleware pattern for request processing
function createServer(middlewares = []) {
return http.createServer(async (req, res) => {
// Execute middlewares in sequence
for (const middleware of middlewares) {
await new Promise((resolve) => {
middleware(req, res, resolve);
});
if (res.headersSent) return; // Middleware sent response
}
});
}
const server = createServer([
// Logging middleware
(req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
},
// Authentication middleware
(req, res, next) => {
if (req.headers.authorization) {
next();
} else {
res.writeHead(401);
res.end('Unauthorized');
}
},
// Main handler
(req, res, next) => {
res.writeHead(200);
res.end('OK');
}
]);
server.listen(3000);