Ответы API и обработка ошибок
Эта статья поможет определить результат запроса и выбрать действие при отказе или потере связи. Для этого нужно проверить HTTP-код, формат содержимого и результат конкретного метода. Полученная страница входа или файл с текстом ошибки не подтверждают выполнение операции.
В этой статье
Порядок проверки ответа
- Убедитесь, что ответ получен полностью. Ошибка соединения или чтения тела отличается от ответа сервера с HTTP-кодом отказа.
- Прочитайте HTTP-код и
Content-Type. Обрабатывайте JSON, текст и файл по предусмотренному для метода сценарию. - При отказе используйте его пояснение. Для JSON проверяйте также корневой
error: true, даже если получен HTTP 200. - При успешном ответе проверьте нужную структуру: карточку, список или подтверждение записи. Затем оцените предметный результат.
Для пакетной операции общий HTTP 200 не означает успех каждого элемента. Метод может вернуть отдельные ошибки, предупреждения и пропуски. Проверяйте предусмотренные им результаты элементов и счётчики.

Как выглядит успешный результат
У API нет одной общей обёртки для всех методов. Не используйте result.res.id или result.ok как универсальную проверку.
| Результат | Что проверить |
|---|---|
| Карточка | Расположение и ID записи по контракту метода. Например, auth/check возвращает пользователя в корне, а карточка заявки ИЛ находится в res. |
| Список | Массив элементов и сведения о количестве/странице, если они предусмотрены. Пустой разрешённый список является успешным результатом. |
| Запись | Признак успеха, ID или возвращённые значения, которые обещает метод. Наличие произвольного объекта JSON этого не заменяет. |
| Пакетная операция | Какие элементы обработаны, отклонены или пропущены. Частичный результат требует отдельного действия для оставшихся элементов. |
| Текст или файл | Ожидаемые содержимое и тип. Например, команда версии обмена 1С возвращает текст 1; к ней нельзя применять схему карточки. |
Пустое тело допустимо только там, где его предусматривает метод. При чтении карточки или подтверждении сохранения оно само по себе не означает «записей нет» или «сохранено».
Какие сведения содержит ошибка
Стандартный отказ ядра содержит error: true и title. Пояснение mess и остальные поля зависят от причины и метода:
{
"error": true,
"title": "Неверный запрос",
"mess": "Проверьте обязательное поле",
"field": "id"
}
titleсообщает краткую причину,messдополняет её.fieldуказывает проблемное поле, если метод его передал.codeможет обозначать предметную причину. Используйте его только по описанию метода; он есть не у каждого отказа.error_infoи зашифрованныйreportмогут содержать диагностику. Не показывайте их как обычное сообщение и не публикуйте вместе с персональными данными.
Если тело пустое или его невозможно разобрать, причину могут передать заголовки Error-Title и Error-Mess. Они кодируются как URL: при чтении замените + пробелом и выполните decodeURIComponent. Отсутствие этих заголовков не отменяет HTTP-отказ.
Выводите сообщения сервера как текст. Сырое тело ответа, HTML страницы прокси и диагностические фрагменты не подставляйте в HTML окна ошибки.
HTTP-коды и дальнейшие действия
| Код | Действие |
|---|---|
| 400 | Проверьте синтаксис тела, обязательные поля и бизнес-условия по field/code/mess. |
| 401 | Сессия не принята либо пользователь заблокирован. Прекратите запросы с прежними данными авторизации. |
| 403 | Прочитайте причину ограничения: параметры входа, ключ, право или запрет доступа. Этот код не всегда означает истечение токена. |
| 404 | Проверьте путь метода, ID и доступность запрошенной записи или файла. |
| 409 | При конфликте версии получите свежую запись и разрешите расхождение перед новой отправкой. Повтор прежнего тела не устраняет конфликт. |
| 413 | Уменьшите размер запроса или части файла согласно лимиту конкретного интерфейса. |
| 419 | Токен закрыт или истёк. Завершите использование старой сессии. |
| 422 | Разберите причину метода. Например, поддержанная идемпотентность отклоняет прежний ключ с другим телом. |
| 429 | Сделайте паузу и уменьшите частоту запросов по правилам интерфейса. |
| 5xx | Ошибка сервера или связанного сервиса. После запроса записи выясните фактический результат перед повтором. |
Код помогает выбрать действие, но не заменяет пояснение метода. Порядок восстановления авторизации описан в статье «Срок действия токена, проверка и завершение сессии».
Пример обработки JSON
Этот обработчик рассчитан на метод, от которого ожидается непустой JSON. Он сохраняет HTTP-код и сведения об отказе, использует резервные заголовки и не выводит сырое тело:
async function readApiJson(response) {
const header = name => {
const value = response.headers.get(name) || '';
if (value === 'null') return '';
try { return decodeURIComponent(value.replaceAll('+', ' ')); }
catch { return value; }
};
const fail = (kind, message, details = {}) =>
Object.assign(new Error(message), {
kind, status: response.status, ...details
});
let text;
try { text = await response.text(); }
catch (cause) {
if (cause?.name === 'AbortError') throw cause;
throw fail('network', 'Ответ не получен полностью', {cause});
}
const type = (response.headers.get('content-type') || '')
.split(';')[0].trim().toLowerCase();
const isJson = type === 'application/json' || type.endsWith('+json');
let data = null, broken = false;
if (isJson && text.trim()) {
try { data = JSON.parse(text); }
catch { broken = true; }
}
const info = data && typeof data === 'object' ? data : {};
if (!response.ok || info.error === true) {
const title = info.title || header('Error-Title');
const mess = info.mess || header('Error-Mess');
throw fail('api', [title, mess].filter(Boolean).join(': ')
|| `HTTP ${response.status}`, {
title, mess, field: info.field, code: info.code
});
}
if (!isJson || !text.trim() || broken) {
throw fail('format', 'Ожидался непустой JSON-ответ');
}
return data;
}
Пример чтения периодов местонахождения экземпляра СИ. Здесь id означает ID экземпляра, а результат содержит массив res и общее количество count:
const url = 'https://lab.example/api/laboratory/measuring/place/info';
const response = await fetch(url, {
method: 'POST',
headers: {
auth: 'YOUR_AUTH_TOKEN', Lang: 'ru', Out: 'json',
'Content-Type': 'application/json'
},
body: JSON.stringify({id: 900101, page: 1})
}).catch(cause => {
if (cause?.name === 'AbortError') throw cause;
throw Object.assign(new Error('Ответ не получен'), {
kind: 'network', cause
});
});
const data = await readApiJson(response);
if (!Array.isArray(data?.res)
|| !Number.isInteger(data.count) || data.count < 0) {
throw new Error('Не получен список периодов местонахождения');
}
Замените условные адрес, токен и ID своими значениями. Последняя проверка относится именно к этому методу; у другого метода будет своя схема. Ошибки с kind: 'api' содержат отказ, format означает неподходящий ответ, network означает отсутствие полного ответа. Отмену запроса по собственной команде обрабатывайте отдельно.
Получение файла
- Проверьте HTTP-код. При отказе прочитайте предусмотренные JSON или заголовки ошибки.
- Сравните
Content-Typeс форматом, который должен вернуть метод. Для ожидаемого PDF страница HTML или обычный JSON-объект не подходят. - Получите имя из
Content-DispositionилиFileName, если сервер их передал, либо задайте его по контракту метода. - Только после проверок получите
Blobи передайте файл на сохранение или просмотр.
JSON и HTML могут быть законными форматами экспорта. Поэтому проверка зависит от ожидаемого файла. Имя с расширением .pdf не превращает ответ в PDF, а успешное получение файла ещё не означает его сохранение на устройстве.
О передаче вложений: «Загрузка файлов и вложений».
Потеря ответа и повтор запроса
Если соединение оборвалось или истёк предел ожидания, операция могла выполниться до потери ответа. Это относится и к сбою во время чтения тела. Полученный HTTP 504 и локальный таймаут являются разными ситуациями, хотя оба могут оставлять результат записи неизвестным.
После создания или изменения записи сначала выясните её фактическое состояние. Повторяйте отправку по правилам конкретной операции; используйте идемпотентность только там, где она поддерживается. Подробности: «Повторные запросы и диагностика сбоев».
Связанные материалы
- API TesLab: адрес сервера и первый запрос.
- Параметры запросов: JSON, формы, типы и заголовки.
- Списки: страницы, сортировка и фильтры.