Cheatsheets / Express.js

Express.js Cheatsheet

Complete Express.js reference. Hit Ctrl+P to print.

Setup & App

npm install expressInstall Express.js
npm install express --saveInstall and save to package.json dependencies
const express = require('express')Import Express (CommonJS)
import express from 'express'Import Express (ES Modules)
const app = express()Create an Express application instance
app.listen(3000)Start server on port 3000
app.listen(3000, () => console.log('Running'))Start server with startup callback
app.listen(port, host, callback)Start server with port, host, and callback
const server = app.listen(3000)Store server reference for graceful shutdown
app.set('view engine', 'ejs')Set template engine to EJS
app.set('views', path.join(__dirname, 'views'))Set views directory
app.set('trust proxy', 1)Trust first proxy (needed behind Nginx/load balancer)
app.get('env')Get current environment (NODE_ENV or "development")
app.locals.title = 'My App'Set app-level local variables for templates
process.env.NODE_ENVAccess current environment (development/production)
app.disable('x-powered-by')Remove X-Powered-By header for security
app.enable('strict routing')Make /foo and /foo/ different routes
app.enable('case sensitive routing')Make /Foo and /foo different routes

Routing

app.get('/path', handler)Handle GET request
app.post('/path', handler)Handle POST request
app.put('/path', handler)Handle PUT request
app.patch('/path', handler)Handle PATCH request
app.delete('/path', handler)Handle DELETE request
app.all('/path', handler)Handle all HTTP methods
app.use('/path', handler)Mount middleware/router at path (matches prefix)
app.get('/users/:id', handler)Route with named parameter
app.get('/users/:id?', handler)Route with optional parameter
app.get('/files/*splat', handler)Wildcard route - v5 uses named wildcard (*name); v4 uses bare *
app.get('/path', mw1, mw2, handler)Multiple handlers for a single route
app.get('/path', [mw1, mw2], handler)Array of handlers for a single route
const router = express.Router()Create a modular router
router.get('/', handler)Define route on router
app.use('/api', router)Mount router at /api prefix
router.route('/users').get(h).post(h)Chainable route handlers
router.route('/users/:id').get(h).put(h).delete(h)Chained handlers for resource CRUD
express.Router({ mergeParams: true })Access parent route params in child router
express.Router({ strict: true })Strict mode: /foo and /foo/ are different

Request Object (req)

req.params.idNamed route parameter value
req.paramsObject of all route parameters
req.query.nameQuery string parameter (?name=value)
req.queryObject of all query string parameters
req.bodyParsed request body (requires body-parser middleware)
req.body.emailAccess specific field from parsed body
req.headers['content-type']Access request header by name (lowercase)
req.header('Authorization')Get header value (case-insensitive)
req.get('Accept')Alias for req.header()
req.methodHTTP method (GET, POST, etc.)
req.pathURL path without query string
req.urlFull URL including query string (relative to mount point)
req.originalUrlFull original URL (not affected by mounting)
req.hostnameHostname from Host header (or X-Forwarded-Host with trust proxy)
req.ipClient IP address
req.ipsArray of IPs from X-Forwarded-For (requires trust proxy)
req.protocolProtocol: "http" or "https"
req.securetrue if connection is HTTPS
req.cookiesParsed cookies object (requires cookie-parser)
req.signedCookiesSigned cookies object (requires cookie-parser with secret)
req.is('application/json')Check if request Content-Type matches
req.accepts('json')Check if client accepts given type (from Accept header)
req.freshtrue if response is still fresh (cache related)
req.staletrue if response is stale (opposite of fresh)
req.subdomainsArray of subdomains in the domain of the request
req.xhrtrue if X-Requested-With is XMLHttpRequest

Response Object (res)

