Зарегистрируйтесь, чтобы продолжить обучение

Модифицирующие формы JS: Веб-разработка

В этом уроке мы изучим формы, которые меняют данные. И с клиентской, и с серверной стороны они обычно устроены сложнее, чем поисковые формы. Для уверенной работы с ними нужно разбираться:

  • Как работают соответствующие HTML-теги
  • Как отправляются формы по HTTP
  • Как происходит обработка на стороне сервера
  • Как работает валидация и вывод ошибок

Все это мы изучим в ближайшее время.

Вывод формы

За вывод формы и ее обработку должны отвечать два разных маршрута — а значит, еще и два обработчика. Рассмотрим примеры маршрутов для создания нового пользователя:

  • GET /users/new — страница с формой, которую заполняет пользователь. Эта форма отправляет POST-запрос на адрес /users, указанный в атрибуте action
  • POST /users — маршрут, обрабатывающий данные формы

Добавим обработчик маршрута /users/new, который выводит форму добавления пользователя:

app.get('/users/new', (req, res) => {
  res.view('src/views/users/new')
})

Создадим форму в файле src/views/users/new.pug

html
  body
    form(action = '/users', method = 'post')
      div
        label Имя:
          input(type = 'text', name = 'name')
      div
        label Email:
          input(type = 'email', name = 'email', required = true)
      div
        label Пароль:
          input(type = 'password', name = 'password', required = true)
      div
        label Подтверждение пароля:
          input(type = 'password', name = 'passwordConfirmation', required = true)
      input(type = 'submit', value = 'Зарегистрировать')

Запустите сервер и убедитесь, что форма выводится по адресу /users/new. Если ее заполнить и попытаться отправить, то браузер сформирует следующий HTTP-запрос:

# Данные взяты для примера

POST /users HTTP/1.1
Host: localhost
Content-type: application/x-www-form-urlencoded
Content-length: 76

name=Mike&email=example@test.com&password=qwerty&passwordConfirmation=qwerty

В примере выше мы видели работу с HTTP, но на практике все устроено немного по-другому. Не стоит передавать электронную почту, пароль и другие чувствительные данные по обычному HTTP-протоколу, потому что так данные легко перехватить и использовать не по назначению.

Именно поэтому современные сайты обычно работают по протоколу HTTPS, который передает данные в зашифрованном виде.

Обработка данных

Форма готова, теперь можно реализовывать ее обработчик. Обработчик формы работает так:

  • Извлекает параметры формы
  • Формирует объект пользователя на основе этих параметров
  • Сохраняет пользователя в базу данных
  • Выполняет редирект — например, на страницу пользователей

Все данные приходят в виде строки. Удобнее всего добавить плагин, который будет помогать парсить тело запроса. Для этого устанавливаем нужный пакет:

npm i @fastify/formbody

И подключаем плагин в приложение:

import fastify from 'fastify'
import formbody from '@fastify/formbody'

const app = fastify()

await app.register(formbody)

Код обработчика выглядит так:

app.post('/users', (req, res) => {
  const user = {
    name: req.body.name,
    email: req.body.email,
    password: req.body.password,
  }

  state.users.push(user)

  res.redirect('/users')
})

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

Нормализация данных

Представим, что при регистрации пользователь написал свою почту в произвольном регистре — MYname@example.com вместо myname@example.com. По спецификации, адреса электронной почты не зависят от регистра. Другими словами, если в двух адресах совпадают буквы, то они считаются одним и тем же адресом.

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

  • Пользователь сможет зарегистрировать несколько аккаунтов на один и тот же адрес почты, просто вводя адрес в разном регистре
  • Пользователь не сможет зайти на сайт, если введет почту не в том регистре, который использовал при регистрации

Чтобы этого не происходило, введенные пользователями данные проходят нормализацию. В случае почты мы приводим ее к нижнему регистру:

// Касается только емейла
const user = {
  name: req.body.name,
  email: req.body.email.toLowerCase(),
  password: req.body.password,
}

Пользователь может не только ошибиться в регистре, но и случайно поставить пробелы в конце или в начале строк — например, из-за копирования. Иногда мы не можем на это влиять. Например, пользователь может специально добавить пробельный символ в начале и конце пароля.

А вот для имени и адреса почты такое недопустимо. Поэтому лучше обрезать концевые пробелы для надежности:

const user = {
  name: req.body.name.trim(),
  email: req.body.email.trim().toLowerCase(),
  password: req.body.password,
}

Самостоятельная работа

  1. Выполните у себя на компьютере все шаги из урока. Добавьте в приложение форму и обработчики для добавления нового пользователя. Не забудьте сделать нормализацию email пользователя.
  2. Измените код приложения так, чтобы пользователи в обработчиках подтягивались из репозитория
  3. Запустите приложение и попробуйте добавлять новых пользователей. Проверьте, что происходит редирект на страницу просмотра всех пользователей и в списке пользователей отображается новый пользователь
  4. Сделайте то же самое для курсов и залейте изменения на GitHub

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff