1
1
export const api = async ( path , method = "GET" , toast = null , data = null , credentials = "include" ) => {
2
2
let baseUrl = "https://api.travellings.cn" ;
3
3
if ( import . meta. env . DEV ) {
4
- baseUrl = "/api" ;
4
+ baseUrl = "/api" ;
5
5
}
6
-
6
+
7
7
const url = baseUrl + path ;
8
8
const body = data ? JSON . stringify ( data ) : null ;
9
9
const headers = {
@@ -15,18 +15,59 @@ export const api = async (path, method = "GET", toast = null, data = null, crede
15
15
headers,
16
16
credentials,
17
17
} ) ;
18
- const resObj = await response . json ( ) ;
18
+ const resObj = await response . json ( ) ;
19
19
if ( ! resObj . success ) {
20
20
toast . error ( resObj . msg ) ;
21
21
return null ;
22
22
}
23
23
if ( ! resObj . data ) {
24
24
return resObj . msg ;
25
25
}
26
-
26
+
27
27
return resObj . data ;
28
28
}
29
29
30
+ export async function getAllDataWithFallback ( toast ) {
31
+ const primaryUrl = import . meta. env . DEV ? '/api/all' : 'https://api.travellings.cn/all' ;
32
+ const backupUrl = 'https://backup.api.travellings.cn/list.json' ;
33
+ const timeout = 10000 ;
34
+
35
+ const fetchWithTimeout = ( url , timeoutMs ) => {
36
+ return Promise . race ( [
37
+ fetch ( url ) ,
38
+ new Promise ( ( _ , reject ) =>
39
+ setTimeout ( ( ) => reject ( new Error ( 'Request timeout' ) ) , timeoutMs )
40
+ )
41
+ ] ) ;
42
+ } ;
43
+
44
+ try {
45
+ const response = await fetchWithTimeout ( primaryUrl , timeout ) ;
46
+
47
+ if ( ! response . ok ) {
48
+ throw new Error ( `HTTP Error ${ response . status } : ${ response . statusText } ` ) ;
49
+ }
50
+
51
+ return await response . json ( ) ;
52
+ } catch ( error ) {
53
+ console . warn ( 'Primary API failed, trying backup:' , error . message ) ;
54
+ toast . warning ( `开往主服务器出现了故障(可能正在遭受攻击)。当前已自动使用备份的数据(可能并不是最新的)。
55
+ The main server has malfunctioned (possibly under attack). Currently, backup data (which may not be the latest) has been automatically used instead.` ) ;
56
+
57
+ try {
58
+ const backupResponse = await fetchWithTimeout ( backupUrl , timeout ) ;
59
+
60
+ if ( ! backupResponse . ok ) {
61
+ throw new Error ( `Backup API HTTP Error ${ backupResponse . status } : ${ backupResponse . statusText } ` ) ;
62
+ }
63
+
64
+ return await backupResponse . json ( ) ;
65
+ } catch ( backupError ) {
66
+ console . error ( 'Both primary and backup APIs failed' ) ;
67
+ throw new Error ( `All APIs failed. Last error: ${ backupError . message } ` ) ;
68
+ }
69
+ }
70
+ }
30
71
const statusIcon = {
31
72
'LOST' : 'exclamation-triangle' ,
32
73
'WAIT' : 'clock-o' ,
0 commit comments