import { HTTPSTATUS } from '@/constants'; import { ROUTE_LOGIN } from '@/constants/routes'; import { getToken, removeToken } from '@/utils/storage'; import { history, RequestConfig } from '@umijs/max'; import { message } from 'antd'; // Error handling scheme: Error types // enum ErrorShowType { // SILENT = 0, // WARN_MESSAGE = 1, // ERROR_MESSAGE = 2, // NOTIFICATION = 3, // REDIRECT = 9, // } // Response data structure agreed with the backend // interface ResponseStructure { // success: boolean; // data: T; // errorCode?: number; // errorMessage?: string; // showType?: ErrorShowType; // } // const codeMessage = { // 200: 'The server successfully returned the requested data。', // 201: 'New or modified data succeeded。', // 202: 'A request has been queued in the background (asynchronous task)。', // 204: 'Data deleted successfully。', // 400: 'There is an error in the request sent, the server did not perform the operation of creating or modifying data。', // 401: 'The user does not have permission (token, username, password is wrong) 。', // 403: 'User is authorized, but access is prohibited。', // 404: 'The request issued was for a non-existent record, the server did not operate。', // 406: 'The requested format is not available。', // 410: 'The requested resource is permanently deleted and will no longer be available。', // 422: 'When creating an object, a validation error occurred。', // 500: 'Server error, please check the server。', // 502: 'Gateway error。', // 503: 'Service unavailable, server temporarily overloaded or maintained。', // 504: 'Gateway timeout。', // }; // Runtime configuration export const handleRequestConfig: RequestConfig = { // Unified request settings timeout: 20000, validateStatus: (status) => { return ( (status >= 200 && status < 300) || status === HTTPSTATUS.HTTP_NOTFOUND ); }, headers: { 'X-Requested-With': 'XMLHttpRequest' }, // Error handling: umi@3's error handling scheme. errorConfig: { // Error throwing errorThrower: (res: any) => { // console.log('Response from backend:', res); const { success, data, errorCode, errorMessage, showType } = res; if (!success) { const error: any = new Error(errorMessage); error.name = 'BizError'; error.info = { errorCode, errorMessage, showType, data }; throw error; // Throw custom error } }, // Error catching and handling errorHandler: (error: any) => { if (error.response) { const { status } = error.response; // Ưu tiên: codeMessage → backend message → statusText // const errMsg = // codeMessage[status as keyof typeof codeMessage] || // data?.message || // statusText || // 'Unknown error'; if (status === HTTPSTATUS.HTTP_UNAUTHORIZED) { removeToken(); history.push(ROUTE_LOGIN); } else if (status === HTTPSTATUS.HTTP_SERVERERROR) { // message.error('💥 Internal server error!'); } else { message.error(`❌ ${status}: ${error.message || 'Error'}`); } } else if (error.request) { message.error('🚨 No response from server!'); } else { message.error(`⚠️ Request setup error: ${error.message}`); } }, }, // Request interceptors requestInterceptors: [ (url: string, options: any) => { const token = getToken(); // console.log('Token: ', token); return { url, options: { ...options, headers: { ...options.headers, ...(token ? { Authorization: `${token}` } : {}), }, }, }; }, ], // Unwrap data from backend response responseInterceptors: [ (response) => { // console.log('Response from server: ', response); // const res = response.data as ResponseStructure; // if (res && res.success) { // // ✅ Trả ra data luôn thay vì cả object // return res.data; // } return { status: response.status, statusText: response.statusText, headers: response.headers, config: response.config, data: response.data, }; }, ], };