Express: маршруты и методы

Маршрут (route) в Express — это сочетание HTTP-метода и пути, связанное с обработчиком (handler-функцией), которая формирует ответ клиенту.

Зачем нужно

Express предоставляет декларативный API для объявления маршрутов вместо ручного if (req.method === 'GET' && req.url === '/users'). Это упрощает читаемость, поддержку middleware и маршрутизацию на основе параметров, регулярных выражений и паттернов.

Где используется

  • Любой HTTP-сервер или REST API на Express
  • Обработка форм (POST-маршруты)
  • Роутинг SPA — перенаправление на index.html
  • Вебхуки — принимать POST от Stripe, GitHub, Telegram

Основной контент

Основные методы

const express = require('express');
const app = express;
app.use(express.json());

// GET — получить ресурс
app.get('/users', (req, res) => {
  res.json([{ id: 1, name: 'Alice' }]);
});

// POST — создать ресурс
app.post('/users', (req, res) => {
  const user = { id: 2, ...req.body };
  res.status(201).json(user);
});

// PUT — полная замена ресурса
app.put('/users/:id', (req, res) => {
  res.json({ id: req.params.id, ...req.body });
});

// PATCH — частичное обновление
app.patch('/users/:id', (req, res) => {
  res.json({ id: req.params.id, updated: req.body });
});

// DELETE — удалить ресурс
app.delete('/users/:id', (req, res) => {
  res.status(204).send;
});

Параметры маршрута

// :id — обязательный параметр
app.get('/users/:id', (req, res) => {
  console.log(req.params.id); // '42'
  res.json({ id: req.params.id });
});

// :category?  — необязательный параметр (? в конце)
app.get('/products/:category?', (req, res) => {
  const { category = 'all' } = req.params;
  res.json({ category });
});

// Wildcard — любой путь
app.get('/files/*', (req, res) => {
  console.log(req.params[0]); // 'docs/readme.txt'
});

Query строка и body

// GET /search?q=node&limit=10
app.get('/search', (req, res) => {
  const { q = '', limit = 20 } = req.query;
  res.json({ query: q, limit: Number(limit) });
});

// POST /login  body: { email, password }
app.post('/login', (req, res) => {
  const { email, password } = req.body;
  // req.body доступен благодаря express.json() middleware
  res.json({ email });
});

app.route — цепочка методов

// Все методы для одного пути
app.route('/articles/:id')
  .get((req, res) => res.json({ id: req.params.id }))
  .put((req, res) => res.json({ updated: true }))
  .delete((req, res) => res.status(204).send);

app.all — все HTTP-методы

// Срабатывает для GET, POST, PUT, DELETE и т.д.
app.all('/api/*', (req, res, next) => {
  console.log(`${req.method} ${req.path}`);
  next;
});

Несколько обработчиков (middleware chain)

const authenticate = (req, res, next) => {
  if (!req.headers.authorization) return res.status(401).json({ error: 'Unauthorized' });
  next;
};

const validate = (req, res, next) => {
  if (!req.body.name) return res.status(400).json({ error: 'name required' });
  next;
};

app.post('/users', authenticate, validate, (req, res) => {
  res.status(201).json({ name: req.body.name });
});

Частые ошибки

  • Отправить ответ дважды — вызвать res.json и потом res.send в одном обработчике: "Cannot set headers after they are sent"
  • Не вызвать next — запрос зависает, если обработчик не отправил ответ и не передал управление дальше
  • Порядок маршрутов/users/me должен быть ВЫШЕ /users/:id, иначе "me" будет интерпретирован как id
  • req.body пуст — не подключён express.json или express.urlencoded middleware

Связанные темы

Ресурсы