iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Express

Express is the de-facto Node web framework. Routes, middleware, and a minimal request/response API — small enough to fit in your head, big enough to ship a real app.

Routes, middleware, error handling, validation

EXAMPLE
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import { z } from 'zod';

const app = express();

// 1) Global middleware — order matters
app.use(helmet());                    // sensible security headers
app.use(cors({ origin: 'https://app.example.com', credentials: true }));
app.use(express.json({ limit: '100kb' }));
app.use((req, _res, next) => {
    console.log(`${req.method} ${req.url}`);
    next();
});

// 2) Routes
app.get('/health', (_req, res) => res.json({ ok: true }));

app.get('/users/:id', async (req, res, next) => {
    try {
        const user = await db.users.findOne({ id: req.params.id });
        if (!user) return res.status(404).json({ error: 'not found' });
        res.json(user);
    } catch (e) { next(e); }
});

// 3) Validate input — Zod schema
const NewUser = z.object({
    email: z.string().email(),
    name:  z.string().min(1).max(100),
});

app.post('/users', async (req, res, next) => {
    try {
        const data = NewUser.parse(req.body);
        const user = await db.users.create(data);
        res.status(201).json(user);
    } catch (e) {
        if (e instanceof z.ZodError) return res.status(400).json({ errors: e.issues });
        next(e);
    }
});

// 4) Routers — split routes across files
import { Router } from 'express';
const posts = Router();
posts.get('/', listPosts);
posts.get('/:id', getPost);
posts.post('/', createPost);
app.use('/posts', posts);

// 5) Auth middleware
function requireAuth(req, res, next) {
    const token = req.headers.authorization?.replace('Bearer ', '');
    const user = token && verifyJWT(token);
    if (!user) return res.status(401).json({ error: 'unauthenticated' });
    req.user = user;
    next();
}
app.get('/me', requireAuth, (req, res) => res.json(req.user));

// 6) Global error handler — last middleware, 4 args
app.use((err, _req, res, _next) => {
    console.error(err);
    res.status(err.status ?? 500).json({ error: err.message ?? 'internal' });
});

// 7) Listen
const port = process.env.PORT ?? 3000;
const server = app.listen(port, () => console.log(`http://localhost:${port}`));

// 8) Graceful shutdown
for (const sig of ['SIGINT', 'SIGTERM']) {
    process.on(sig, () => server.close(() => process.exit(0)));
}

Why it matters

Move every route into a Router and keep app.ts small — security headers, body parsing, error handler. The pattern scales from a side project to 200 routes without surprises.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
import express from 'express';
const app = express();
app.get('/', (req, res) => res.send('Hello!'));
app.listen(3000);
Try it Yourself »

Exercise

Define a GET route.

app. ('/', (req, res) => res.send('Hi'));

Test yourself

Q1. Define a route with…
Q2. Middleware signature is…
Q3. Body parsing JSON needs…

Discussion

Loading…