@pluve/mp-logger-sdk 0.0.1

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.
Files changed (84) hide show
  1. package/README.md +133 -0
  2. package/dist/cjs/capture/wechatError.js +85 -0
  3. package/dist/cjs/compress/compression.js +94 -0
  4. package/dist/cjs/config/index.js +48 -0
  5. package/dist/cjs/core/fingerprint.js +32 -0
  6. package/dist/cjs/core/httpClient.js +55 -0
  7. package/dist/cjs/core/loggerSDK.js +580 -0
  8. package/dist/cjs/core/queueManager.js +121 -0
  9. package/dist/cjs/core/retryManager.js +123 -0
  10. package/dist/cjs/index.js +25 -0
  11. package/dist/cjs/stack/stacktrace.js +69 -0
  12. package/dist/cjs/transport/transport.js +17 -0
  13. package/dist/cjs/transport/transportAdapter.js +39 -0
  14. package/dist/cjs/transport/wechatTransport.js +98 -0
  15. package/dist/cjs/types/api.js +17 -0
  16. package/dist/cjs/types/env.js +17 -0
  17. package/dist/cjs/types/external.d.ts +15 -0
  18. package/dist/cjs/types/logEvent.js +17 -0
  19. package/dist/cjs/types/logEventLevel.js +17 -0
  20. package/dist/cjs/types/sdkOptions.js +17 -0
  21. package/dist/cjs/types/securityType.js +34 -0
  22. package/dist/cjs/types/trackOptions.js +17 -0
  23. package/dist/cjs/utils/environment.js +85 -0
  24. package/dist/cjs/utils/innerMD5.js +143 -0
  25. package/dist/cjs/utils/session.js +27 -0
  26. package/dist/cjs/utils/tools.js +73 -0
  27. package/dist/cjs/utils/uuid.js +31 -0
  28. package/dist/esm/capture/wechatError.js +65 -0
  29. package/dist/esm/compress/compression.js +74 -0
  30. package/dist/esm/config/index.js +28 -0
  31. package/dist/esm/core/fingerprint.js +12 -0
  32. package/dist/esm/core/httpClient.js +35 -0
  33. package/dist/esm/core/loggerSDK.js +560 -0
  34. package/dist/esm/core/queueManager.js +101 -0
  35. package/dist/esm/core/retryManager.js +103 -0
  36. package/dist/esm/index.js +5 -0
  37. package/dist/esm/stack/stacktrace.js +49 -0
  38. package/dist/esm/transport/transport.js +0 -0
  39. package/dist/esm/transport/transportAdapter.js +19 -0
  40. package/dist/esm/transport/wechatTransport.js +78 -0
  41. package/dist/esm/types/api.js +0 -0
  42. package/dist/esm/types/env.js +0 -0
  43. package/dist/esm/types/external.d.ts +15 -0
  44. package/dist/esm/types/logEvent.js +0 -0
  45. package/dist/esm/types/logEventLevel.js +0 -0
  46. package/dist/esm/types/sdkOptions.js +0 -0
  47. package/dist/esm/types/securityType.js +14 -0
  48. package/dist/esm/types/trackOptions.js +0 -0
  49. package/dist/esm/utils/environment.js +65 -0
  50. package/dist/esm/utils/innerMD5.js +123 -0
  51. package/dist/esm/utils/session.js +7 -0
  52. package/dist/esm/utils/tools.js +53 -0
  53. package/dist/esm/utils/uuid.js +11 -0
  54. package/dist/types/capture/jsError.d.ts +2 -0
  55. package/dist/types/capture/promiseError.d.ts +2 -0
  56. package/dist/types/capture/resourceError.d.ts +2 -0
  57. package/dist/types/capture/wechatError.d.ts +3 -0
  58. package/dist/types/compress/compression.d.ts +9 -0
  59. package/dist/types/config/index.d.ts +9 -0
  60. package/dist/types/core/fingerprint.d.ts +8 -0
  61. package/dist/types/core/httpClient.d.ts +11 -0
  62. package/dist/types/core/loggerSDK.d.ts +87 -0
  63. package/dist/types/core/queueManager.d.ts +55 -0
  64. package/dist/types/core/retryManager.d.ts +53 -0
  65. package/dist/types/index.d.ts +2 -0
  66. package/dist/types/stack/stacktrace.d.ts +2 -0
  67. package/dist/types/transport/beaconTransport.d.ts +11 -0
  68. package/dist/types/transport/pixelImageTransport.d.ts +11 -0
  69. package/dist/types/transport/transport.d.ts +14 -0
  70. package/dist/types/transport/transportAdapter.d.ts +8 -0
  71. package/dist/types/transport/wechatTransport.d.ts +11 -0
  72. package/dist/types/types/api.d.ts +12 -0
  73. package/dist/types/types/env.d.ts +14 -0
  74. package/dist/types/types/logEvent.d.ts +57 -0
  75. package/dist/types/types/logEventLevel.d.ts +2 -0
  76. package/dist/types/types/sdkOptions.d.ts +61 -0
  77. package/dist/types/types/securityType.d.ts +6 -0
  78. package/dist/types/types/trackOptions.d.ts +7 -0
  79. package/dist/types/utils/environment.d.ts +10 -0
  80. package/dist/types/utils/innerMD5.d.ts +6 -0
  81. package/dist/types/utils/session.d.ts +1 -0
  82. package/dist/types/utils/tools.d.ts +12 -0
  83. package/dist/types/utils/uuid.d.ts +7 -0
  84. package/package.json +65 -0
