feat: add MQTT client for camera configuration and enhance camera management
This commit is contained in:
@@ -9,8 +9,9 @@ import {
|
||||
getRefreshToken,
|
||||
setAccessToken,
|
||||
} from '@/utils/storage';
|
||||
import { history, request, RequestConfig } from '@umijs/max';
|
||||
import { history, RequestConfig } from '@umijs/max';
|
||||
import { message } from 'antd';
|
||||
import axios from 'axios';
|
||||
|
||||
// Trạng thái dùng chung cho cơ chế refresh token + hàng đợi
|
||||
let refreshingTokenPromise: Promise<string | null> | null = null;
|
||||
@@ -52,7 +53,8 @@ export const handleRequestConfig: RequestConfig = {
|
||||
return (
|
||||
(status >= 200 && status < 300) ||
|
||||
status === HTTPSTATUS.HTTP_NOTFOUND ||
|
||||
status === HTTPSTATUS.HTTP_UNAUTHORIZED
|
||||
status === HTTPSTATUS.HTTP_UNAUTHORIZED ||
|
||||
status === HTTPSTATUS.HTTP_FORBIDDEN
|
||||
);
|
||||
},
|
||||
headers: { 'X-Requested-With': 'XMLHttpRequest' },
|
||||
@@ -123,15 +125,17 @@ export const handleRequestConfig: RequestConfig = {
|
||||
// Unwrap data from backend response
|
||||
responseInterceptors: [
|
||||
async (response: any, options: any) => {
|
||||
const isRefreshRequest = response.url?.includes(API_PATH_REFRESH_TOKEN);
|
||||
const alreadyRetried = options?.skipAuthRefresh === true;
|
||||
// const isRefreshRequest = response.url?.includes(API_PATH_REFRESH_TOKEN); // response.url may be undefined or different in prod
|
||||
const isRefreshRequest = response.config.url?.includes(
|
||||
API_PATH_REFRESH_TOKEN,
|
||||
);
|
||||
// const alreadyRetried = options?.skipAuthRefresh === true;
|
||||
|
||||
// Xử lý 401: đưa request vào hàng đợi, gọi refresh token, rồi gọi lại
|
||||
if (
|
||||
response.status === HTTPSTATUS.HTTP_UNAUTHORIZED &&
|
||||
// Không tự refresh cho chính API refresh token để tránh vòng lặp vô hạn
|
||||
!isRefreshRequest &&
|
||||
!alreadyRetried
|
||||
!isRefreshRequest
|
||||
) {
|
||||
const newToken = await getValidAccessToken();
|
||||
|
||||
@@ -151,24 +155,35 @@ export const handleRequestConfig: RequestConfig = {
|
||||
|
||||
// Rebuild request options from config
|
||||
const originalConfig = response.config;
|
||||
|
||||
// Parse data if it is a JSON string to avoid double serialization when using axios directly
|
||||
let data = originalConfig.data;
|
||||
if (typeof data === 'string') {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch (e) {
|
||||
// Ignore parse error, use original string
|
||||
}
|
||||
}
|
||||
|
||||
const newOptions = {
|
||||
url: originalConfig.url,
|
||||
method: originalConfig.method,
|
||||
headers: {
|
||||
...(originalConfig.headers || {}),
|
||||
Authorization: `${newToken}`,
|
||||
},
|
||||
data: originalConfig.data,
|
||||
data: data,
|
||||
params: originalConfig.params,
|
||||
skipAuthRefresh: true,
|
||||
};
|
||||
|
||||
// Gọi lại request gốc với accessToken mới
|
||||
return request(originalConfig.url, newOptions);
|
||||
// Gọi lại request gốc với accessToken mới bằng axios để tránh double-unwrap
|
||||
return axios(newOptions);
|
||||
}
|
||||
|
||||
if (
|
||||
response.status === HTTPSTATUS.HTTP_UNAUTHORIZED &&
|
||||
(isRefreshRequest || alreadyRetried)
|
||||
isRefreshRequest
|
||||
) {
|
||||
clearAllData();
|
||||
history.push(ROUTE_LOGIN);
|
||||
|
||||
Reference in New Issue
Block a user