res.send('Hello World')Send a string response
res.send(Buffer)Send a Buffer as binary response
res.json({ key: 'value' })Send JSON response (sets Content-Type automatically)
res.status(404).json({ error: 'Not found' })Set status code and send JSON
res.sendStatus(204)Send status code with default status message body
res.redirect('/new-url')Redirect to URL (302 by default)
res.redirect(301, '/new-url')Permanent redirect
res.redirect('back')Redirect to Referer header URL
res.render('template', { data })Render view template with data
res.sendFile(path)Send file at absolute path
res.sendFile(path, options, callback)Send file with options and completion callback
res.download(path, filename)Prompt download with optional custom filename
res.set('Content-Type', 'text/html')Set single response header
res.set({ 'X-Custom': 'value' })Set multiple response headers at once
res.get('Content-Type')Get current response header value
res.append('Link', '<url>')Append value to response header
res.cookie('name', value, options)Set a cookie
res.clearCookie('name')Clear a cookie
res.type('json')Set Content-Type by extension or MIME type
res.format({ 'text/html': fn, 'application/json': fn })Content negotiation - respond based on Accept header
res.locals.user = req.userPass data to template via response locals
res.end()End response without data
res.headersSentBoolean - true if headers have already been sent
res.vary('Accept')Add field to Vary header
res.links({ next: url, prev: url })Set Link header for pagination

Middleware

app.use(middleware)Apply middleware to all routes
app.use('/path', middleware)Apply middleware to specific path prefix
(req, res, next) => {}Middleware function signature
next()Pass control to next middleware or route handler
next(err)Pass error to error-handling middleware
next('route')Skip remaining handlers in current route stack
next('router')Skip remaining middleware in this Router and continue in the calling layer
express.json()Parse JSON request bodies (built-in)
express.json({ limit: '10mb' })Parse JSON with body size limit
express.urlencoded({ extended: true })Parse URL-encoded form bodies (built-in)
express.urlencoded({ extended: false })Parse URL-encoded using querystring (no nested objects)
express.static('public')Serve static files from "public" directory
express.static('public', { maxAge: '1d' })Serve static files with cache control
express.raw()Parse raw binary request bodies as Buffer
express.text()Parse text/plain request bodies as string
app.use(cors())Enable CORS for all routes (requires cors package)
app.use(helmet())Set security headers (requires helmet package)
app.use(morgan('dev'))HTTP request logger (requires morgan package)
app.use(compression())Gzip compress responses (requires compression package)

Error Handling

(err, req, res, next) => {}Error-handling middleware signature (4 params required)
app.use((err, req, res, next) => { ... })Register error handler (must be after all other app.use())
next(new Error('Something failed'))Pass error to error-handling middleware
err.status / err.statusCodeError HTTP status code (Express uses err.status)
err.messageError message string
res.status(err.status || 500).json({ error: err.message })Common error response pattern
app.use((req, res) => res.status(404).send('Not found'))Catch-all 404 handler (register last)
class AppError extends Error { constructor(msg, status) {...} }Custom error class with status code
throw new Error('msg')Synchronous errors caught automatically in route handlers
async (req, res, next) => { try { ... } catch(e) { next(e) } }In Express v4, async errors must be caught manually and forwarded with next(err)
require('express-async-errors')Auto-wrap async handlers to forward errors (third-party)
throw new Error('msg') // async, v5Express v5 auto-catches async throws - no try/catch needed
process.on('unhandledRejection', (err) => { ... })Catch unhandled promise rejections globally
process.on('uncaughtException', (err) => { ... })Catch uncaught synchronous exceptions globally

Router

const router = express.Router()Create a modular router instance
router.use(middleware)Apply middleware to all router routes
router.get('/', handler)GET route on router
router.post('/', handler)POST route on router
router.param('id', callback)Pre-processing callback for route param
router.param('id', (req, res, next, id) => {})Load resource by ID before handler runs
router.route('/items').get(listAll).post(create)Chained route handlers on same path
router.route('/items/:id').get(getOne).put(update).delete(remove)Full CRUD on parameterized route
app.use('/api/v1', router)Mount router at versioned API prefix
express.Router({ mergeParams: true })Inherit params from parent router
module.exports = routerExport router for use in main app file
const userRoutes = require('./routes/users')Import route module
app.use('/users', userRoutes)Mount imported user routes

Static Files & Templates

