What is Express.js, and why use it instead of the
httpmodule?Express is a minimal web framework on Node's
httpmodule that adds routing, middleware, body parsing and helpers such asres.json.const express = require('express'); const app = express(); app.use(express.json()); // parse JSON bodies into req.body app.get('/users/:id', (req, res) => { res.json({ id: req.params.id }); }); app.listen(3000, () => console.log('listening on 3000'));Alternatives: Fastify (faster, schema validation), NestJS (dependency injection, on Express or Fastify) and Koa.
What is middleware in Express?
A function
(req, res, next)that runs during a request, in registration order. It can changereqandres, end the response, or callnext(). Logging, auth and body parsing are middleware.function requestTimer(req, res, next) { const start = Date.now(); res.on('finish', () => { console.log(req.method, req.url, res.statusCode, Date.now() - start, 'ms'); }); next(); } function requireAuth(req, res, next) { if (!req.headers.authorization) { return res.status(401).json({ error: 'missing token' }); } next(); } app.use(requestTimer); // every route app.get('/orders', requireAuth, listOrders); // one routeClassic bugs: neither calling
next()nor responding hangs the request; callingnext()after responding lets a later handler respond again, which throws "Cannot set headers after they are sent to the client".What is the difference between
req.params,req.queryandreq.body?req.paramsholds route segments (/users/:id),req.querythe query string (?page=2),req.bodythe parsed body. Params and query values are strings, so convert and validate them, andreq.bodyisundefinedwithout a parser such asexpress.json().How do you handle errors in Express?
Add a middleware with four parameters
(err, req, res, next)after all routes; errors passed tonext(err)or thrown in a handler go there.app.get('/users/:id', async (req, res) => { const user = await db.findUser(req.params.id); // may reject if (!user) { const err = new Error('user not found'); err.status = 404; throw err; } res.json(user); }); // last; the four parameters are how Express recognizes it app.use((err, req, res, next) => { console.error(err); res.status(err.status ?? 500).json({ error: err.status ? err.message : 'internal error' }); });Express 5 forwards a rejected
asynchandler there too. Express 4 does not: the request hangs and, on Node 15 and later, the process crashes, so catch and callnext(err).What is
express.Routerand how do you structure routes?express.Router()is a mini app with its own routes and middleware, mounted under a prefix to split an API into files.// routes/users.js const express = require('express'); const router = express.Router(); router.get('/', listUsers); // GET /api/users router.get('/:id', getUser); // GET /api/users/42 router.post('/', createUser); // POST /api/users module.exports = router; // app.js app.use('/api/users', require('./routes/users'));Keep routes thin: they parse input and call a service, which holds the business logic, so it stays testable without HTTP.
What is the difference between
app.useandapp.get?app.getmatches onlyGET(andHEAD) on the exact path.app.usematches every method and every path under the prefix, and strips the prefix fromreq.url. Mount routers and middleware withuse, endpoints withgetorpost.app.use('/api', apiLogger); // GET /api/users, POST /api/orders/7, ... app.get('/api/users', listUsers); // only GET /api/usersWhat is CORS, and how do you enable it in a Node.js API?
CORS is a browser rule: a page may read a response from another origin only if the API's headers allow it. Only browsers enforce it, so it does not protect your API. For JSON bodies, custom headers or
PUT, the browser first sends anOPTIONSpreflight.const cors = require('cors'); app.use(cors({ origin: ['https://app.example.com'], // never '*' when sending cookies credentials: true, }));How do you create an HTTP server without Express?
With
node:http:createServertakes a(req, res)handler for every request, and routing and parsing are yours.JavaScriptconst http = require('node:http'); const server = http.createServer((req, res) => { const url = new URL(req.url, 'http://localhost'); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ path: url.pathname, x: url.searchParams.get('x') })); }); server.listen(0, () => { const { port } = server.address(); http.get(`http://127.0.0.1:${port}/hello?x=1`, (res) => { let body = ''; res.setEncoding('utf8'); res.on('data', (chunk) => (body += chunk)); res.on('end', () => { console.log(res.statusCode, res.headers['content-type'], body); server.close(); }); }); });Port
0asks the OS for any free port, the usual trick in tests.What is the difference between
res.send,res.jsonandres.endin Express?res.endis Node's raw method: it ends the response with an optional string or Buffer and sets noContent-Type.res.sendis Express: it sets the type from the value (a string istext/html, a Bufferapplication/octet-stream, an object JSON) plusContent-Lengthand anETag.res.jsonalways serializes and sendsapplication/json.app.get('/raw', (req, res) => res.end('ok')); // no Content-Type app.get('/page', (req, res) => res.send('<p>ok</p>')); // text/html app.get('/api', (req, res) => res.json({ ok: true })); // application/json app.delete('/x', (req, res) => res.status(204).end()); // no bodySo
res.send(JSON.stringify(data))goes out as HTML; useres.json(data).How do you implement JWT authentication in an Express API?
At login, check the password and sign a short-lived token; on each request, a middleware reads
Authorization: Bearer <token>, verifies it and setsreq.user, or answers401.const jwt = require('jsonwebtoken'); const SECRET = process.env.JWT_SECRET; app.post('/login', async (req, res) => { const user = await users.checkPassword(req.body.email, req.body.password); if (!user) return res.status(401).json({ error: 'invalid credentials' }); res.json({ token: jwt.sign({ sub: user.id }, SECRET, { expiresIn: '15m' }) }); }); function requireUser(req, res, next) { const [scheme, token] = (req.headers.authorization ?? '').split(' '); try { if (scheme !== 'Bearer') throw new Error('missing token'); req.user = jwt.verify(token, SECRET, { algorithms: ['HS256'] }); next(); } catch { res.status(401).json({ error: 'invalid or expired token' }); } } app.get('/me', requireUser, (req, res) => res.json({ id: req.user.sub }));A JWT is signed, not encrypted: anyone can read its payload. It cannot be revoked before it expires without a denylist, hence short expiry plus a refresh token.
Express.js Interview Questions
Express examples are static because this page has no npm packages; the last question uses http and runs.