@conecli/cone-render 0.10.1-shop3.1 → 0.10.1-shop3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import Taro from '@tarojs/taro'
2
1
  isSupportHybridHttpRequest,
3
2
  draInterfaceCustomReport,
4
3
  draBusinessCustomReport,
5
4
  jsonHeader = 'application/json;charset=utf-8',
6
5
  formDataHeader = 'application/x-www-form-urlencoded',
7
6
  HYBRID: 'httpRequest_hybrid',
8
7
  TARO: 'httpRequest_taro',
9
8
  #requestTimeStamp: number
10
9
  #responseTimeStamp: number
11
10
  #getResTimeStamp: number
12
11
  #reportType: string
13
12
  #callbackFunction: string
14
13
 
15
14
  async request({
16
15
  url,
17
16
  method = 'POST',
18
17
  timeout = 7000,
19
18
  isColorVerify = false,
20
19
  ...otherOptions
21
20
  }): Promise<Taro.request.SuccessCallbackResult<any>> {
22
21
  const { header: otherHeader, ...otherOpts } = otherOptions
23
22
  const header = {
24
23
  'content-type':
25
24
  method === 'POST'
26
25
  ? RequestHeaderContentType.formDataHeader
27
26
  : RequestHeaderContentType.jsonHeader,
28
27
  ...otherHeader,
29
28
  }
30
29
  let getRequestUrl = url
31
30
  let requestTask
32
31
  const data = otherOpts?.data
33
32
  const isGatewayRequest =
34
33
  url === this.api.apiFunc && typeof data === 'object'
35
34
  if (isGatewayRequest) {
36
35
  getRequestUrl = this._handleSpecialGatewayUrl(url)
37
36
  const shouldUseHybridRequest = this._shouldUseHybridRequest()
38
37
  if (shouldUseHybridRequest) {
39
38
  requestTask = this._hybridRequest(getRequestUrl, data)
40
39
  } else {
41
40
  otherOpts.data = await this._prepareGatewayReqData(data, isColorVerify)
42
41
  requestTask = this._taroRequest(
43
42
  getRequestUrl,
44
43
  otherOpts,
45
44
  method,
46
45
  timeout,
47
46
  header,
48
47
  )
49
48
  }
50
49
  } else {
51
50
  requestTask = this._taroRequest(
52
51
  getRequestUrl,
53
52
  otherOpts,
54
53
  method,
55
54
  timeout,
56
55
  header,
57
56
  )
58
57
  }
59
58
  const requestTimeoutPromise =
60
59
  new Promise<ServiceInterFace.RequestPromiseRes>((resolve) => {
61
60
  setTimeout(() => {
62
61
  resolve({
63
62
  statusCode: 500,
64
63
  resTimeoutState: true,
65
64
  errMsg: 'request timeout',
66
65
  })
67
66
  }, timeout)
68
67
  })
69
68
  return Promise.race([requestTask, requestTimeoutPromise]).then(
70
69
  (res: any) => {
71
70
  if (res && res.statusCode === 500 && res.resTimeoutState) {
72
71
  if (this.#reportType === HTTP_REQUEST_TYPE.HYBRID) {
73
72
  this._clearFunction(this.#callbackFunction)
74
73
  } else {
75
74
  requestTask.abort && requestTask.abort()
76
75
  }
77
76
  }
78
77
  this._handleReportInterfaceError(url, data, timeout, res)
79
78
  return res
80
79
  },
81
80
  )
82
81
  }
83
82
 
84
83
  _handleSpecialGatewayUrl(url: string): string {
85
84
  if (isPc && window.location.hostname.includes('.jd.hk')) {
86
85
  return this.api.hkApiFunc
87
86
  }
88
87
  if (
89
88
  isJdApp &&
90
89
  window?.shopGlobalSwitch?.dualProtocol &&
91
90
  !window.location.href.includes('jshopx_vconsole')
92
91
  ) {
93
92
  return window?.shopGlobalSwitch?.dualProtocol?.apiTestApp || url
94
93
  }
95
94
  return url
96
95
  }
97
96
 
98
97
  _shouldUseHybridRequest(): boolean {
99
98
  try {
100
99
  if (!isJdApp || !isSupportHybridHttpRequest || isJdAndHarmonyDevice) {
101
100
  return false
102
101
  }
103
102
  const configData = global.getDynamicConfig('hybridHttpSwitch')
104
103
  const { globalOn = false, grayscale = {} } = configData || {}
105
104
  const buildType = process.env.BUILD_TYPE || ''
106
105
  const isInvokeGray = globalOn || grayscale[buildType]
107
106
  console.log(
108
107
  '使用hybrid请求是否命中灰度,isInvokeGray:',
109
108
  isInvokeGray,
110
109
  '获取mpaas配置hybridHttpSwitch原始数据configData',
111
110
  configData,
112
111
  )
113
112
  const hasWindowXWebView = !!window.XWebView
114
113
  return isInvokeGray && hasWindowXWebView
115
114
  } catch (e) {
116
115
  console.log('获取是否使用Hybrid请求出错,e:', e)
117
116
  return false
118
117
  }
119
118
  }
120
119
 
121
120
  _hybridRequest(url: string, data: any): Promise<any> {
122
121
  return new Promise((resolve, reject) => {
123
122
  try {
124
123
  const changeCurrentUrl = url.startsWith('//') ? `https:${url}` : url
125
124
  const reqParams = {
126
125
  url: isIosDevice ? `${changeCurrentUrl}/` : changeCurrentUrl,
127
126
  functionId: data?.functionId,
128
127
  body: data?.body,
129
128
  headerType: '0',
130
129
  }
131
130
  const callbackFunction = this._generateCallbackFunction()
132
131
  this.#callbackFunction = callbackFunction
133
132
  this.#requestTimeStamp = Date.now()
134
133
  this.#reportType = HTTP_REQUEST_TYPE.HYBRID
135
134
  window.XWebView.callNative(
136
135
  'ColorQueryPlugin',
137
136
  'colorRequest',
138
137
  JSON.stringify(reqParams),
139
138
  callbackFunction,
140
139
  '1',
141
140
  )
142
141
  window[callbackFunction] = (result) => {
143
142
  this.#responseTimeStamp = Date.now()
144
143
  try {
145
144
  const resultObj =
146
145
  typeof result === 'string' ? JSON.parse(result) : result
147
146
  resolve(resultObj)
148
147
  } catch (error) {
149
148
  const errMsg = 'hybrid网络请求JSON解析失败, error: ' + error
150
149
  draBusinessCustomReport({
151
150
  type: `${HTTP_REQUEST_TYPE.HYBRID}_jsonParseError`,
152
151
  errMsg,
153
152
  result,
154
153
  })
155
154
  reject({ errMsg })
156
155
  }
157
156
  this._clearFunction(callbackFunction)
158
157
  }
159
158
  } catch (error) {
160
159
  reject({
161
160
  errMsg:
162
161
  'hybrid网络请求,App下调用window.XWebView.callNative出错, error: ' +
163
162
  error,
164
163
  })
165
164
  }
166
165
  })
167
166
  }
168
167
 
169
168
  _generateCallbackFunction() {
170
169
  return `hybridHttpRequestCallback_${Date.now()}_${Math.ceil(
171
170
  Math.random() * 100000,
172
171
  )}`
173
172
  }
174
173
 
175
174
  _clearFunction(functionName: string) {
176
175
  try {
177
176
  delete window[functionName]
178
177
  } catch (e) {
179
178
  window[functionName] = undefined
180
179
  }
181
180
  }
182
181
 
183
182
  async _prepareGatewayReqData(
184
183
  data: any,
185
184
  isColorVerify: boolean,
186
185
  ): Promise<any> {
187
186
  const { functionId } = data
188
187
  console.log('获取当前是否需要color加固', isColorVerify, functionId)
189
188
  if (isColorVerify) {
190
189
  const { h5st } = await colorSign.paramsSign(data)
191
190
  h5st && (data.h5st = encodeURI(h5st))
192
191
  console.log(`${functionId}的apiReq_h5st===>:${h5st}`)
193
192
  }
194
193
  const { jsToken } = await colorSign.getFmInfo()
195
194
  console.log(`${functionId}的api jsToken指纹===>:${jsToken}`)
196
195
  jsToken && (data['x-api-eid-token'] = jsToken)
197
196
  return data
198
197
  }
199
198
 
200
199
  _taroRequest(
201
200
  url: string,
202
201
  otherOpts: any,
203
202
  method: string,
204
203
  timeout: number,
205
204
  header: string,
206
205
  ): Promise<any> {
207
206
  const reqParam = {
208
207
  url,
209
208
  method,
210
209
  timeout,
211
210
  header,
212
211
  credentials: 'include',
213
212
  ...otherOpts,
214
213
  }
215
214
  this.#requestTimeStamp = Date.now()
216
215
  this.#reportType = HTTP_REQUEST_TYPE.TARO
217
216
  return Taro.request(reqParam)
218
217
  }
219
218
 
220
219
  _reportRequestTime(url: string, data: any): void {
221
220
  this.#getResTimeStamp = Date.now()
222
221
  if (this.#reportType === HTTP_REQUEST_TYPE.TARO) {
223
222
  this.#responseTimeStamp = this.#getResTimeStamp
224
223
  }
225
224
  draInterfaceCustomReport(
226
225
  {
227
226
  type: `${this.#reportType}_consumeTime`,
228
227
  url,
229
228
  functionId: data?.functionId,
230
229
  requestTimeStamp: this.#requestTimeStamp,
231
230
  responseTimeStamp: this.#responseTimeStamp,
232
231
  errMsg: `使用${this.#reportType}调用接口请求响应耗时`,
233
232
  source: 'remote',
234
233
  },
235
234
  {
236
235
  consumeTime: `${this.#responseTimeStamp - this.#requestTimeStamp}ms`,
237
236
  getResTime: `${this.#getResTimeStamp - this.#requestTimeStamp}ms`,
238
237
  },
239
238
  )
240
239
  }
241
240
 
242
241
  _handleReportInterfaceError(
243
242
  url: string,
244
243
  reqData: any,
245
244
  timeOut: any,
246
245
  res: any,
247
246
  ): void {
248
247
  const source = 'remote'
249
248
  const requestType = this.#reportType
250
249
  let errorType = ''
251
250
  let subMsg = ''
252
251
  let reportFlag = false
253
252
  if (res) {
254
253
  const { statusCode, data, status, resTimeoutState } = res
255
254
  if (statusCode === 500 && resTimeoutState) {
256
255
  reportFlag = true
257
256
  errorType = 'timeout'
258
257
  subMsg = `接口请求超时${timeOut}ms`
259
258
  } else if ((statusCode === 200 || status === '0') && data) {
260
259
  const resCode = Object.prototype.hasOwnProperty.call(data, 'code')
261
260
  ? Number(data.code)
262
261
  : -1
263
262
  const isSuccess = resCode === 0 || resCode === 200
264
263
  if (!isSuccess) {
265
264
  reportFlag = true
266
265
  errorType = 'dataError'
267
266
  subMsg = '接口请求返回数据异常'
268
267
  }
269
268
  } else {
270
269
  reportFlag = true
271
270
  errorType = 'statusError'
272
271
  subMsg = '接口请求本身异常'
273
272
  }
274
273
  }
275
274
  reportFlag &&
276
275
  draInterfaceCustomReport({
277
276
  subMsg,
278
277
  url,
279
278
  source,
280
279
  requestType,
281
280
  errorType,
282
281
  ...reqData,
283
282
  ...res,
284
283
  })
285
284
  }
285
+ import Taro from '@tarojs/taro'
286
286
  isSupportHybridHttpRequest,
287
287
  draInterfaceCustomReport,
288
288
  draBusinessCustomReport,
289
289
  jsonHeader = 'application/json;charset=utf-8',
290
290
  formDataHeader = 'application/x-www-form-urlencoded',
291
291
  HYBRID: 'httpRequest_hybrid',
292
292
  TARO: 'httpRequest_taro',
293
293
  #requestTimeStamp: number
294
294
  #responseTimeStamp: number
295
295
  #getResTimeStamp: number
296
296
  #reportType: string
297
297
  #callbackFunction: string
298
298
 
299
299
  async request({
300
300
  url,
301
301
  method = 'POST',
302
302
  timeout = 7000,
303
303
  isColorVerify = false,
304
304
  ...otherOptions
305
305
  }): Promise<Taro.request.SuccessCallbackResult<any>> {
306
306
  const { header: otherHeader, ...otherOpts } = otherOptions
307
307
  const header = {
308
308
  'content-type':
309
309
  method === 'POST'
310
310
  ? RequestHeaderContentType.formDataHeader
311
311
  : RequestHeaderContentType.jsonHeader,
312
312
  ...otherHeader,
313
313
  }
314
314
  let getRequestUrl = url
315
315
  let requestTask
316
316
  const data = otherOpts?.data
317
317
  const isGatewayRequest =
318
318
  url === this.api.apiFunc && typeof data === 'object'
319
319
  if (isGatewayRequest) {
320
320
  getRequestUrl = this._handleSpecialGatewayUrl(url)
321
321
  const shouldUseHybridRequest = this._shouldUseHybridRequest(data)
322
322
  if (shouldUseHybridRequest) {
323
323
  requestTask = this._hybridRequest(getRequestUrl, data)
324
324
  } else {
325
325
  otherOpts.data = await this._prepareGatewayReqData(data, isColorVerify)
326
326
  requestTask = this._taroRequest(
327
327
  getRequestUrl,
328
328
  otherOpts,
329
329
  method,
330
330
  timeout,
331
331
  header,
332
332
  )
333
333
  }
334
334
  } else {
335
335
  requestTask = this._taroRequest(
336
336
  getRequestUrl,
337
337
  otherOpts,
338
338
  method,
339
339
  timeout,
340
340
  header,
341
341
  )
342
342
  }
343
343
  const requestTimeoutPromise =
344
344
  new Promise<ServiceInterFace.RequestPromiseRes>((resolve) => {
345
345
  setTimeout(() => {
346
346
  resolve({
347
347
  statusCode: 500,
348
348
  resTimeoutState: true,
349
349
  errMsg: 'request timeout',
350
350
  })
351
351
  }, timeout)
352
352
  })
353
353
  return Promise.race([requestTask, requestTimeoutPromise]).then(
354
354
  (res: any) => {
355
355
  if (res && res.statusCode === 500 && res.resTimeoutState) {
356
356
  if (this.#reportType === HTTP_REQUEST_TYPE.HYBRID) {
357
357
  this._clearFunction(this.#callbackFunction)
358
358
  } else {
359
359
  requestTask.abort && requestTask.abort()
360
360
  }
361
361
  }
362
362
  this._handleReportInterfaceError(url, data, timeout, res)
363
363
  return res
364
364
  },
365
365
  )
366
366
  }
367
367
 
368
368
  _handleSpecialGatewayUrl(url: string): string {
369
369
  if (isPc && window.location.hostname.includes('.jd.hk')) {
370
370
  return this.api.hkApiFunc
371
371
  }
372
372
  if (
373
373
  isJdApp &&
374
374
  window?.shopGlobalSwitch?.dualProtocol &&
375
375
  !window.location.href.includes('jshopx_vconsole')
376
376
  ) {
377
377
  return window?.shopGlobalSwitch?.dualProtocol?.apiTestApp || url
378
378
  }
379
379
  return url
380
380
  }
381
381
 
382
382
  _shouldUseHybridRequest(data: any): boolean {
383
383
  try {
384
384
  const isWhxFunctionId = /^whx\_/.test(data?.functionId)
385
385
  const isGlobalOpenHybirdHttpRequest =
386
386
  window?.shopGlobalSwitch?.openHybirdHttpRequest === 'true'
387
387
  if (
388
388
  !isJdApp ||
389
389
  !isSupportHybridHttpRequest ||
390
390
  !isGlobalOpenHybirdHttpRequest ||
391
391
  isWhxFunctionId ||
392
392
  isJdAndHarmonyDevice
393
393
  ) {
394
394
  return false
395
395
  }
396
396
  const configData = global.getDynamicConfig('hybridHttpSwitch')
397
397
  const { globalOn = false, grayscale = {} } = configData || {}
398
398
  const buildType = process.env.BUILD_TYPE || ''
399
399
  const isInvokeGray = globalOn || grayscale[buildType]
400
400
  console.log(
401
401
  '使用hybrid请求是否命中灰度,isInvokeGray:',
402
402
  isInvokeGray,
403
403
  '获取mpaas配置hybridHttpSwitch原始数据configData',
404
404
  configData,
405
405
  )
406
406
  const hasWindowXWebView = !!window.XWebView
407
407
  return isInvokeGray && hasWindowXWebView
408
408
  } catch (e) {
409
409
  console.log('获取是否使用Hybrid请求出错,e:', e)
410
410
  return false
411
411
  }
412
412
  }
413
413
 
414
414
  _hybridRequest(url: string, data: any): Promise<any> {
415
415
  return new Promise((resolve, reject) => {
416
416
  try {
417
417
  const changeCurrentUrl = url.startsWith('//') ? `https:${url}` : url
418
418
  const { functionId, body, ...otherH5Param } = data
419
419
  const reqParams = {
420
420
  url: isIosDevice ? `${changeCurrentUrl}/` : changeCurrentUrl,
421
421
  functionId: functionId,
422
422
  body: body,
423
423
  headerType: '0',
424
424
  param: {
425
425
  ...otherH5Param,
426
426
  },
427
427
  header: {
428
428
  Referer: window.location.origin,
429
429
  },
430
430
  }
431
431
  const callbackFunction = this._generateCallbackFunction()
432
432
  this.#callbackFunction = callbackFunction
433
433
  this.#requestTimeStamp = Date.now()
434
434
  this.#reportType = HTTP_REQUEST_TYPE.HYBRID
435
435
  window.XWebView.callNative(
436
436
  'ColorQueryPlugin',
437
437
  'colorRequest',
438
438
  JSON.stringify(reqParams),
439
439
  callbackFunction,
440
440
  '1',
441
441
  )
442
442
  window[callbackFunction] = (result) => {
443
443
  this.#responseTimeStamp = Date.now()
444
444
  try {
445
445
  const resultObj =
446
446
  typeof result === 'string' ? JSON.parse(result) : result
447
447
  resolve(resultObj)
448
448
  } catch (error) {
449
449
  const errMsg = 'hybrid网络请求JSON解析失败, error: ' + error
450
450
  draBusinessCustomReport({
451
451
  type: `${HTTP_REQUEST_TYPE.HYBRID}_jsonParseError`,
452
452
  errMsg,
453
453
  result,
454
454
  })
455
455
  reject({ errMsg })
456
456
  }
457
457
  this._clearFunction(callbackFunction)
458
458
  }
459
459
  } catch (error) {
460
460
  reject({
461
461
  errMsg:
462
462
  'hybrid网络请求,App下调用window.XWebView.callNative出错, error: ' +
463
463
  error,
464
464
  })
465
465
  }
466
466
  })
467
467
  }
468
468
 
469
469
  _generateCallbackFunction() {
470
470
  return `hybridHttpRequestCallback_${Date.now()}_${Math.ceil(
471
471
  Math.random() * 100000,
472
472
  )}`
473
473
  }
474
474
 
475
475
  _clearFunction(functionName: string) {
476
476
  try {
477
477
  delete window[functionName]
478
478
  } catch (e) {
479
479
  window[functionName] = undefined
480
480
  }
481
481
  }
482
482
 
483
483
  async _prepareGatewayReqData(
484
484
  data: any,
485
485
  isColorVerify: boolean,
486
486
  ): Promise<any> {
487
487
  const { functionId } = data
488
488
  console.log('获取当前是否需要color加固', isColorVerify, functionId)
489
489
  if (isColorVerify) {
490
490
  const { h5st } = await colorSign.paramsSign(data)
491
491
  h5st && (data.h5st = encodeURI(h5st))
492
492
  console.log(`${functionId}的apiReq_h5st===>:${h5st}`)
493
493
  }
494
494
  const { jsToken } = await colorSign.getFmInfo()
495
495
  console.log(`${functionId}的api jsToken指纹===>:${jsToken}`)
496
496
  jsToken && (data['x-api-eid-token'] = jsToken)
497
497
  return data
498
498
  }
499
499
 
500
500
  _taroRequest(
501
501
  url: string,
502
502
  otherOpts: any,
503
503
  method: string,
504
504
  timeout: number,
505
505
  header: string,
506
506
  ): Promise<any> {
507
507
  const reqParam = {
508
508
  url,
509
509
  method,
510
510
  timeout,
511
511
  header,
512
512
  credentials: 'include',
513
513
  ...otherOpts,
514
514
  }
515
515
  this.#requestTimeStamp = Date.now()
516
516
  this.#reportType = HTTP_REQUEST_TYPE.TARO
517
517
  return Taro.request(reqParam)
518
518
  }
519
519
 
520
520
  _reportRequestTime(url: string, data: any): void {
521
521
  this.#getResTimeStamp = Date.now()
522
522
  if (this.#reportType === HTTP_REQUEST_TYPE.TARO) {
523
523
  this.#responseTimeStamp = this.#getResTimeStamp
524
524
  }
525
525
  draInterfaceCustomReport(
526
526
  {
527
527
  type: `${this.#reportType}_consumeTime`,
528
528
  url,
529
529
  functionId: data?.functionId,
530
530
  requestTimeStamp: this.#requestTimeStamp,
531
531
  responseTimeStamp: this.#responseTimeStamp,
532
532
  errMsg: `使用${this.#reportType}调用接口请求响应耗时`,
533
533
  source: 'remote',
534
534
  },
535
535
  {
536
536
  consumeTime: `${this.#responseTimeStamp - this.#requestTimeStamp}ms`,
537
537
  getResTime: `${this.#getResTimeStamp - this.#requestTimeStamp}ms`,
538
538
  },
539
539
  )
540
540
  }
541
541
 
542
542
  _handleReportInterfaceError(
543
543
  url: string,
544
544
  reqData: any,
545
545
  timeOut: any,
546
546
  res: any,
547
547
  ): void {
548
548
  const source = 'remote'
549
549
  const requestType = this.#reportType
550
550
  let errorType = ''
551
551
  let subMsg = ''
552
552
  let reportFlag = false
553
553
  if (res) {
554
554
  const { statusCode, data, status, resTimeoutState } = res
555
555
  if (statusCode === 500 && resTimeoutState) {
556
556
  reportFlag = true
557
557
  errorType = 'timeout'
558
558
  subMsg = `接口请求超时${timeOut}ms`
559
559
  } else if ((statusCode === 200 || status === '0') && data) {
560
560
  const resCode = Object.prototype.hasOwnProperty.call(data, 'code')
561
561
  ? Number(data.code)
562
562
  : -1
563
563
  const subCode = Object.prototype.hasOwnProperty.call(data, 'subCode')
564
564
  ? Number(data.subCode)
565
565
  : -1
566
566
  const isSuccess =
567
567
  data.success === true ||
568
568
  data.isSuccess ||
569
569
  resCode === 0 ||
570
570
  resCode === 200 ||
571
571
  subCode === 0
572
572
  if (!isSuccess && resCode !== 3) {
573
573
  reportFlag = true
574
574
  errorType = 'dataError'
575
575
  subMsg = '接口请求返回数据异常'
576
576
  }
577
577
  } else {
578
578
  reportFlag = true
579
579
  errorType = 'statusError'
580
580
  subMsg = '接口请求错误,h5请求statusCode非200,或hybrid请求status非0,或未返回data字段'
581
581
  }
582
582
  }
583
583
  reportFlag &&
584
584
  draInterfaceCustomReport({
585
585
  subMsg,
586
586
  url,
587
587
  source,
588
588
  requestType,
589
589
  errorType,
590
590
  functionId: reqData?.functionId,
591
591
  appid: reqData?.appId,
592
592
  client: reqData?.client,
593
593
  clientVersion: reqData?.clientVersion,
594
594
  statusCode: res?.statusCode,
595
595
  status: res?.status,
596
596
  code: res?.data?.code || res?.data?.subCode,
597
597
  errMsg: res?.errMsg || res?.msg || res?.message || res?.data?.echo,
598
598
  originReqDataStr: JSON.stringify(reqData),
599
599
  originResDataStr: JSON.stringify(res),
600
600
  })
601
601
  }