JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Парсинг тела запроса в Express

Парсинг тела запроса в Express

Модуль 4: Node.js, Next.js и Angular
5 уровень , 5 лекция
Открыта

1. Зачем нужен парсинг тела запроса?

Когда клиент (браузер, мобильное приложение, Postman или fetch-запрос) отправляет данные на сервер методом POST, PUT или PATCH, эти данные обычно помещаются в "тело запроса" (request body). Например, вы заполняете форму регистрации, нажимаете "Отправить" — и браузер шлёт данные на сервер.

Но Express по умолчанию не умеет "читать мысли" и не парсит тело запроса автоматически. Если вы попытаетесь вывести req.body, получите undefined или пустой объект. Почему? Потому что тело запроса — это просто "сырой поток байтов", который нужно разобрать в удобный для работы вид.

Парсинг тела запроса — это процесс превращения этого "сырого потока" в объект JavaScript, с которым удобно работать в обработчиках Express.

Какие бывают типы тела запроса?

В реальных приложениях чаще всего встречаются два формата передачи данных в теле запроса:

  • JSON
    Современные SPA, мобильные приложения и API любят отправлять данные в формате JSON (application/json). Пример тела запроса:
    {
      "username": "alice",
      "password": "qwerty"
    }
  • x-www-form-urlencoded
    Это стандартный формат, который используют обычные HTML-формы при отправке через <form method="POST"> (если не указать enctype). Пример тела запроса:
    username=alice&password=qwerty

Есть ещё multipart/form-data (для загрузки файлов), но о нём поговорим позже, когда будем разбирать загрузку файлов.

2. Почему Express не парсит тело сам?

Express — это минималистичный фреймворк. Он не парсит тело запроса "по умолчанию", чтобы не тратить ресурсы на ненужную обработку, если ваше приложение этого не требует. Для разбора тела Express использует middleware — специальные функции, которые подключаются к вашему приложению и "ловят" запросы на ранней стадии.

В старых версиях Express (до 4.x) был встроенный middleware bodyParser, но сейчас его основные функции вынесены в отдельные модули и встроены в сам Express.

Middleware для парсинга тела: express.json() и express.urlencoded()

В Express 4.x и выше есть два встроенных middleware для парсинга тела запроса:

  • express.json() — для разбора тела в формате JSON.
  • express.urlencoded() — для разбора данных, закодированных как x-www-form-urlencoded (обычные HTML-формы).

Как подключить парсеры?

Всё очень просто: достаточно вызвать их как middleware до объявления ваших маршрутов.

const express = require('express');
const app = express();

// Подключаем парсер JSON
app.use(express.json());

// Подключаем парсер для form-urlencoded
app.use(express.urlencoded({ extended: true }));

// Ваши маршруты идут ниже!

Внимание:
Порядок важен! Сначала подключаем парсеры, потом объявляем маршруты.

3. Пример: Получаем JSON из POST-запроса

Давайте разберём классический пример: пользователь отправляет данные регистрации через JSON.

Клиент отправляет такой запрос:

{
  "username": "bob",
  "email": "bob@example.com"
}

Сервер — код Express:

const express = require('express');
const app = express();

// Подключаем JSON-парсер
app.use(express.json());

app.post('/register', (req, res) => {
  // Теперь req.body — это объект с данными!
  console.log(req.body);
  // { username: 'bob', email: 'bob@example.com' }

  // Можно делать что угодно: валидация, запись в базу и т.д.
  res.send(`Привет, ${req.body.username}!`);
});

app.listen(3000, () => {
  console.log('Сервер запущен на http://localhost:3000');
});

Как проверить?
Можно воспользоваться Postman, curl или fetch в браузере:

curl -X POST http://localhost:3000/register \
  -H "Content-Type: application/json" \
  -d '{"username":"bob","email":"bob@example.com"}'

4. Пример: Получаем данные из HTML-формы

Если пользователь отправляет данные через обычную HTML-форму (без загрузки файлов):

<form action="/register" method="POST">
  <input name="username">
  <input name="email">
  <button type="submit">Зарегистрироваться</button>
</form>

Тогда браузер отправит данные в формате x-www-form-urlencoded:
username=alice&email=alice@example.com

Сервер — код Express:

const express = require('express');
const app = express();

// Подключаем парсер для form-urlencoded
app.use(express.urlencoded({ extended: true }));

