Форматы ответов об ошибках, статусные коды, детали проблем (RFC 7807)
Обработка ошибок — это неотъемлемая часть проектирования API. Хорошая стратегия обработки ошибок делает API предсказуемым, надежным и простым в отладке.
| Поле | Тип | Обязательное | Описание | Пример |
|---|---|---|---|---|
| type | string | Да | URI, указывающий на тип ошибки | https://api.example.com/errors/validation |
| title | string | Да | Краткое, человекочитаемое описание | "Validation Error" |
| status | integer | Да | HTTP-статусный код | 400 |
| detail | string | Да | Подробное описание причины | "Email is required" |
| instance | string | Нет | URI конкретного экземпляра ошибки | /users/123 |
| errors | array | Нет | Список полей с ошибками | [{"field": "email", "message": "Required"}] |
type может вести на страницу с подробной документациейHTTP-ответ при валидации:
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://api.example.com/errors/validation",
"title": "Validation Error",
"status": 400,
"detail": "Email is required",
"instance": "/users",
"errors": [
{
"field": "email",
"message": "Required"
},
{
"field": "password",
"message": "Must be at least 8 characters"
}
]
}Реализация на сервере (Node.js/Express):
// Middleware для обработки ошибок
app.use((err, req, res, next) => {
const problem = {
type: err.type || 'https://api.example.com/errors/generic',
title: err.title || 'Error',
status: err.status || 500,
detail: err.message || 'An error occurred'
};
// Добавляем instance для конкретных ресурсов
if (req.path) {
problem.instance = req.path;
}
// Добавляем errors для валидационных ошибок
if (err.validationErrors) {
problem.errors = err.validationErrors;
}
res.status(problem.status).json(problem);
});
// Пример использования
const validateUser = (req, res, next) => {
const errors = [];
if (!req.body.email) {
errors.push({ field: 'email', message: 'Required' });
}
if (!req.body.password || req.body.password.length < 8) {
errors.push({ field: 'password', message: 'Must be at least 8 characters' });
}
if (errors.length > 0) {
const err = new Error('Validation failed');
err.status = 400;
err.type = 'https://api.example.com/errors/validation';
err.title = 'Validation Error';
err.validationErrors = errors;
return next(err);
}
next();
};| Этап | Действия | Ответственные | Сроки |
|---|---|---|---|
| Проектирование | Определение типов ошибок, создание схемы Problem Details | Архитектор, Tech Lead | На этапе проектирования API |
| Разработка | Реализация middleware, обработка исключений, валидация | Разработчики | В процессе разработки |
| Тестирование | Тестирование различных сценариев ошибок, проверка форматов | QA, DevOps | Перед PR и в CI |
| Релиз | Документация ошибок, примеры для клиентов | Technical Writer, Release Manager | При релизе |
| Поддержка | Мониторинг ошибок, анализ логов, улучшение сообщений | DevOps, Support Team | Постоянно |
Q: Что такое RFC 7807 Problem Details?
A: Стандартный формат ошибок: type, title, status, detail, instance; машиночитаемый, последовательный для всех API.
Q: Какой HTTP-статус код используется для 'Not Found'? A: Код 404 Not Found используется, когда сервер не может найти запрашиваемый ресурс. Это самый распространенный код для отсутствующих URL.
Q: Какой заголовок используется для указания на то, что клиент должен повторить запрос позже?
A: Заголовок Retry-After используется в ответах с кодом 429 Too Many Requests или 503 Service Unavailable, чтобы указать клиенту, через сколько секунд или в какое время можно повторить запрос.
Q: Что означает статус код 409 Conflict? A: Код 409 Conflict используется, когда запрос не может быть выполнен из-за конфликта с текущим состоянием ресурса (например, попытка создать ресурс с уже существующим ID).
Хорошая стратегия обработки ошибок делает API предсказуемым, надежным и простым в отладке.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.