Episode 3 — NodeJS MongoDB Backend Architecture / 3.2 — Creating Server

3.2 — Quick Revision: Creating a Server

A compact cheat sheet covering the http module, status codes, content types, request/response objects, routing patterns, and nodemon.


< Interview Questions | README


How to Use This Material

  • Use this as a last-minute review before interviews or assessments.
  • Read through the tables and code snippets. If anything looks unfamiliar, go back to the corresponding subtopic file and re-read that section.
  • Cover the right column of each table and quiz yourself on the answers.
  • This is a reference sheet, not a learning resource. Learn from 3.2.a through 3.2.f first.

Minimal Server (Copy-Paste Starter)

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello, World!');
});

server.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

http Module API

Method / PropertyPurpose
http.createServer(callback)Creates an HTTP server; callback receives (req, res)
server.listen(port, [host], [callback])Starts listening for connections on the given port
server.close([callback])Stops the server from accepting new connections
server.on('request', fn)Same as passing callback to createServer
server.on('error', fn)Handles server errors (e.g., EADDRINUSE)
server.on('listening', fn)Fires when server begins listening
server.on('connection', fn)Fires on each new TCP connection
server.on('close', fn)Fires when server shuts down

req Object (http.IncomingMessage)

Property / MethodReturnsExample Value
req.methodHTTP method string"GET", "POST", "PUT", "DELETE"
req.urlFull URL path + query string"/api/users?page=2"
req.headersObject of all headers (keys lowercased){ host: 'localhost:3000', 'user-agent': '...' }
req.headers['content-type']Request body format"application/json"
req.headers['authorization']Auth credentials"Bearer eyJ..."
req.httpVersionHTTP version string"1.1"
req.socket.remoteAddressClient IP address"127.0.0.1"
req.on('data', fn)Receive body chunkChunk is a Buffer
req.on('end', fn)Body fully receivedParse body here

Reading a POST Body

let body = '';
req.on('data', (chunk) => { body += chunk.toString(); });
req.on('end', () => {
  const data = JSON.parse(body);
  // use data
});

res Object (http.ServerResponse)

Method / PropertyPurpose
res.writeHead(statusCode, headers)Set status code + headers in one call (call once)
res.setHeader(name, value)Set a single header (call multiple times)
res.statusCode = 200Set status code separately
res.write(data)Write a chunk to the response body
res.end([data])Finish the response (optionally send final data)
res.getHeader(name)Read a previously set header
res.removeHeader(name)Remove a previously set header

writeHead vs setHeader

Featureres.writeHead()res.setHeader()
Sets status codeYesNo (use res.statusCode)
Sets multiple headersYes (object)One at a time
Can call multiple timesNoYes
Best forAll headers known upfrontBuilding headers incrementally

HTTP Status Codes

2xx Success

CodeNameWhen to Use
200OKSuccessful GET, PUT, PATCH returning data
201CreatedSuccessful POST that created a resource
204No ContentSuccessful DELETE or PUT with no response body

3xx Redirection

CodeNameWhen to Use
301Moved PermanentlyURL permanently changed (SEO, domain change)
302FoundTemporary redirect (maintenance, post-redirect-get)
304Not ModifiedClient cache is still valid

4xx Client Errors

CodeNameWhen to Use
400Bad RequestMalformed JSON, unparseable body
401UnauthorizedNo credentials or invalid credentials (authentication)
403ForbiddenValid credentials but insufficient permissions (authorization)
404Not FoundResource or route does not exist
405Method Not AllowedWrong HTTP method for this route (include Allow header)
409ConflictDuplicate resource (e.g., email already registered)
422Unprocessable EntityValid JSON but invalid data values
429Too Many RequestsRate limit exceeded (include Retry-After header)

5xx Server Errors

CodeNameWhen to Use
500Internal Server ErrorUnhandled exception, server bug
502Bad GatewayUpstream server returned invalid response
503Service UnavailableMaintenance or overload (include Retry-After header)
504Gateway TimeoutUpstream server did not respond in time

Quick Decision Rule

2xx = "All good."
3xx = "Go somewhere else."
4xx = "You (client) messed up."
5xx = "I (server) messed up."

Content Types (MIME Types)

Content-TypeData FormatUse Case
text/plainPlain textSimple text, debugging
text/htmlHTML markupWeb pages
text/cssCSS stylesheetStyles
text/csvComma-separated valuesData exports
application/jsonJSONAPI responses
application/javascriptJavaScriptScript files
application/xmlXMLLegacy APIs
application/pdfPDFDocuments
application/octet-streamBinary (generic)File downloads
image/pngPNG imageGraphics
image/jpegJPEG imagePhotos
image/svg+xmlSVG imageVector graphics
multipart/form-dataForm with filesFile uploads
application/x-www-form-urlencodedURL-encoded formHTML form submissions

HTTP Methods

MethodPurposeHas BodyIdempotentSafe
GETRetrieve a resourceNoYesYes
POSTCreate a new resourceYesNoNo
PUTReplace entire resourceYesYesNo
PATCHPartially update resourceYesNoNo
DELETERemove a resourceOptionalYesNo
HEADSame as GET, no body in responseNoYesYes
OPTIONSAsk what methods are allowedNoYesYes

Routing Patterns

Pattern 1: if/else on req.url

if (req.url === '/' && req.method === 'GET') {
  res.end('Home');
} else if (req.url === '/about' && req.method === 'GET') {
  res.end('About');
} else {
  res.writeHead(404);
  res.end('Not Found');
}

Pattern 2: Route table object