app.use(express.static('public'))Serve files from public/ directory
app.use('/static', express.static('assets'))Serve assets/ at /static URL prefix
express.static('public', { dotfiles: 'ignore' })Ignore dotfiles in static serving
express.static('public', { etag: false })Disable ETag generation
express.static('public', { extensions: ['html'] })Try .html extension if file not found
express.static('public', { index: 'index.html' })Specify default index file
express.static('public', { maxAge: '7d' })Set cache-control max-age
express.static('public', { redirect: false })Disable trailing slash redirect for directories
app.set('view engine', 'ejs')Set EJS as template engine
app.set('view engine', 'pug')Set Pug as template engine
app.set('view engine', 'hbs')Set Handlebars as template engine
app.set('views', './views')Set views directory
app.set('views', ['./views', './partials'])Multiple view directories
res.render('index')Render views/index.ejs (or .pug etc.)
res.render('index', { title: 'Home', user })Render template with data object
res.render('index', (err, html) => res.send(html))Render with callback instead of auto-send

Common Middleware (Third-Party)

cors()Enable CORS with default settings (allow all origins)
cors({ origin: 'https://example.com' })Restrict CORS to specific origin
cors({ origin: ['https://a.com', 'https://b.com'] })Allow multiple origins
cors({ credentials: true })Allow cookies with CORS requests
helmet()Set secure HTTP headers (XSS, HSTS, etc.)
helmet({ contentSecurityPolicy: false })Helmet with CSP disabled
morgan('dev')Concise colored HTTP request logging
morgan('combined')Apache-style combined HTTP request logging
compression()Gzip/deflate response compression
rateLimit({ windowMs: 15*60*1000, max: 100 })Rate limit: 100 req per 15 minutes
upload.single('file')Multer: accept single file upload (field name "file")
upload.array('photos', 5)Multer: accept up to 5 files from "photos" field
upload.fields([{ name: 'avatar' }, { name: 'docs' }])Multer: accept files from multiple fields
body('email').isEmail()express-validator: validate email field
validationResult(req)express-validator: extract validation errors from request
cookieParser(secret)Parse cookies and optionally sign them
session({ secret: 'key', resave: false, saveUninitialized: false })express-session: create session middleware
req.session.userId = user.idStore data in session
req.session.destroy()Destroy session (logout)

Patterns & Best Practices

async (req, res, next) => { try { ... } catch(e) { next(e) } }Async/await error forwarding pattern
const wrap = fn => (req, res, next) => fn(req, res, next).catch(next)Async handler wrapper utility
app.use('/v1', v1Router); app.use('/v2', v2Router)API versioning with separate routers
require('dotenv').config()Load .env file for environment variables
express.json({ limit: '10mb' })Set request body size limit
app.disable('x-powered-by')Hide Express fingerprint from response headers
router.param('userId', loadUser)Load resources by ID with param middleware
// app.js - express config; server.js - app.listen()Separate app config from server startup for testability
module.exports = appExport app without listening (for testing and imports)
process.on('SIGTERM', () => server.close())Graceful shutdown on SIGTERM signal
process.on('SIGINT', () => server.close())Graceful shutdown on Ctrl+C (SIGINT)
// controllers/userController.jsController pattern: separate route logic from route definitions
// services/userService.jsService layer: business logic separate from HTTP handling
res.status(201).json({ id: newItem.id })Return correct status codes (201 Created, etc.)
app.use(express.json()); app.use(express.urlencoded({ extended: false }))Register body parsers before route handlers
if (process.env.NODE_ENV !== 'production') { app.use(morgan('dev')) }Conditional middleware based on environment
const PORT = process.env.PORT || 3000Use environment variable for port with fallback

Testing

npm install --save-dev supertestInstall supertest for HTTP integration testing
const request = require('supertest')Import supertest
request(app).get('/').expect(200)Assert 200 status on GET /
request(app).get('/').expect('Content-Type', /json/)Assert response Content-Type matches regex
request(app).post('/users').send({ name: 'Alice' }).expect(201)POST with body and assert 201 Created
.set('Authorization', 'Bearer token')Set request header in supertest chain
.query({ page: 1, limit: 10 })Set query string parameters in supertest
.then(res => { expect(res.body.name).toBe('Alice') })Assert on response body properties
const res = await request(app).get('/users')Async/await style supertest request
expect(res.statusCode).toBe(200)Jest assertion on status code
expect(res.body).toHaveProperty('id')Jest assertion on body property
beforeAll(async () => { await db.connect() })Set up database before all tests
afterAll(async () => { await db.close() })Clean up database after all tests
jest.mock('./services/emailService')Mock a module for isolated unit testing