Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Проверка данных формы

Валидация — проверка данных до того, как их сохранить. Посетитель может отправить пустой заголовок, слишком длинный текст или вообще не то поле. Сервер обязан проверить всё сам: проверки в браузере легко обойти.

Ручная проверка

Самый простой вариант — несколько условий в обработчике store из прошлого урока:

// src/controllers/postsController.js
export function store(req, res) {
  const title = String(req.body.title ?? '').trim();
  const body = String(req.body.body ?? '').trim();
  const errors = [];
 
  if (title.length < 3) {
    errors.push('Заголовок — не короче 3 символов');
  }
  if (body === '') {
    errors.push('Напишите текст статьи');
  }
 
  if (errors.length > 0) {
    return res.status(422).render('posts/new', {
      title: 'Новая статья',
      errors,
      values: { title, body },
    });
  }
 
  const post = { id: posts.length + 1, title, body };
  posts.push(post);
  res.redirect(`/posts/${post.id}`);
}

При ошибке форма показывается снова с кодом 422 — «данные не прошли проверку». Перенаправлять здесь не нужно: посетитель должен увидеть свои введённые значения.

Ошибки в шаблоне

Добавьте в views/posts/new.ejs вывод ошибок и верните введённые значения в поля:

<% if (locals.errors) { %>
  <ul class="errors">
    <% for (const error of errors) { %>
      <li><%= error %></li>
    <% } %>
  </ul>
<% } %>
 
<form method="post" action="/posts">
  <input name="title" value="<%= locals.values?.title ?? '' %>">
  <textarea name="body"><%= locals.values?.body ?? '' %></textarea>
  <button>Опубликовать</button>
</form>

locals — объект со всеми данными шаблона. Через него можно проверить переменную, которую не передали: при первом показе формы errors нет, и без locals. шаблон упал бы с ошибкой.

Проверка через Zod

Когда полей много, условия разрастаются. Библиотека Zod описывает правила одной схемой:

npm install zod

Создайте файл src/validation/postSchema.js:

// src/validation/postSchema.js
import { z } from 'zod';
 
export const postSchema = z.object({
  title: z.string().trim().min(3, 'Заголовок — не короче 3 символов').max(120, 'Заголовок — не длиннее 120 символов'),
  body: z.string().trim().min(1, 'Напишите текст статьи'),
});

Метод safeParse() не выбрасывает исключение, а возвращает результат с полем success:

// src/controllers/postsController.js
import { postSchema } from '../validation/postSchema.js';
 
export function store(req, res) {
  const result = postSchema.safeParse(req.body);
 
  if (!result.success) {
    return res.status(422).render('posts/new', {
      title: 'Новая статья',
      errors: result.error.issues.map((issue) => issue.message),
      values: req.body,
    });
  }
 
  const post = { id: posts.length + 1, ...result.data };
  posts.push(post);
  res.redirect(`/posts/${post.id}`);
}

Отправьте форму с заголовком «Hi» — над формой появится «Заголовок — не короче 3 символов». В result.data лежат уже очищенные значения: без пробелов по краям и только с описанными в схеме полями.

Частая ошибка

Атрибуты required и minlength в HTML удобны, но это только подсказка браузеру. Запрос можно отправить через curl или изменить форму в инструментах разработчика. Оставляйте их для удобства посетителя, но всегда повторяйте проверку на сервере.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.