app.post('/register', (req, res) => {
  // req.body — объект с данными формы!
  console.log(req.body);
  // { username: 'alice', email: 'alice@example.com' }

  res.send(`Спасибо за регистрацию, ${req.body.username}!`);
});

app.listen(3000, () => {
  console.log('Сервер запущен на http://localhost:3000');
});

Как проверить?
Можно отправить форму из браузера или воспользоваться curl:

curl -X POST http://localhost:3000/register \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=alice&email=alice@example.com"

5. Полезные нюансы

Что значит { extended: true }?

В опциях для express.urlencoded() есть параметр extended:

  • extended: false — использует встроенный парсер Node.js (ограниченный, только строки и массивы).
  • extended: true — использует библиотеку qs, которая умеет парсить вложенные объекты и массивы.

В 99% случаев используйте extended: true — так вы сможете получать сложные структуры из формы, например:

<input name="user[name]" value="Bob">
<input name="user[email]" value="bob@example.com">

Результат в req.body:

{
  user: {
    name: 'Bob',
    email: 'bob@example.com'
  }
}

Совмещаем оба парсера: JSON и urlencoded

В реальных приложениях часто нужно поддерживать оба варианта. Просто подключите оба парсера:

const express = require('express');
const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// ... ваши маршруты

Express сам разберётся, какой парсер применить, исходя из заголовка Content-Type в запросе клиента.

6. Практика: Развиваем наше мини-приложение

Давайте добавим в наше учебное приложение новый маршрут для добавления задач в список дел (todo list). Мы хотим поддерживать оба варианта: отправку через JSON (например, из fetch) и через HTML-форму.

Серверный код:

const express = require('express');
const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Наш массив задач (в памяти)
const todos = [];

// Добавление задачи
app.post('/todos', (req, res) => {
  // req.body работает и для JSON, и для формы!
  const { title } = req.body;
  if (!title) {
    return res.status(400).json({ error: 'Не указано название задачи' });
  }
  const todo = { id: todos.length + 1, title };
  todos.push(todo);
  res.status(201).json(todo);
});

// Получение всех задач
app.get('/todos', (req, res) => {
  res.json(todos);
});

app.listen(3000, () => {
  console.log('TODO-сервер запущен на http://localhost:3000');
});

Проверяем через curl:

Через JSON:

curl -X POST http://localhost:3000/todos \
  -H "Content-Type: application/json" \
  -d '{"title":"Купить хлеб"}'

Через форму:

curl -X POST http://localhost:3000/todos \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "title=Позвонить маме"

7. Типичные ошибки при парсинге тела запроса

Ошибка №1: забыли подключить парсер.
Самая частая ошибка: забыли добавить app.use(express.json()) или app.use(express.urlencoded()), и req.body всегда пустой. Если вы видите undefined или {} вместо ожидаемых данных — проверьте, что парсер подключён!

Ошибка №2: не тот Content-Type у клиента.
Если клиент отправляет JSON, но не указал заголовок Content-Type: application/json, парсер не сработает, и req.body будет пустым. Аналогично с формами: нужен application/x-www-form-urlencoded.

Ошибка №3: неправильный порядок middleware.
Если парсер подключён после маршрутов, он не сработает для этих маршрутов. Всегда подключайте парсеры ДО объявления роутов.

Ошибка №4: забыли про вложенные объекты в формах.
Если используете вложенные поля в форме (например, user[name]), обязательно выставляйте extended: true в express.urlencoded().

Ошибка №5: не обрабатываете ошибку парсинга.
Если клиент отправил некорректный JSON, Express вернёт ошибку 400. Можно добавить обработчик ошибок, чтобы красиво сообщать о проблеме.

Ошибка №6: используете устаревший body-parser.
В старых туториалах часто встречается const bodyParser = require('body-parser'). Сейчас это не нужно — всё уже встроено в Express.

1
Задача
Модуль 4: Node.js, Next.js и Angular, 5 уровень, 5 лекция
Недоступна
Использование express.json() для парсинга JSON-запроса
Использование express.json() для парсинга JSON-запроса
1
Задача
Модуль 4: Node.js, Next.js и Angular, 5 уровень, 5 лекция
Недоступна
Обработка данных из HTML-формы с помощью express.urlencoded()
Обработка данных из HTML-формы с помощью express.urlencoded()
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