Express Basics

Routing, middleware, and request handling with the most popular Node.js web framework

Why Express?

Express is the most popular Node.js web framework. It provides routing, middleware, and utilities that make web development much easier than using raw http.

Compare Module 02's routing code to Express:

Raw Node.js (http module) Express
if (req.url === '/about' && req.method === 'GET') { res.writeHead(200, {...}); res.end('About page'); } app.get('/about', (req, res) => { res.send('About page'); });

Express handles URL parsing, headers, and much more automatically.

Getting Started with npm

Express is installed via npm (Node Package Manager):

# Create a new project mkdir my-app cd my-app # Initialize package.json npm init -y # Install Express npm install express

This creates:

  • package.json — Project metadata and dependencies
  • node_modules/ — Installed packages (don't commit to git)
  • package-lock.json — Exact versions (do commit)

Hello Express

// hello-express.js const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Hello World!'); }); app.listen(3000, () => { console.log('Server running on http://localhost:3000'); });

That's it! No manual URL parsing, no header management, no content-type setting.

Routing

Express provides methods for each HTTP verb:

// GET request app.get('/users', (req, res) => { res.send('Get all users'); }); // POST request app.post('/users', (req, res) => { res.send('Create a user'); }); // PUT request app.put('/users/:id', (req, res) => { res.send(`Update user ${req.params.id}`); }); // DELETE request app.delete('/users/:id', (req, res) => { res.send(`Delete user ${req.params.id}`); });

Route Parameters

// :id is a parameter app.get('/users/:id', (req, res) => { const userId = req.params.id; // Access the parameter res.send(`User ID: ${userId}`); }); // Multiple parameters app.get('/posts/:year/:month', (req, res) => { const { year, month } = req.params; res.send(`Posts from ${month}/${year}`); });

Query Strings

// URL: /search?q=nodejs&page=2 app.get('/search', (req, res) => { const query = req.query.q; // 'nodejs' const page = req.query.page; // '2' res.send(`Searching for: ${query}, page ${page}`); });

Reading Request Data

Express provides convenient ways to access all parts of a request:

Headers

// Express provides req.get() as a shortcut app.get('/info', (req, res) => { const userAgent = req.get('user-agent'); // Cleaner than req.headers['user-agent'] const contentType = req.get('content-type'); const host = req.get('host'); // Client IP (handles proxies) const clientIP = req.ip; // or req.headers['x-forwarded-for'] res.json({ userAgent, contentType, host, clientIP }); });

Request Body

To access POST data in req.body, you must enable the parsing middleware first:

// IMPORTANT: Add these BEFORE your routes! app.use(express.json()); // For JSON bodies app.use(express.urlencoded({ extended: true })); // For form bodies app.post('/login', (req, res) => { // Now req.body contains the parsed data const { username, password } = req.body; res.json({ received: { username, password } }); });

Comparison: Raw Node.js vs Express

Task Raw Node.js Express
Query string url.parse(req.url, true).query req.query
Route parameters Manual URL parsing req.params
Headers req.headers['user-agent'] req.get('user-agent')
POST body Collect stream chunks manually req.body (with middleware)
Client IP req.connection.remoteAddress req.ip

Response Methods

Express provides convenient response methods:

// Send plain text or HTML res.send('Hello'); res.send('

Hello

'); // Send JSON (sets Content-Type automatically) res.json({ name: 'Alice', age: 25 }); // Send a file res.sendFile('/path/to/file.html'); // Set status code res.status(404).send('Not found'); // Redirect res.redirect('/other-page'); res.redirect(301, '/permanent-redirect');

Serving Static Files

Remember the complex static file code from Module 02? Express does it in one line:

// Serve files from the 'public' directory app.use(express.static('public'));

Now files in public/ are accessible:

  • public/style.csshttp://localhost:3000/style.css
  • public/images/logo.pnghttp://localhost:3000/images/logo.png

Middleware

Middleware functions run before your route handlers. They can:

  • Log requests
  • Parse request bodies
  • Check authentication
  • Modify request/response objects
// Middleware runs for ALL requests app.use((req, res, next) => { console.log(`${req.method} ${req.url}`); next(); // Continue to the next handler }); // Built-in middleware for parsing JSON app.use(express.json()); // Built-in middleware for parsing form data app.use(express.urlencoded({ extended: true }));

Middleware and Route Ordering

In Express, order matters. Middleware and routes are processed in the order they're defined. This is a common source of bugs.

Middleware Must Come Before Routes

// WRONG - body parser comes after route app.post('/data', (req, res) => { console.log(req.body); // undefined! }); app.use(express.json()); // Too late! // CORRECT - body parser comes first app.use(express.json()); // Parse JSON bodies app.post('/data', (req, res) => { console.log(req.body); // Works! });

Route Order Matters

// WRONG - catch-all route comes first app.get('/users/*', (req, res) => { res.send('Catch all'); }); app.get('/users/profile', (req, res) => { res.send('Profile page'); // Never reached! }); // CORRECT - specific routes first app.get('/users/profile', (req, res) => { res.send('Profile page'); // Matches first }); app.get('/users/*', (req, res) => { res.send('Catch all'); // Only if above didn't match });

404 Handler Must Be Last

// WRONG - 404 handler catches everything app.use((req, res) => { res.status(404).send('Not found'); }); app.get('/about', (req, res) => { res.send('About'); // Never reached! }); // CORRECT - 404 at the very end app.get('/about', (req, res) => { res.send('About'); }); // ... all other routes ... app.use((req, res) => { res.status(404).send('Not found'); // Only unmatched requests reach here });

Complete Example

// routes.js - Complete Express example const express = require('express'); const app = express(); // Middleware app.use(express.json()); app.use(express.static('public')); // Routes app.get('/', (req, res) => { res.send('

Welcome

View Items'); }); // API routes app.get('/api/items', (req, res) => { res.json([ { id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' } ]); }); app.get('/api/items/:id', (req, res) => { res.json({ id: req.params.id, name: `Item ${req.params.id}` }); }); app.post('/api/items', (req, res) => { const newItem = req.body; res.status(201).json({ message: 'Created', item: newItem }); }); // 404 handler (must be last) app.use((req, res) => { res.status(404).json({ error: 'Not found' }); }); app.listen(3000);

Summary

  • Express simplifies routing with app.get(), app.post(), etc.
  • Use :param for route parameters, req.query for query strings
  • Access headers with req.get('header-name') or req.headers
  • Access POST data with req.body (requires express.json() or express.urlencoded() middleware)
  • Response methods: res.send(), res.json(), res.redirect()
  • Static files: app.use(express.static('folder'))
  • Middleware processes requests before route handlers
  • Order matters: Middleware before routes, specific routes before catch-alls, 404 handler last