Menu
CoddyTech

Единый формат ошибки

Часть раздела REST API путешествия по Node.js на Coddy. Урок 12 из 25.

Теперь ваш API возвращает ошибки в двух форматах: строку для 404 и объект zod для 400. Клиенту нужно обрабатывать каждый из них. Используйте единый формат для всех ошибок:

{ "error": { "code": "not_found", "message": "Invoice not found" } }

{ "error": { "code": "invalid_body", "message": "Too small: ...",
             "fields": { "amount": ["Too small: expected number to be >0"] } } }

code предназначен для программ: он никогда не меняется, поэтому клиент может сравнивать его. message предназначен для людей, и его формулировка может меняться. fields указывает форме, какое поле ввода нужно отметить. Определите этот формат в одной функции и вызывайте её из каждого маршрута, чтобы форматы маршрутов не расходились:

sendError(res, 404, 'not_found', 'Invoice not found');
challenge icon

Задание

Легко

Теперь ваш API отправляет ошибки в двух форматах: простую строку для 404 и объект zod для 400. Приведите все ошибки к одному формату, чтобы клиент мог обрабатывать их одинаково. Теперь каждая ошибка выглядит так; fields добавляется, только если есть что перечислить:

{ "error": { "code": "not_found", "message": "Task not found" } }
  1. В errors.js завершите функцию sendError(res, status, code, message, fields). Она отправляет ответ с указанным статусом и приведённой выше структурой. Добавляйте fields во внутренний объект, только если этот аргумент был передан. Функция sendInvalid ниже уже написана и вызывает вашу функцию.
  2. В routes/tasks.js импортируйте оба вспомогательных средства:
    • Замените четыре ответа 404 (GET, PATCH, PUT и DELETE для одной задачи) на sendError, указав код not_found и сообщение Task not found.
    • Замените три ответа 400 для некорректного тела запроса (POST, PATCH и PUT) на sendInvalid(res, result.error).

    В таком случае некорректное тело запроса выглядит так (сообщение формирует zod):

    {
      "error": {
        "code": "invalid_body",
        "message": "Invalid input: expected string, received number",
        "fields": { "title": ["Invalid input: expected string, received number"] }
      }
    }
  3. В server.js импортируйте sendError и используйте его в обработчике ошибок внизу:
    • Если тело запроса не является допустимым JSON, отправьте статус 400, код invalid_json и сообщение The body is not valid JSON.
    • В любом другом случае отправьте статус 500, код server_error и сообщение Something went wrong.

Проверьте: DELETE /api/tasks/99 возвращает 404 с ответом { "error": { "code": "not_found", "message": "Task not found" } } без fields. Отправьте POST-запрос с телом { "title": 123 } на /api/tasks: вы получите 400 с приведённой выше ошибкой invalid_body. Панель запросов не позволяет отправлять некорректный JSON, поэтому проверка протестирует случай invalid_json за вас.

Попробуйте сами

import { z } from 'zod';

// Отправляет все ошибки в едином формате:
// { "error": { "code": "not_found", "message": "Task not found" } }
// при этом "fields" добавляется только в том случае, если оно передано.
export const sendError = (res, status, code, message, fields) => {
    // Отправьте ответ здесь
};

// Ошибка zod с кодом 400: первая проблема — в сообщении, проблемы каждого поля —
// в fields.
export const sendInvalid = (res, zodError) =>
    sendError(res, 400, 'invalid_body', zodError.issues[0].message, z.flattenError(zodError).fieldErrors);
quiz iconПроверьте себя

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

Все уроки раздела REST API

Потренируйтесь самостоятельно: Песочница Express