1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { warn } from '../../log/Log'; 17import { BurialPointRequestBody, GeneralRecordRequest, pluginUsage } from './SpStatisticsHttpBean'; 18 19export class SpStatisticsHttpUtil { 20 static requestServerInfo: string = ''; 21 static serverTime: number = 0; 22 static timeDiff: number = 0; 23 static retryCount: number = 0; 24 static retryMaxCount: number = 5; 25 static pauseRetry: boolean = false; 26 static retryRestTimeOut: boolean = false; 27 static recordPlugin: Array<string> = []; 28 static controllersMap: Map<number, AbortController> = new Map<number, AbortController>(); 29 static isInterrupt: boolean = false; 30 31 static initStatisticsServerConfig(): void { 32 if (SpStatisticsHttpUtil.requestServerInfo === '') { 33 SpStatisticsHttpUtil.requestServerInfo = SpStatisticsHttpUtil.getRequestServerInfo(); 34 } 35 if (SpStatisticsHttpUtil.serverTime === 0) { 36 SpStatisticsHttpUtil.getServerTime(); 37 } 38 } 39 40 static getRequestServerInfo(): string { 41 try { 42 let req = new XMLHttpRequest(); 43 req.onreadystatechange = (): void => { 44 if (req.readyState === 4 && req.status === 200) { 45 let requestInfo = req.getResponseHeader('request_info'); 46 if (requestInfo && requestInfo.length > 0) { 47 SpStatisticsHttpUtil.requestServerInfo = requestInfo; 48 } 49 } 50 }; 51 req.open( 52 'GET', 53 `${window.location.protocol}//${window.location.host.split(':')[0]}:${window.location.port 54 }/application/serverInfo`, 55 true 56 ); 57 req.send(null); 58 } catch { 59 warn('Connect Server Failed'); 60 } 61 return ''; 62 } 63 64 static getServerTime(): void { 65 if (SpStatisticsHttpUtil.requestServerInfo === '') { 66 SpStatisticsHttpUtil.requestServerInfo = SpStatisticsHttpUtil.getRequestServerInfo(); 67 } 68 if (SpStatisticsHttpUtil.pauseRetry) { 69 return; 70 } 71 fetch(`https://${SpStatisticsHttpUtil.requestServerInfo}/serverTime`) 72 .then((resp) => { 73 resp.text().then((it) => { 74 if (it && it.length > 0) { 75 SpStatisticsHttpUtil.serverTime = Number(it); 76 SpStatisticsHttpUtil.timeDiff = SpStatisticsHttpUtil.serverTime - Date.now(); 77 } 78 }); 79 }) 80 .catch((e) => { 81 this.handleRequestException(); 82 }); 83 } 84 85 private static handleRequestException(): void { 86 if (SpStatisticsHttpUtil.retryCount >= SpStatisticsHttpUtil.retryMaxCount) { 87 SpStatisticsHttpUtil.pauseRetry = true; 88 if (SpStatisticsHttpUtil.retryRestTimeOut) { 89 return; 90 } 91 SpStatisticsHttpUtil.retryRestTimeOut = true; 92 setTimeout(() => { 93 SpStatisticsHttpUtil.retryCount = 0; 94 SpStatisticsHttpUtil.pauseRetry = false; 95 SpStatisticsHttpUtil.retryRestTimeOut = false; 96 }, 600000); 97 } 98 ++SpStatisticsHttpUtil.retryCount; 99 } 100 101 static addUserVisitAction(requestUrl: string): void { 102 // @ts-ignore 103 if (window.useWb) { 104 return; 105 } 106 if (SpStatisticsHttpUtil.requestServerInfo === '') { 107 SpStatisticsHttpUtil.requestServerInfo = SpStatisticsHttpUtil.getRequestServerInfo(); 108 } 109 if (SpStatisticsHttpUtil.pauseRetry) { 110 return; 111 } 112 let visitId = 0; 113 fetch(`https://${SpStatisticsHttpUtil.requestServerInfo}/${requestUrl}`, { 114 method: 'post', 115 headers: { 116 'Content-Type': 'application/json', 117 }, 118 }) 119 .then((resp) => { 120 resp.text().then((it) => { 121 let res = JSON.parse(it); 122 if (res && res.data) { 123 visitId = res.data.accessId; 124 } 125 }); 126 }) 127 .catch((err) => { }); 128 setTimeout(() => { 129 fetch(`https://${SpStatisticsHttpUtil.requestServerInfo}/${requestUrl}`, { 130 method: 'post', 131 headers: { 132 'Content-Type': 'application/json', 133 }, 134 body: JSON.stringify({ 135 effectiveAccess: true, 136 visitId: visitId, 137 }), 138 }) 139 .catch((err) => { }) 140 .then((resp) => { }); 141 }, 1800000); 142 } 143 144 static addOrdinaryVisitAction(requestBody: BurialPointRequestBody): void { 145 // @ts-ignore 146 if (window.useWb) { 147 return; 148 } 149 if (SpStatisticsHttpUtil.requestServerInfo === '') { 150 SpStatisticsHttpUtil.requestServerInfo = SpStatisticsHttpUtil.getRequestServerInfo(); 151 } 152 if (SpStatisticsHttpUtil.pauseRetry) { 153 return; 154 } 155 requestBody.ts = SpStatisticsHttpUtil.getCorrectRequestTime(); 156 if (SpStatisticsHttpUtil.serverTime === 0) { 157 return; 158 } 159 fetch(`https://${SpStatisticsHttpUtil.requestServerInfo}/record`, { 160 method: 'post', 161 headers: { 162 'Content-Type': 'application/json', 163 }, 164 body: JSON.stringify(requestBody), 165 }) 166 .catch((err) => { 167 }) 168 .then((resp) => { }); 169 } 170 171 // ai问答 172 static generalRecord(category: string, secondCat: string, thirdCat: Array<string>): void { 173 let requestBody: GeneralRecordRequest = { 174 ts: SpStatisticsHttpUtil.getCorrectRequestTime(), 175 category, 176 secondCat, 177 thirdCat 178 }; 179 fetch(`https://${SpStatisticsHttpUtil.requestServerInfo}/generalRecord`, { 180 method: 'post', 181 headers: { 182 'Content-Type': 'application/json' 183 }, 184 body: JSON.stringify(requestBody) 185 }).then( 186 res => { } 187 ).catch(err => { 188 }); 189 } 190 191 static recordPluginUsage(): void { 192 fetch(`https://${SpStatisticsHttpUtil.requestServerInfo}/recordPluginUsage`, { 193 method: 'post', 194 headers: { 195 'Content-Type': 'application/json' 196 }, 197 body: JSON.stringify({ 198 eventData: { 199 plugin: SpStatisticsHttpUtil.recordPlugin 200 } 201 }) 202 }).then(res => { 203 }).catch(err => { 204 }); 205 SpStatisticsHttpUtil.recordPlugin = []; 206 } 207 208 static getNotice(): Promise<Response> { 209 return fetch(`https://${window.location.host}${window.location.pathname}messagePublish`); 210 } 211 212 static getCorrectRequestTime(): number { 213 if (SpStatisticsHttpUtil.serverTime === 0) { 214 SpStatisticsHttpUtil.getServerTime(); 215 } 216 return Date.now() + SpStatisticsHttpUtil.timeDiff; 217 } 218 219 // ai对话接口--获取token 220 static async getAItoken(params:string): Promise<AiResponse> { 221 let controller = new AbortController(); 222 let response: AiResponse = { 223 status: 0, 224 data: '' 225 }; 226 setTimeout(() => { 227 controller.abort(); 228 }, 60000); 229 let res = await window.fetch(`https://${window.location.host}/${params}`, { 230 method: 'post', 231 signal: controller.signal, 232 headers: { 233 'Content-Type': 'application/json' 234 } 235 }).then(async res => { 236 response.status = res.status; 237 if (res.status === 200) { 238 let resp = await res.text(); 239 let resj = await JSON.parse(resp); 240 response.data = resj.token; 241 } 242 }).catch(err => { 243 response.status = 700; 244 }); 245 return response; 246 } 247 248 // ai对话接口--问答 249 // @ts-ignore 250 static askAi(requestBody, params: string): Promise<AiResponse> { 251 return new Promise((resolve, reject) => { 252 let controller = new AbortController(); 253 let date = Date.now(); 254 if (!SpStatisticsHttpUtil.controllersMap.has(date)) { 255 SpStatisticsHttpUtil.controllersMap.set(date, controller); 256 } 257 let response: AiResponse = { 258 status: 0, 259 data: '', 260 time: date, 261 }; 262 setTimeout(() => { 263 controller.abort(); 264 }, 60000); 265 window.fetch(`https://${window.location.host}/${params}`, { 266 method: 'post', 267 signal: controller.signal, 268 headers: { 269 'Content-Type': 'application/json' 270 }, 271 body: JSON.stringify(requestBody) 272 }).then(async res => { 273 response.status = res.status; 274 if (res.status === 200) { 275 let resp = await res.text(); 276 let resj = await JSON.parse(resp); 277 response.data = resj.reason && resj.reason === 'ok' ? resj.chatbot_reply : '服务器异常,请稍后再试'; 278 } 279 else { 280 response.data = '服务器请求失败'; 281 } 282 resolve(response); 283 }).catch((err) => { 284 if (err.toString().indexOf('AbortError') > -1) { 285 response.data = '请求超时,已中断!'; 286 response.status = 504; 287 } else { 288 response.data = '请求错误'; 289 } 290 reject(response); 291 }); 292 }); 293 } 294} 295 296export class AiResponse { 297 status: number = 0; 298 data: string = ''; 299 time?: number = 0; 300} 301