В этом уроке мы рассмотрим спецификацию Problem Details, которая описана в RFC 9457. Эта спецификация предоставляет стандартный формат для сообщения об ошибках в REST API. Основной целью Problem Details является упрощение интерпретации и обработки ошибок клиентами и серверами.
Зачем использовать Problem Details?
Когда ваше API возвращает ошибки, важно, чтобы клиент понимал, что пошло не так, и как исправить ошибку. Стандарт Problem Details предлагает универсальный формат для этих сообщений, что упрощает обработку ошибок и улучшает взаимодействие между клиентом и сервером.
Формат Problem Details
По спецификации RFC 9457, формат Problem Details определяется как JSON-объект, который включает следующие поля:
- type: (опционально) URI, указывающий на тип ошибки. Это помогает клиентам определить тип проблемы и может указывать на документ или страницу, где можно найти больше информации.
title: (опционально) Краткое описание проблемы в текстовом виде, которое подходит для отображения пользователю.
status: (опционально) Код состояния HTTP, который вызвал проблему. Это поле помогает клиентам понять, какой код состояния связан с проблемой.
detail: (опционально) Подробное описание проблемы. Это поле предоставляет более детальную информацию о том, что пошло не так.
instance: (опционально) URI, указывающий на ресурс, связанный с проблемой. Это полезно для ссылок на конкретные экземпляры ресурсов, которые вызвали ошибку.
Пример использования
Рассмотрим пример ответа API с ошибкой, которая использует формат Problem Details:
# Вернет 422
curl -XPOST localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{ "fullName": "Toto", "email": "" }'
{
"detail": "Errors related to business logic such as uniqueness",
"errors": [
{
"field": "email",
"message": "The email field must be a valid email address",
"rule": "email"
}
],
"status": 422,
"title": "Validation Error"
}
Вы можете расширять объект Problem Details, добавляя свои собственные поля и структуры, чтобы лучше соответствовать требованиям вашего API. Например, вы можете использовать поле errors, как в примере выше, для предоставления более детализированной информации о проблемах, которые не укладываются в стандартные поля.
Интеграция в TypeSpec
В TypeSpec мы можем определить модели ошибок, используя аннотацию @error. Это позволяет нам задать стандартный формат для различных типов ошибок, включая расширенные версии Problem Details.
Модель ProblemDetails определяет основные поля, которые могут быть использованы в любом типе ошибки:
@error
model ProblemDetails {
@header("content-type") contentType: "application/problem+json";
type?: string;
title?: string;
status?: integer;
detail?: string;
instance?: string;
}
Модели ошибок можно расширить, чтобы включать специфические поля или настройки для определенных типов ошибок.
@error
model NotFoundError {
@statusCode _: 404;
...ProblemDetails;
}
@error
model UnauthorizedError {
@statusCode _: 401;
...ProblemDetails;
}
// Эта модель включает дополнительное поле errors,
// которое содержит детали о конкретных ошибках.
@error
model UnprocessableEntityError {
@statusCode _: 422;
...ProblemDetails;
errors: Array<{
message: string;
rule: string;
field: string;
}>;
}
В TypeSpec мы можем использовать эти модели ошибок для описания возможных ответов нашего API. Вот как это может выглядеть:
@route("/users")
namespace users {
@get
op index(@query page?: numeric = 1): {
@body _: {
data: User[];
};
};
@get
op show(@path id: numeric): {
@body _: User;
} | NotFoundError;
@post
op create(@body _: UserCreateDTO): {
@body _: User;
@statusCode statusCode: 201;
} | UnprocessableEntityError;
@patch
op update(@path id: numeric, @body user: UserEditDTO): {
@body _: User;
} | NotFoundError | UnprocessableEntityError;
@delete
op destroy(@path id: numeric): {
@statusCode statusCode: 204;
} | NotFoundError;
}
- index: Получение списка пользователей. Ошибок не ожидается.
- show: Получение конкретного пользователя по идентификатору. Возможна ошибка NotFoundError, если пользователь не найден.
- create: Создание нового пользователя. Возможны ошибки UnprocessableEntityError в случае проблем с данными запроса.
- update: Обновление пользователя. Возможны ошибки NotFoundError и UnprocessableEntityError.
- destroy: Удаление пользователя. Возможна ошибка NotFoundError, если пользователь не найден.
Заключение
Интеграция стандартов Problem Details в спецификацию API с помощью TypeSpec позволяет четко определить формат сообщений об ошибках и улучшить взаимодействие между клиентом и сервером. Это помогает сделать ваши API более понятными и удобными для использования, обеспечивая единый формат для обработки и интерпретации ошибок.
Самостоятельная работа
- Добавьте в TypeSpec описания ошибок для всех маршрутов
- Запушьте изменения в репозиторий
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.