Handling Requests and Responses
Now that you can create a basic server, let's dive deeper into handling incoming requests and crafting appropriate responses. You'll learn to extract data from requests and send proper HTTP responses.
Parsing the Request URL
The req.url property contains the path and query string:
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
// req.url example: "/users?page=1&limit=10"
// Parse the URL
const parsedUrl = new URL(req.url, `http://${req.headers.host}`);
console.log('Pathname:', parsedUrl.pathname); // "/users"
console.log('Search:', parsedUrl.search); // "?page=1&limit=10"
// Get query parameters
const page = parsedUrl.searchParams.get('page'); // "1"
const limit = parsedUrl.searchParams.get('limit'); // "10"
res.end(`Page: ${page}, Limit: ${limit}`);
});
HTTP Methods
Different methods indicate different operations:
| Method | Purpose | Has Body |
|---|---|---|
| GET | Retrieve data | No |
| POST | Create data | Yes |
| PUT | Update data (replace) | Yes |
| PATCH | Update data (partial) | Yes |
| DELETE | Delete data | Usually no |
| HEAD | Get headers only | No |
| OPTIONS | Get allowed methods | No |
const server = http.createServer((req, res) => {
console.log('Method:', req.method);
switch (req.method) {
case 'GET':
// Return data
res.end('Here is your data');
break;
case 'POST':
// Handle creation
res.end('Data created');
break;
case 'DELETE':
// Handle deletion
res.end('Data deleted');
break;
default:
res.statusCode = 405;
res.end('Method Not Allowed');
}
});
Reading Request Headers
const server = http.createServer((req, res) => {
// All headers (lowercase keys)
console.log(req.headers);
// Common headers
const contentType = req.headers['content-type'];
const userAgent = req.headers['user-agent'];
const authorization = req.headers['authorization'];
const accept = req.headers['accept'];
res.end('Headers received');
});
Reading Request Body
For POST/PUT requests, you need to collect the body data:
const http = require('http');
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('Body:', body);
// Parse JSON body
try {
const data = JSON.parse(body);
console.log('Parsed:', data);
res.end('Data received');
} catch (err) {
res.statusCode = 400;
res.end('Invalid JSON');
}
});
} else {
res.end('Send a POST request');
}
});
Helper Function for Body Parsing
Create a reusable body parser:
function getBody(req) {
return new Promise((resolve, reject) => {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
// Prevent too-large bodies
if (body.length > 1e6) {
req.destroy();
reject(new Error('Body too large'));
}
});
req.on('end', () => resolve(body));
req.on('error', reject);
});
}
// Usage
const server = http.createServer(async (req, res) => {
if (req.method === 'POST') {
try {
const body = await getBody(req);
const data = JSON.parse(body);
res.end(JSON.stringify({ received: data }));
} catch (err) {
res.statusCode = 400;
res.end(JSON.stringify({ error: err.message }));
}
}
});
Setting Response Headers
const server = http.createServer((req, res) => {
// Set individual headers
res.setHeader('Content-Type', 'application/json');
res.setHeader('X-Powered-By', 'Node.js');
res.setHeader('Cache-Control', 'no-cache');
// Or use writeHead for status + headers together
res.writeHead(200, {
'Content-Type': 'application/json',
'X-Request-Id': '12345'
});
res.end(JSON.stringify({ status: 'ok' }));
});
Common Response Headers
| Header | Purpose | Example |
|---|---|---|
Content-Type | Body format | application/json |
Content-Length | Body size | 1234 |
Cache-Control | Caching rules | max-age=3600 |
Location | Redirect URL | https://example.com |
Set-Cookie | Set cookie | session=abc; HttpOnly |
Access-Control-Allow-Origin | CORS | * |
Sending Different Response Types
Redirects
const server = http.createServer((req, res) => {
if (req.url === '/old-page') {
// Permanent redirect (301)
res.writeHead(301, { 'Location': '/new-page' });
res.end();
return;
}
if (req.url === '/temporary') {
// Temporary redirect (302)
res.writeHead(302, { 'Location': '/somewhere-else' });
res.end();
return;
}
res.end('Normal page');
});
Error Responses
function sendError(res, statusCode, message) {
res.statusCode = statusCode;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
error: true,
message: message,
statusCode: statusCode
}));
}
const server = http.createServer((req, res) => {
if (req.url === '/protected' && !req.headers.authorization) {
sendError(res, 401, 'Authentication required');
return;
}
if (req.url === '/admin' && !isAdmin(req)) {
sendError(res, 403, 'Access forbidden');
return;
}
res.end('OK');
});
CORS Headers
Enable cross-origin requests:
const server = http.createServer((req, res) => {
// CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
// Handle preflight
if (req.method === 'OPTIONS') {
res.writeHead(204);
res.end();
return;
}
// Normal request handling
res.end('CORS enabled');
});
Complete Request/Response Example
const http = require('http');
const server = http.createServer(async (req, res) => {
// Parse URL
const url = new URL(req.url, `http://${req.headers.host}`);
// Log request
console.log(`${req.method} ${url.pathname}`);
// Set CORS
res.setHeader('Access-Control-Allow-Origin', '*');
// Handle preflight
if (req.method === 'OPTIONS') {
res.writeHead(204);
res.end();
return;
}
// Route handling
if (req.method === 'GET' && url.pathname === '/api/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'healthy' }));
return;
}
if (req.method === 'POST' && url.pathname === '/api/echo') {
let body = '';
for await (const chunk of req) {
body += chunk;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(body);
return;
}
// 404 for unknown routes
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Not found' }));
});
server.listen(3000);
Key Takeaways
- Use
new URL(req.url, base)to parse URLs and query parameters - Check
req.methodto handle different HTTP methods - Access headers via
req.headers(lowercase keys) - Collect body data using
req.on('data')andreq.on('end') - Use
res.writeHead()orres.setHeader()for response headers - Always set appropriate
Content-Typeheader - Return proper status codes (200, 400, 401, 404, 500, etc.)
Summary
You now know how to fully process incoming HTTP requests—parsing URLs, reading headers and body data, and responding appropriately. You can handle different content types, implement redirects, and return proper error responses. These skills form the foundation for building APIs and web applications.
Next, you'll learn about routing—directing different requests to different handlers based on URL patterns.

