Воспроизведение запроса
Сообщение «Не удалось загрузить: HTTP 400» объясняет, что сервер отверг запрос, но ещё не показывает причину. Чтобы передать ошибку другому разработчику, нужно сохранить минимальные условия: какое действие построило адрес, какие данные были отправлены и что сервер ожидал вместо них.
В lesson-22 архива специально добавлена опечатка при выборе «Фронтенд». Используется только локальная учебная лаборатория и GET с вымышленными данными. Запросы, команды и исправление не выполнялись; сценарий показывает ожидаемую причину и подготовленный правильный файл.
Ошибка построения параметра
HTML содержит правильное значение option: frontend. Однако JavaScript начального снимка заменяет его при построении запроса:
const topic = select.value === "frontend" ? "fronted" : select.value;
Поэтому после выбора «Фронтенд» и нажатия загрузки ожидается GET /api/courses?topic=fronted. Сервер принимает только all, frontend, publishing. Ошибка находится в клиентском преобразовании значения, а не в сохранённой настройке или доступности существующего курса.
Сначала откройте Network до действия, выберите тему и выполните одну загрузку. Прочитайте полный адрес и инициатор. Затем прочитайте Response: ожидается Problem JSON со статусом 400 и пояснением допустимых значений. Наша страница выводит только HTTP 400, потому что обработчик проверяет response.ok до чтения успешного JSON.
Это различие важно для записи ошибки. Текст интерфейса содержит меньше информации, чем сетевой ответ, но оба соответствуют одному действию. Если записать только снимок пустой формы или старого списка, другой автор не увидит опечатку в параметре и может начать исследование не с того места.
Минимальный самостоятельный запрос
Для учебного API достаточно одного адреса и заголовка Accept. Cookie не управляет доступом, localStorage не отправляется автоматически, тело у GET отсутствует. Поэтому подготовленная команда для будущего ручного воспроизведения короткая:
curl -i 'http://127.0.0.1:4310/api/courses?topic=fronted' \
-H 'Accept: application/json'
Она должна получить 400 при работающей нашей лаборатории. Сравните с правильным вариантом:
curl -i 'http://127.0.0.1:4310/api/courses?topic=frontend' \
-H 'Accept: application/json'
Ожидается 200 и два курса. Эти команды не выполнялись. Они не обращаются к ProfessorWeb и не меняют состояние сервера. Самостоятельный запрос показывает, что сервер правильно различает допустимое и ошибочное значение; браузерная форма добавляет объяснение, откуда ошибочное значение появилось.
Для API с авторизацией минимальные условия могли бы включать доступ, CSRF или другое состояние. Здесь такого договора нет. Поэтому не переносите упрощение автоматически в произвольный production-запрос. Сначала определите, какие параметры действительно необходимы для выбранного поведения и какие данные нельзя передавать посторонним.
Копирование без лишних данных
В Network доступны способы копирования запроса. Справочник Chrome описывает работу с сетевыми записями. Копия удобна как исходная точка, но её содержимое нужно прочитать до отправки коллеге: там могут присутствовать cookie, заголовки авторизации и другие данные контекста.
В нашей модели они не нужны для воспроизведения опечатки. Подготовленный пример содержит только локальный URL, метод GET и Accept. Это делает причину видимой: fronted отличается от frontend на одну букву. Десятки автоматических заголовков браузера только затруднили бы чтение маленького учебного договора.
Полный HAR может сохранять множество запросов и ответы. Для данной задачи он избыточен: достаточно одной записи и действий формы. Если в другом исследовании HAR действительно нужен, сначала определите разрешённый состав и удалите лишние данные. Название «экспорт для отладки» само по себе не делает любой журнал пригодным к передаче.
Сохранение условий исследования
В сценарии есть reproduction.md с точным описанием. Укажите исходный файл, выбранную тему, ожидаемый параметр, фактический подготовленный параметр и два возможных ответа. Отдельно запишите, что сервер должен работать на 127.0.0.1:4310, а API поддерживает только чтение.
Начальный вариант: lesson-22/start.
Действие: выбрать Фронтенд, нажать Загрузить курсы.
Запрос по исходнику: GET /api/courses?topic=fronted.
Договор: допустимо frontend, ожидается два курса.
Подготовленный ответ ошибки: 400 Problem JSON.
Выполнение: не проводилось.
Такая запись различает вывод из исходника и результат наблюдения. Если позже запрос действительно выполнен, добавьте окружение и полученные данные отдельно. Не заменяйте «не проводилось» на «проверено» только потому, что команда выглядит правдоподобно или опечатка кажется очевидной.
Нужно также помнить прежний список. При ошибке приложение оставляет карточки последней успешной загрузки. Поэтому наличие двух элементов после 400 не означает, что запрос принят. Запишите статус и новую сетевую запись, а не оценивайте состояние только по числу карточек.
Минимальный запрос и сценарий интерфейса отвечают на разные вопросы. Команда с fronted показывает подготовленное поведение сервера для неверного значения. Выбор «Фронтенд» показывает, почему клиент сформировал именно это значение, хотя HTML содержит правильный вариант. Если сохранить только команду, другой автор может решить, что пользователь вручную ввёл опечатку. Если сохранить только экран, он не увидит существенный параметр. Поэтому материал передачи включает оба уровня, но не копирует весь журнал. Такая композиция позволяет проверить исправление по смыслу: серверный договор сохраняется, а форма перестаёт создавать неверный запрос. Состояние cookie и localStorage не объясняет замену букв в этом снимке исходника. Их можно указать как условия, но не следует назначать причиной без связи с кодом. После правки минимальный ошибочный запрос всё ещё должен получать 400, что подтверждает прежнюю границу API.
Исправление источника значения
В правильном файле убрано ошибочное преобразование:
const topic = select.value;
Остальная работа URL, fetch и обработчика сохраняется. Сервер продолжает отвергать fronted, что полезно: клиентская правка не расширяет договор на опечатки. Подготовленный expected/public/app.js содержит исправление целиком, а остальные исходники совпадают с начальным вариантом.
Постоянные URL карточек не меняются. Ошибка затрагивала параметр фильтра, а не адрес курса. Это различие помогает выбрать узкую правку и не начать случайную миграцию маршрутов ради исправления загрузки. На старом сайте подобное разделение особенно ценно: исправлять внутренний запрос можно, сохраняя внешние входные страницы.
Для будущего ручного чтения верните нормальные сетевые условия и снимите лишние точки останова. Если оставлен Offline или остановленный обработчик, даже правильный файл может показать другой результат. Окружение исследования должно быть частью описания, а не скрытым состоянием компьютера автора.
Конечный результат урока — короткое воспроизведение ошибки, правильный сравниваемый запрос и узкое изменение клиента. Мы сохранили существенные условия, не выдавая ожидаемые ответы за выполненные. В следующем уроке соберём описание проекта так, чтобы другой разработчик понимал исходники, запуск и границы сопровождения.