const routes = {
  'GET /':      (req, res) => res.end('Home'),
  'GET /about': (req, res) => res.end('About'),
};
const handler = routes[`${req.method} ${req.url}`];
handler ? handler(req, res) : res.writeHead(404) && res.end('Not Found');

Pattern 3: Dynamic parameters with split

// GET /api/users/42
const parts = req.url.split('/');  // ['', 'api', 'users', '42']
const id = parseInt(parts[3]);

Pattern 4: Dynamic parameters with regex

const match = req.url.match(/^\/api\/users\/(\d+)$/);
if (match) {
  const id = parseInt(match[1]);
}

Parsing Query Strings

// Modern (recommended)
const url = new URL(req.url, `http://${req.headers.host}`);
url.pathname;                      // "/products"
url.searchParams.get('page');      // "2"
url.searchParams.has('sort');      // true or false

// Legacy (deprecated)
const parsed = require('url').parse(req.url, true);
parsed.pathname;                   // "/products"
parsed.query.page;                 // "2"

Response Patterns

Plain text

res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World!');

HTML

res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end('<h1>Hello</h1>');

JSON

const data = { message: 'Hello' };
const body = JSON.stringify(data);
res.writeHead(200, {
  'Content-Type': 'application/json',
  'Content-Length': Buffer.byteLength(body)
});
res.end(body);

Redirect

res.writeHead(301, { 'Location': '/new-page' });
res.end();

Error (JSON API)

res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Not Found', message: 'User does not exist' }));

Static file

const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'public', 'index.html');
fs.readFile(filePath, (err, content) => {
  if (err) { res.writeHead(500); res.end('Error'); return; }
  res.writeHead(200, { 'Content-Type': 'text/html' });
  res.end(content);
});

Common Ports

PortService
80HTTP
443HTTPS
3000Node.js / React dev
5173Vite dev
8080Alternative HTTP / proxies
5432PostgreSQL
27017MongoDB
6379Redis

Networking Essentials

TermMeaning
localhostHostname pointing to your own machine
127.0.0.1IPv4 loopback address (same as localhost)
0.0.0.0All network interfaces (accessible from other devices)
DNSTranslates domain names to IP addresses
TCPTransport protocol; reliable, ordered delivery
TLS/SSLEncryption layer for HTTPS
StatelessEach HTTP request is independent; server does not remember previous requests

Nodemon and Development Workflow

Install and configure

npm install -D nodemon
// package.json scripts
{
  "start": "node server.js",
  "dev": "nodemon server.js"
}
npm run dev     # Development (auto-restart)
npm start       # Production (no auto-restart)

nodemon.json

{
  "watch": ["src"],
  "ext": "js,json",
  "ignore": ["node_modules", "tests", "*.test.js"],
  "delay": 500
}

Common CLI flags

FlagPurposeExample
--extFile extensions to watchnodemon --ext js,json
--watchDirectories to watchnodemon --watch src
--ignorePaths to ignorenodemon --ignore logs/
--delayRestart delay (ms)nodemon --delay 1000
--execAlternate executornodemon --exec ts-node
--inspectEnable Node debuggernodemon --inspect

node --watch (Node 18.11+, built-in alternative)

node --watch server.js
node --watch-path=./src server.js

When to use which

ScenarioTool
Simple project, only .js, Node 18+node --watch
Need ignore paths, extensions, delaynodemon
TypeScript projecttsx watch or nodemon --exec ts-node

Common Mistakes Checklist

MistakeConsequenceFix
Forgetting res.end()Client hangs foreverAlways call res.end()
res.write() after res.end()Runtime errorEnsure end() is last
Passing object to res.end()TypeErrorUse JSON.stringify()
Wrong Content-TypeGarbled output in browserMatch header to actual data format
200 for errorsBreaks client error handlingUse correct 4xx/5xx codes
fs.readFile used synchronouslyReturns undefinedUse callback or readFileSync
String concat for file pathsBreaks cross-OS, security riskUse path.join()
Route order wrongGreedy match hides specific routesCheck specific routes first
No 404 catch-allUnknown routes hang or crashAlways add a fallback
Using 500 for client errorsMisleading; triggers wrong alertsUse 400/422 for bad input

Key Headers to Remember

Response headers

HeaderPurposeExample
Content-TypeData format of response bodyapplication/json
Content-LengthSize of body in bytes256
LocationRedirect target URL/new-page
Set-CookieSend a cookie to the clientsessionId=abc; HttpOnly
Cache-ControlCaching instructionsmax-age=3600
Access-Control-Allow-OriginCORS: which origins allowed*
AllowAllowed methods (with 405)GET, POST
Retry-AfterWhen to retry (with 429/503)60
WWW-AuthenticateAuth scheme (with 401)Bearer

Request headers

HeaderPurposeExample
HostTarget serverexample.com
AcceptAcceptable response formatsapplication/json
Content-TypeFormat of request bodyapplication/json
AuthorizationAuth credentialsBearer eyJ...
User-AgentClient softwareMozilla/5.0...
CookieCookies from previous responsessessionId=abc123

Testing Commands

# Simple GET
curl http://localhost:3000

# GET with verbose output (shows headers)
curl -v http://localhost:3000

# GET headers only
curl -I http://localhost:3000

# POST with JSON body
curl -X POST http://localhost:3000/api/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice"}'

# POST with form data
curl -X POST http://localhost:3000/form \
  -d "name=Alice&email=alice@example.com"

# DELETE request
curl -X DELETE http://localhost:3000/api/users/1

# Pretty-print JSON
curl http://localhost:3000/api/users | python3 -m json.tool

Navigation: < Interview Questions | README