Built-in Middleware

beginner express middleware body-parser static

Express ships with a handful of built-in middleware functions. You’ll use these in nearly every app. They used to live in a separate body-parser package, but since Express 4.16 they’re bundled directly.

express.json()

Parses incoming requests with Content-Type: application/json and attaches the parsed body to req.body.

const express = require('express');
const app = express();

app.use(express.json());

app.post('/users', (req, res) => {
  console.log(req.body); // { name: 'Manish', age: 28 }
  res.status(201).json(req.body);
});

Without this middleware, req.body would be undefined for JSON POST/PUT requests. The Node http module gives us a raw stream — Express needs to read it, decode it, and JSON-parse it.

Common options:

app.use(express.json({
  limit: '1mb',     // max body size (default: 100kb)
  strict: true,     // only accept arrays/objects (default: true)
}));

The limit is important — without it, an attacker can flood your server with massive payloads. Set it as tight as your real use case allows.

express.urlencoded()

Parses application/x-www-form-urlencoded bodies — the format HTML forms submit by default.

app.use(express.urlencoded({ extended: true }));

app.post('/login', (req, res) => {
  const { email, password } = req.body;
  // ... handle login
});

The extended option:

  • extended: false — uses Node’s built-in querystring. Only string/array values.
  • extended: true — uses the qs library. Supports nested objects like user[name]=Manish.

For modern APIs that only accept JSON, you may not need this at all. Add it if you serve HTML forms.

express.static()

Serves static files (HTML, CSS, JS, images) from a directory:

app.use(express.static('public'));

Now GET /logo.png serves ./public/logo.png. GET / serves ./public/index.html if it exists.

We usually mount it at a path:

app.use('/assets', express.static('public'));
// /assets/logo.png → ./public/logo.png

Options worth knowing:

app.use(express.static('public', {
  maxAge: '1d',          // Cache-Control: max-age=86400
  etag: true,            // ETag header for revalidation
  index: 'home.html',    // default file (default: 'index.html')
}));

Production tip: in real deployments, static files should be served by nginx or a CDN, not Express. Express is fine for dev or low-traffic apps.

express.Router()

Already covered in detail in the Router & Modular Routes note. The TL;DR — creates a mini sub-app to organize routes across files.

const router = express.Router();
router.get('/', (req, res) => res.json([]));
module.exports = router;
The built-ins at a glance
Middleware Purpose When you need it
express.json()Parse JSON bodiesREST APIs (always)
express.urlencoded()Parse form bodiesHTML form submissions
express.static()Serve filesDev / small sites
express.Router()Modular routesAny non-trivial app

A realistic setup

A typical Express app’s middleware stack looks like this:

const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');

const app = express();

// Security & logging
app.use(helmet());                                    // 3rd party
app.use(cors({ origin: 'https://pman47.cc' }));       // 3rd party
app.use(morgan('combined'));                          // 3rd party

// Body parsing (built-in)
app.use(express.json({ limit: '1mb' }));
app.use(express.urlencoded({ extended: true }));

// Static files (built-in)
app.use('/assets', express.static('public'));

// Routes
app.use('/api', require('./routes'));

// Error handler (last)
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: 'Internal' });
});

app.listen(3000);

That’s almost every production Express app’s skeleton. The built-ins cover body parsing and static files; everything else (CORS, security headers, logging, rate limiting) comes from npm.

These are common but not built-in:

  • cookie-parser — parses cookies into req.cookies
  • express-session — server-side sessions
  • multer — multipart/form-data (file uploads)

They were part of Express 3 but split out in Express 4. Install them separately when needed.