Merge dev: Add API improvements (timeout, error handling, logging)
Some checks are pending
CI/CD / lint-and-build (push) Waiting to run
Some checks are pending
CI/CD / lint-and-build (push) Waiting to run
This commit is contained in:
commit
abc35ad0ca
@ -35,7 +35,7 @@ router.post(
|
|||||||
.isNumeric()
|
.isNumeric()
|
||||||
.withMessage('Value must be a number'),
|
.withMessage('Value must be a number'),
|
||||||
],
|
],
|
||||||
validate, // Middleware для обработки ошибок валидации
|
validate, // Проверяем результаты валидации
|
||||||
(req, res) => {
|
(req, res) => {
|
||||||
try {
|
try {
|
||||||
const { name, value } = req.body;
|
const { name, value } = req.body;
|
||||||
|
|||||||
@ -26,32 +26,70 @@ export async function apiRequest<T = unknown>(
|
|||||||
options: RequestInit = {}
|
options: RequestInit = {}
|
||||||
): Promise<ApiResponse<T>> {
|
): Promise<ApiResponse<T>> {
|
||||||
try {
|
try {
|
||||||
|
// Добавляем timeout через AbortController
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 секунд
|
||||||
|
|
||||||
|
console.log(`[API] Request to: ${apiUrl}/api/${endpoint}`);
|
||||||
|
|
||||||
const response = await fetch(`${apiUrl}/api/${endpoint}`, {
|
const response = await fetch(`${apiUrl}/api/${endpoint}`, {
|
||||||
...options,
|
...options,
|
||||||
|
signal: controller.signal,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
...options.headers,
|
...options.headers,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await response.json();
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
|
// Сначала читаем ответ как текст, потом парсим JSON
|
||||||
|
const responseText = await response.text();
|
||||||
|
let data: any;
|
||||||
|
|
||||||
|
if (responseText) {
|
||||||
|
try {
|
||||||
|
data = JSON.parse(responseText);
|
||||||
|
} catch (jsonErr) {
|
||||||
|
// Если не удалось распарсить JSON, возвращаем текст как ошибку
|
||||||
|
console.error('Failed to parse JSON response:', responseText);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: `Invalid JSON response: ${responseText.substring(0, 100)}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = {};
|
||||||
|
}
|
||||||
|
|
||||||
// Если статус не успешный, возвращаем данные с ошибкой
|
// Если статус не успешный, возвращаем данные с ошибкой
|
||||||
// (могут содержать детали валидации)
|
// (могут содержать детали валидации)
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: data.error || `HTTP error! status: ${response.status}`,
|
error: data.error || data.message || `HTTP error! status: ${response.status}`,
|
||||||
errors: data.errors, // Ошибки валидации, если есть
|
errors: data.errors, // Ошибки валидации, если есть
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('API Error:', err);
|
console.error('[API] Error:', err);
|
||||||
|
let errorMessage = 'Unknown error';
|
||||||
|
|
||||||
|
if (err instanceof Error) {
|
||||||
|
if (err.name === 'AbortError') {
|
||||||
|
errorMessage = 'Request timeout - сервер не отвечает';
|
||||||
|
} else if (err.message.includes('Failed to fetch')) {
|
||||||
|
errorMessage = 'Не удалось подключиться к серверу. Проверьте, что бэкенд запущен.';
|
||||||
|
} else {
|
||||||
|
errorMessage = err.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: err instanceof Error ? err.message : 'Unknown error',
|
error: errorMessage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user