Express.js
Express.js is a small web framework for Node.js.
It is mainly used to build:
- web servers
- REST APIs
- server-rendered websites
Backend
Section titled “Backend”Before building a backend, it helps to know the main concepts you usually find in one.
- installation
- basic app
- serving static files
- routing
- request and response
- status codes
- middleware
- database integration
- frontend integration
- file uploads
Installation
Section titled “Installation”For this course, a simple setup is:
npm install expressBasic App
Section titled “Basic App”import express from 'express';
const app = express();const port = process.env.PORT || 3000;
app.get('/', (req, res) => { res.send('Hello from Express');});
app.listen(port, () => { console.log(`Server running on http://localhost:${port}`);});Serving Static Files
Section titled “Serving Static Files”Static files are files the server sends directly, such as:
- images
- CSS files
- JavaScript files
In Express, you can serve them with express.static().
app.use(express.static('public'));If your project has this file:
public/logo.png
Then the browser can request:
/logo.png
If your project has this file:
public/uploads/avatar.jpg
Then the browser can request:
/uploads/avatar.jpg
This is useful for things like website images, CSS, and frontend JavaScript files.
Routing
Section titled “Routing”Routing means deciding which code runs for a request.
A route is based on:
- the HTTP method
- the path
Examples:
app.get('/users', (req, res) => { res.json([{ id: 1, name: 'Alice' }]);});
app.get('/users/:id', (req, res) => { res.json({ id: req.params.id, name: 'Alice' });});
app.post('/users', (req, res) => { res.status(201).json({ message: 'User created' });});
app.put('/users/:id', (req, res) => { res.json({ message: `User ${req.params.id} updated` });});
app.delete('/users/:id', (req, res) => { res.json({ message: `User ${req.params.id} deleted` });});Route Params
Section titled “Route Params”Use route params for one specific item.
app.get('/users/:id', (req, res) => { res.json({ id: req.params.id });});Request:
GET /users/42
Query Params
Section titled “Query Params”Use query params for filtering or searching.
app.get('/users', (req, res) => { const { role } = req.query; res.json({ role });});Request:
GET /users?role=admin
Routers
Section titled “Routers”Routers help split large apps into smaller files.
import express from 'express';
const router = express.Router();
router.get('/', (req, res) => { res.send('All users');});
export default router;Mount the router in the main app:
app.use('/users', router);Request and Response
Section titled “Request and Response”Every route handler receives:
reqfor the incoming requestresfor the outgoing response
Example:
app.get('/info', (req, res) => { res.json({ method: req.method, path: req.path, headers: req.headers, });});You will often read data from req and send data back with res.
Status Codes
Section titled “Status Codes”Status codes tell the client what happened.
HTTP status codes are grouped like this:
1xxinformational2xxsuccess3xxredirect4xxclient error5xxserver error
Common examples:
res.status(200).json({ ok: true });res.status(201).json({ created: true });res.status(204).send();res.status(400).json({ error: 'Invalid data' });res.status(401).json({ error: 'Unauthorized' });res.status(403).json({ error: 'Forbidden' });res.status(404).json({ error: 'Not found' });res.status(500).json({ error: 'Internal Server Error' });Middleware
Section titled “Middleware”Middleware is a function that runs between request and response.
Middleware can:
- run code
- change
reqorres - stop the request
- call
next()to continue
Security
Section titled “Security”Authentication is often checked with middleware before a protected route runs.
export function authCheck(req, res, next) { const token = req.headers.authorization;
if (!token) { return res.status(401).json({ error: 'Unauthorized' }); }
next();}import { authCheck } from './middlewares/auth.js';
app.get('/profile', authCheck, (req, res) => { res.json({ message: 'Private profile data' });});Error Handling
Section titled “Error Handling”Errors should not crash the app without a clear response.
Simple Error Example
Section titled “Simple Error Example”app.get('/error', (req, res) => { throw new Error('Something went wrong');});Error Middleware
Section titled “Error Middleware”Error middleware has 4 parameters:
app.use((err, req, res, next) => { console.error(err.message); res.status(500).json({ error: 'Internal Server Error' });});Database Integration
Section titled “Database Integration”Express does not include a database by itself.
You connect a database by installing a Node.js driver.
For MySQL, a common package is:
npm install mysql2Create a Connection Pool
Section titled “Create a Connection Pool”import mysql from 'mysql2/promise';
export const pool = mysql.createPool({ host: process.env.DB_HOST || '', user: process.env.DB_USER || '', password: process.env.DB_PASSWORD || '', database: process.env.DB_NAME || '',});Query from a Route
Section titled “Query from a Route”import { pool } from './db.js';
app.get('/users', async (req, res, next) => { try { const [rows] = await pool.query('SELECT id, name, email FROM users'); res.json(rows); } catch (err) { next(err); }});SQL Parameters
Section titled “SQL Parameters”import { pool } from './db.js';
app.get('/users/:id', async (req, res, next) => { try { const [rows] = await pool.query( 'SELECT id, name, email FROM users WHERE id = ?', [req.params.id], );
res.json(rows[0]); } catch (err) { next(err); }});Frontend Integration
Section titled “Frontend Integration”Template engines let the server generate HTML pages with data.
For this subject, use EJS.
Install it when you need server-rendered pages:
npm install ejsSetup:
app.set('view engine', 'ejs');app.set('views', './views');Route:
app.get('/', (req, res) => { res.render('index', { title: 'Users', users: ['Alice', 'Bob', 'Charlie'], });});Example views/index.ejs:
<!DOCTYPE html><html> <head> <title><%= title %></title> </head> <body> <h1><%= title %></h1>
<ul> <% users.forEach((user) => { %> <li><%= user %></li> <% }) %> </ul> </body></html>This is useful when you want to loop over data and render HTML for each item.
File Uploads
Section titled “File Uploads”For file uploads, a common package is:
npm install multerSimple example:
import multer from 'multer';
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('avatar'), (req, res) => { res.json({ filename: req.file.filename });});Debugging
Section titled “Debugging”Debugging means finding out what the server is doing.
Simple ways:
- use
console.log() - test routes with Postman or the browser
- use the Express debug logs
Run Express with debug output:
DEBUG=express:* node server.jsThis shows useful internal logs for:
- routes
- middleware
- rendering