@@ -0,0 +1,143 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/utils/innerMD5.ts
20
+ var innerMD5_exports = {};
21
+ __export(innerMD5_exports, {
22
+ md5: () => md5
23
+ });
24
+ module.exports = __toCommonJS(innerMD5_exports);
25
+ var md5 = (input) => {
26
+ const k = [
27
+ 3614090360,
28
+ 3905402710,
29
+ 606105819,
30
+ 3250441966,
31
+ 4118548399,
32
+ 1200080426,
33
+ 2821735955,
34
+ 4249261313,
35
+ 1770035416,
36
+ 2336552879,
37
+ 4294925233,
38
+ 2304563134,
39
+ 1804603682,
40
+ 4254626195,
41
+ 2792965006,
42
+ 1236535329,
43
+ 4129170786,
44
+ 3225465664,
45
+ 643717713,
46
+ 3921069994,
47
+ 3593408605,
48
+ 38016083,
49
+ 3634488961,
50
+ 3889429448,
51
+ 568446438,
52
+ 3275163606,
53
+ 4107603335,
54
+ 1163531501,
55
+ 2850285829,
56
+ 4243563512,
57
+ 1735328473,
58
+ 2368359562,
59
+ 4294588738,
60
+ 2272392833,
61
+ 1839030562,
62
+ 4259657740,
63
+ 2763975236,
64
+ 1272893353,
65
+ 4139469664,
66
+ 3200236656,
67
+ 681279174,
68
+ 3936430074,
69
+ 3572445317,
70
+ 76029189,
71
+ 3654602809,
72
+ 3873151461,
73
+ 530742520,
74
+ 3299628645,
75
+ 4096336452,
76
+ 1126891415,
77
+ 2878612391,
78
+ 4237533241,
79
+ 1700485571,
80
+ 2399980690,
81
+ 4293915773,
82
+ 2240044497,
83
+ 1873313359,
84
+ 4264355552,
85
+ 2734768916,
86
+ 1309151649,
87
+ 4149444226,
88
+ 3174756917,
89
+ 718787259,
90
+ 3951481745
91
+ ];
92
+ const str = unescape(encodeURIComponent(input));
93
+ const x = [];
94
+ for (let i = 0; i < str.length * 8; i += 8) {
95
+ x[i >> 5] |= (str.charCodeAt(i / 8) & 255) << i % 32;
96
+ }
97
+ x[str.length * 8 >> 5 << 5] |= 128 << str.length * 8 % 32;
98
+ x[(str.length * 8 + 64 >>> 9 << 4) + 14] = str.length * 8;
99
+ let a = 1732584193;
100
+ let b = -271733879;
101
+ let c = -1732584194;
102
+ let d = 271733878;
103
+ for (let i = 0; i < x.length; i += 16) {
104
+ const olda = a;
105
+ const oldb = b;
106
+ const oldc = c;
107
+ const oldd = d;
108
+ for (let j = 0; j < 64; j += 1) {
109
+ let f;
110
+ let g;
111
+ if (j < 16) {
112
+ f = b & c | ~b & d;
113
+ g = j;
114
+ } else if (j < 32) {
115
+ f = d & b | ~d & c;
116
+ g = (5 * j + 1) % 16;
117
+ } else if (j < 48) {
118
+ f = b ^ c ^ d;
119
+ g = (3 * j + 5) % 16;
120
+ } else {
121
+ f = c ^ (b | ~d);
122
+ g = 7 * j % 16;
123
+ }
124
+ const temp = d;
125
+ d = c;
126
+ c = b;
127
+ b = b + (a + f + k[j] + (x[i + g] || 0) << 7 + (j < 16 ? [7, 12, 17, 22][j % 4] : j < 32 ? [5, 9, 14, 20][j % 4] : j < 48 ? [4, 11, 16, 23][j % 4] : [6, 10, 15, 21][j % 4])) | 0;
128
+ a = temp;
129
+ }
130
+ a = a + olda | 0;
131
+ b = b + oldb | 0;
132
+ c = c + oldc | 0;
133
+ d = d + oldd | 0;
134
+ }
135
+ const hex = (val) => {
136
+ let output = "";
137
+ for (let i = 0; i < 4; i += 1) {
138
+ output += (val >> i * 8 & 255).toString(16).padStart(2, "0");
139
+ }
140
+ return output;
141
+ };
142
+ return hex(a) + hex(b) + hex(c) + hex(d);
143
+ };
@@ -0,0 +1,27 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/utils/session.ts
20
+ var session_exports = {};
21
+ __export(session_exports, {
22
+ getSessionId: () => getSessionId
23
+ });
24
+ module.exports = __toCommonJS(session_exports);
25
+ function getSessionId() {
26
+ return `${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
27
+ }
@@ -0,0 +1,73 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/utils/tools.ts
20
+ var tools_exports = {};
21
+ __export(tools_exports, {
22
+ flattenStack: () => flattenStack,
23
+ hashToProb: () => hashToProb,
24
+ logDebug: () => logDebug,
25
+ normalizeMessage: () => normalizeMessage,
26
+ now: () => now,
27
+ safeStringify: () => safeStringify
28
+ });
29
+ module.exports = __toCommonJS(tools_exports);
30
+ var import_stacktrace = require("../stack/stacktrace");
31
+ var now = () => Date.now();
32
+ function safeStringify(obj) {
33
+ const seen = /* @__PURE__ */ new WeakSet();
34
+ return JSON.stringify(obj, (_k, v) => {
35
+ if (v && typeof v === "object") {
36
+ if (seen.has(v))
37
+ return "[Circular]";
38
+ seen.add(v);
39
+ }
40
+ return v;
41
+ });
42
+ }
43
+ function normalizeMessage(message) {
44
+ return message.replace(/\d+/g, "{n}").replace(/https?:\/\/\S+/g, "{url}").replace(/[a-f0-9]{16,}/gi, "{id}").slice(0, 200);
45
+ }
46
+ function logDebug(debug, ...args) {
47
+ if (debug)
48
+ console.debug("[LoggerSDK]", ...args);
49
+ }
50
+ function hashToProb(s) {
51
+ let h = 2166136261 >>> 0;
52
+ for (let i = 0; i < s.length; i += 1) {
53
+ h ^= s.charCodeAt(i);
54
+ h = h + (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24) >>> 0;
55
+ }
56
+ return h % 1e4 / 1e4;
57
+ }
58
+ async function flattenStack(error) {
59
+ if (!error) {
60
+ return {
61
+ location: "",
62
+ throwable: ""
63
+ };
64
+ }
65
+ const stackFrames = await (0, import_stacktrace.parseStack)(error);
66
+ return stackFrames && stackFrames.length > 0 ? {
67
+ location: [stackFrames[0]].map((frame) => `${frame.file}:${frame.line}:${frame.column}`).join("\n "),
68
+ throwable: stackFrames.map((frame) => `${frame.file}:${frame.line}:${frame.column}`).join("\n ")
69
+ } : {
70
+ location: "",
71
+ throwable: ""
72
+ };
73
+ }
@@ -0,0 +1,31 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/utils/uuid.ts
20
+ var uuid_exports = {};
21
+ __export(uuid_exports, {
22
+ uuid: () => uuid
23
+ });
24
+ module.exports = __toCommonJS(uuid_exports);
25
+ function uuid() {
26
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
27
+ const r = Math.floor(Math.random() * 16);
28
+ const v = c === "x" ? r : Math.floor(r % 4 + 8);
29
+ return v.toString(16);
30
+ });
31
+ }
@@ -0,0 +1,65 @@
1
+ // src/capture/wechatError.ts
2
+ import { parseStack } from "../stack/stacktrace";
3
+ import { logDebug } from "../utils/tools";
4
+ function registerWechatErrorCapture(debug, callback) {
5
+ try {
6
+ const wxAny = globalThis.wx;
7
+ if (wxAny && typeof wxAny.onError === "function") {
8
+ const handler = async (error) => {
9
+ logDebug(debug, "registerWechatErrorCapture onError", error);
10
+ const msg = String((error == null ? void 0 : error.message) ?? error);
11
+ const err = error instanceof Error ? error : new Error(msg);
12
+ const stack = await parseStack(err);
13
+ callback({
14
+ type: "js",
15
+ message: err.message,
16
+ stack,
17
+ throwable: err.stack || ""
18
+ });
19
+ };
20
+ wxAny.onError(handler);
21
+ return () => {
22
+ try {
23
+ wxAny.offError && wxAny.offError(handler);
24
+ } catch {
25
+ }
26
+ };
27
+ }
28
+ } catch (e) {
29
+ logDebug(debug, "registerWechatErrorCapture attach failed", e);
30
+ }
31
+ return void 0;
32
+ }
33
+ function registerWechatUnhandledCapture(debug, callback) {
34
+ try {
35
+ const wxAny = globalThis.wx;
36
+ if (wxAny && typeof wxAny.onUnhandledRejection === "function") {
37
+ const handler = async (res) => {
38
+ const reason = res == null ? void 0 : res.reason;
39
+ logDebug(debug, "registerWechatUnhandledCapture onUnhandledRejection", reason);
40
+ const err = reason instanceof Error ? reason : new Error(String(reason));
41
+ const stack = await parseStack(err);
42
+ callback({
43
+ type: "promise",
44
+ message: err.message,
45
+ stack,
46
+ throwable: err.stack || ""
47
+ });
48
+ };
49
+ wxAny.onUnhandledRejection(handler);
50
+ return () => {
51
+ try {
52
+ wxAny.offUnhandledRejection && wxAny.offUnhandledRejection(handler);
53
+ } catch {
54
+ }
55
+ };
56
+ }
57
+ } catch (e) {
58
+ logDebug(debug, "registerWechatUnhandledCapture attach failed", e);
59
+ }
60
+ return void 0;
61
+ }
62
+ export {
63
+ registerWechatErrorCapture,
64
+ registerWechatUnhandledCapture
65
+ };
@@ -0,0 +1,74 @@
1
+ // src/compress/compression.ts
2
+ import { gzipSync } from "fflate";
3
+ function toUtf8Bytes(s) {
4
+ if (typeof TextEncoder !== "undefined") {
5
+ return new TextEncoder().encode(s);
6
+ }
7
+ const enc = encodeURIComponent(s);
8
+ const out = [];
9
+ for (let i = 0; i < enc.length; i += 1) {
10
+ const c = enc[i];
11
+ if (c === "%") {
12
+ out.push(parseInt(enc.slice(i + 1, i + 3), 16));
13
+ i += 2;
14
+ } else {
15
+ out.push(c.charCodeAt(0));
16
+ }
17
+ }
18
+ return new Uint8Array(out);
19
+ }
20
+ async function gzipCompress(data) {
21
+ try {
22
+ const input = toUtf8Bytes(data);
23
+ const compressed = gzipSync(input);
24
+ return convert2Base64FromArray(compressed);
25
+ } catch (e) {
26
+ console.log("gzipCompress 压缩失败", e);
27
+ }
28
+ throw new Error("gzipCompress 不支持压缩");
29
+ }
30
+ function isGzipSupported() {
31
+ return true;
32
+ }
33
+ function convert2Base64FromArray(data) {
34
+ try {
35
+ if (typeof wx !== "undefined" && wx.arrayBufferToBase64) {
36
+ if (data.byteLength !== data.buffer.byteLength) {
37
+ const copy = new Uint8Array(data);
38
+ return wx.arrayBufferToBase64(copy.buffer);
39
+ }
40
+ return wx.arrayBufferToBase64(data.buffer);
41
+ }
42
+ } catch (e) {
43
+ }
44
+ let binary = "";
45
+ for (let i = 0; i < data.length; i += 1) {
46
+ binary += String.fromCharCode(data[i]);
47
+ }
48
+ if (typeof btoa !== "undefined") {
49
+ return btoa(binary);
50
+ }
51
+ throw new Error("convert2Base64FromArray 不支持转换");
52
+ }
53
+ async function convert2Base64(data) {
54
+ if (typeof btoa !== "undefined") {
55
+ try {
56
+ return btoa(data);
57
+ } catch {
58
+ }
59
+ }
60
+ try {
61
+ const bytes = toUtf8Bytes(data);
62
+ if (typeof wx !== "undefined" && wx.arrayBufferToBase64) {
63
+ return wx.arrayBufferToBase64(bytes.buffer);
64
+ }
65
+ } catch (e) {
66
+ }
67
+ return data;
68
+ }
69
+ export {
70
+ convert2Base64,
71
+ convert2Base64FromArray,
72
+ gzipCompress,
73
+ isGzipSupported
74
+ };
@@ -0,0 +1,28 @@
1
+ // src/config/index.ts
2
+ var getSDKBaseApi = (env) => {
3
+ switch (env) {
4
+ case "product":
5
+ return "https://apm.pharmacyyf.com";
6
+ case "testing":
7
+ return "https://apm-te.pharmacyyf.com";
8
+ case "develop":
9
+ return "https://chief-dev.yifengx.com";
10
+ default:
11
+ return "https://apm.pharmacyyf.com";
12
+ }
13
+ };
14
+ var getRegisterApi = (env) => {
15
+ return `${getSDKBaseApi(env)}/yfcloud-apm/log/front/init`;
16
+ };
17
+ var getReportApi = (env) => {
18
+ return `${getSDKBaseApi(env)}/yfcloud-apm/log/front/batchSave`;
19
+ };
20
+ var getPixelBatchApi = (env) => {
21
+ return `${getSDKBaseApi(env)}/yfcloud-apm/log/front/pixelBatchSave`;
22
+ };
23
+ export {
24
+ getPixelBatchApi,
25
+ getRegisterApi,
26
+ getReportApi,
27
+ getSDKBaseApi
28
+ };
@@ -0,0 +1,12 @@
1
+ // src/core/fingerprint.ts
2
+ import { normalizeMessage } from "../utils/tools";
3
+ function generateFingerprint(error) {
4
+ var _a;
5
+ const msg = normalizeMessage(error.message);
6
+ const frame = (_a = error.stack) == null ? void 0 : _a[0];
7
+ const frameKey = frame ? `${frame.file}:${frame.line}` : "no_frame";
8
+ return `${error.type}|${msg}|${frameKey}`;
9
+ }
10
+ export {
11
+ generateFingerprint
12
+ };
@@ -0,0 +1,35 @@
1
+ // src/core/httpClient.ts
2
+ import { logDebug } from "../utils/tools";
3
+ var HttpClient = class {
4
+ /**
5
+ * 发送 POST 请求,需要兼容浏览器和微信小程序
6
+ */
7
+ static async post(url, data, token) {
8
+ logDebug(true, "post", url, data, token);
9
+ return new Promise((resolve, reject) => {
10
+ wx.request({
11
+ url,
12
+ method: "POST",
13
+ data,
14
+ header: {
15
+ "Content-Type": "application/json",
16
+ token
17
+ },
18
+ success: (res) => resolve({
19
+ type: "wechat",
20
+ response: res
21
+ }),
22
+ fail: (err) => (
23
+ // eslint-disable-next-line prefer-promise-reject-errors
24
+ reject({
25
+ type: "wechat",
26
+ error: err
27
+ })
28
+ )
29
+ });
30
+ });
31
+ }
32
+ };
33
+ export {
34
+ HttpClient
35
+ };