@hono/node-server 1.7.0 → 1.8.0

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.
@@ -4,8 +4,9 @@ import { createReadStream, existsSync, lstatSync } from "fs";
4
4
  // node_modules/hono/dist/utils/filepath.js
5
5
  var getFilePath = (options) => {
6
6
  let filename = options.filename;
7
- if (/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(filename))
7
+ if (/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(filename)) {
8
8
  return;
9
+ }
9
10
  let root = options.root || "";
10
11
  const defaultDocument = options.defaultDocument || "index.html";
11
12
  if (filename.endsWith("/")) {
@@ -22,34 +23,27 @@ var getFilePath = (options) => {
22
23
  };
23
24
 
24
25
  // node_modules/hono/dist/utils/mime.js
25
- var getMimeType = (filename) => {
26
+ var getMimeType = (filename, mimes = baseMimes) => {
26
27
  const regexp = /\.([a-zA-Z0-9]+?)$/;
27
28
  const match = filename.match(regexp);
28
- if (!match)
29
+ if (!match) {
29
30
  return;
31
+ }
30
32
  let mimeType = mimes[match[1]];
31
33
  if (mimeType && mimeType.startsWith("text") || mimeType === "application/json") {
32
34
  mimeType += "; charset=utf-8";
33
35
  }
34
36
  return mimeType;
35
37
  };
36
- var mimes = {
38
+ var baseMimes = {
37
39
  aac: "audio/aac",
38
- abw: "application/x-abiword",
39
- arc: "application/x-freearc",
40
40
  avi: "video/x-msvideo",
41
41
  avif: "image/avif",
42
42
  av1: "video/av1",
43
- azw: "application/vnd.amazon.ebook",
44
43
  bin: "application/octet-stream",
45
44
  bmp: "image/bmp",
46
- bz: "application/x-bzip",
47
- bz2: "application/x-bzip2",
48
- csh: "application/x-csh",
49
45
  css: "text/css",
50
46
  csv: "text/csv",
51
- doc: "application/msword",
52
- docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
53
47
  eot: "application/vnd.ms-fontobject",
54
48
  epub: "application/epub+zip",
55
49
  gif: "image/gif",
@@ -58,7 +52,6 @@ var mimes = {
58
52
  html: "text/html",
59
53
  ico: "image/x-icon",
60
54
  ics: "text/calendar",
61
- jar: "application/java-archive",
62
55
  jpeg: "image/jpeg",
63
56
  jpg: "image/jpeg",
64
57
  js: "text/javascript",
@@ -71,31 +64,20 @@ var mimes = {
71
64
  mp3: "audio/mpeg",
72
65
  mp4: "video/mp4",
73
66
  mpeg: "video/mpeg",
74
- mpkg: "application/vnd.apple.installer+xml",
75
- odp: "application/vnd.oasis.opendocument.presentation",
76
- ods: "application/vnd.oasis.opendocument.spreadsheet",
77
- odt: "application/vnd.oasis.opendocument.text",
78
67
  oga: "audio/ogg",
79
68
  ogv: "video/ogg",
80
69
  ogx: "application/ogg",
81
70
  opus: "audio/opus",
82
71
  otf: "font/otf",
83
72
  pdf: "application/pdf",
84
- php: "application/php",
85
73
  png: "image/png",
86
- ppt: "application/vnd.ms-powerpoint",
87
- pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
88
74
  rtf: "application/rtf",
89
- sh: "application/x-sh",
90
75
  svg: "image/svg+xml",
91
- swf: "application/x-shockwave-flash",
92
- tar: "application/x-tar",
93
76
  tif: "image/tiff",
94
77
  tiff: "image/tiff",
95
78
  ts: "video/mp2t",
96
79
  ttf: "font/ttf",
97
80
  txt: "text/plain",
98
- vsd: "application/vnd.visio",
99
81
  wasm: "application/wasm",
100
82
  webm: "video/webm",
101
83
  weba: "audio/webm",
@@ -103,14 +85,10 @@ var mimes = {
103
85
  woff: "font/woff",
104
86
  woff2: "font/woff2",
105
87
  xhtml: "application/xhtml+xml",
106
- xls: "application/vnd.ms-excel",
107
- xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
108
88
  xml: "application/xml",
109
- xul: "application/vnd.mozilla.xul+xml",
110
89
  zip: "application/zip",
111
90
  "3gp": "video/3gpp",
112
91
  "3g2": "video/3gpp2",
113
- "7z": "application/x-7z-compressed",
114
92
  gltf: "model/gltf+json",
115
93
  glb: "model/gltf-binary"
116
94
  };
package/dist/server.js CHANGED
@@ -55,7 +55,7 @@ var Request = class extends GlobalRequest {
55
55
  Object.defineProperty(global, "Request", {
56
56
  value: Request
57
57
  });
58
- var newRequestFromIncoming = (method, url, incoming) => {
58
+ var newRequestFromIncoming = (method, url, incoming, abortController) => {
59
59
  const headerRecord = [];
60
60
  const rawHeaders = incoming.rawHeaders;
61
61
  for (let i = 0; i < rawHeaders.length; i += 2) {
@@ -67,7 +67,8 @@ var newRequestFromIncoming = (method, url, incoming) => {
67
67
  }
68
68
  const init = {
69
69
  method,
70
- headers: headerRecord
70
+ headers: headerRecord,
71
+ signal: abortController.signal
71
72
  };
72
73
  if (!(method === "GET" || method === "HEAD")) {
73
74
  init.body = import_node_stream.Readable.toWeb(incoming);
@@ -78,6 +79,8 @@ var getRequestCache = Symbol("getRequestCache");
78
79
  var requestCache = Symbol("requestCache");
79
80
  var incomingKey = Symbol("incomingKey");
80
81
  var urlKey = Symbol("urlKey");
82
+ var abortControllerKey = Symbol("abortControllerKey");
83
+ var getAbortController = Symbol("getAbortController");
81
84
  var requestPrototype = {
82
85
  get method() {
83
86
  return this[incomingKey].method || "GET";
@@ -85,11 +88,17 @@ var requestPrototype = {
85
88
  get url() {
86
89
  return this[urlKey];
87
90
  },
91
+ [getAbortController]() {
92
+ this[getRequestCache]();
93
+ return this[abortControllerKey];
94
+ },
88
95
  [getRequestCache]() {
96
+ this[abortControllerKey] ||= new AbortController();
89
97
  return this[requestCache] ||= newRequestFromIncoming(
90
98
  this.method,
91
99
  this[urlKey],
92
- this[incomingKey]
100
+ this[incomingKey],
101
+ this[abortControllerKey]
93
102
  );
94
103
  }
95
104
  };
@@ -183,18 +192,19 @@ var buildOutgoingHttpHeaders = (headers) => {
183
192
  if (cookies.length > 0) {
184
193
  res["set-cookie"] = cookies;
185
194
  }
186
- res["content-type"] ??= "text/plain;charset=UTF-8";
195
+ res["content-type"] ??= "text/plain; charset=UTF-8";
187
196
  return res;
188
197
  };
189
198
 
190
199
  // src/response.ts
191
200
  var responseCache = Symbol("responseCache");
201
+ var getResponseCache = Symbol("getResponseCache");
192
202
  var cacheKey = Symbol("cache");
193
203
  var GlobalResponse = global.Response;
194
204
  var Response2 = class _Response {
195
205
  #body;
196
206
  #init;
197
- get cache() {
207
+ [getResponseCache]() {
198
208
  delete this[cacheKey];
199
209
  return this[responseCache] ||= new GlobalResponse(this.#body, this.#init);
200
210
  }
@@ -204,7 +214,7 @@ var Response2 = class _Response {
204
214
  const cachedGlobalResponse = init[responseCache];
205
215
  if (cachedGlobalResponse) {
206
216
  this.#init = cachedGlobalResponse;
207
- this.cache;
217
+ this[getResponseCache]();
208
218
  return;
209
219
  } else {
210
220
  this.#init = init.#init;
@@ -213,7 +223,7 @@ var Response2 = class _Response {
213
223
  this.#init = init;
214
224
  }
215
225
  if (typeof body === "string" || body instanceof ReadableStream) {
216
- let headers = init?.headers || { "content-type": "text/plain;charset=UTF-8" };
226
+ let headers = init?.headers || { "content-type": "text/plain; charset=UTF-8" };
217
227
  if (headers instanceof Headers) {
218
228
  headers = buildOutgoingHttpHeaders(headers);
219
229
  }
@@ -236,14 +246,14 @@ var Response2 = class _Response {
236
246
  ].forEach((k) => {
237
247
  Object.defineProperty(Response2.prototype, k, {
238
248
  get() {
239
- return this.cache[k];
249
+ return this[getResponseCache]()[k];
240
250
  }
241
251
  });
242
252
  });
243
253
  ["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
244
254
  Object.defineProperty(Response2.prototype, k, {
245
255
  value: function() {
246
- return this.cache[k]();
256
+ return this[getResponseCache]()[k]();
247
257
  }
248
258
  });
249
259
  });
@@ -252,6 +262,22 @@ Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
252
262
  Object.defineProperty(global, "Response", {
253
263
  value: Response2
254
264
  });
265
+ var stateKey = Reflect.ownKeys(new GlobalResponse()).find(
266
+ (k) => typeof k === "symbol" && k.toString() === "Symbol(state)"
267
+ );
268
+ if (!stateKey) {
269
+ console.warn("Failed to find Response internal state key");
270
+ }
271
+ function getInternalBody(response) {
272
+ if (!stateKey) {
273
+ return;
274
+ }
275
+ if (response instanceof Response2) {
276
+ response = response[getResponseCache]();
277
+ }
278
+ const state = response[stateKey];
279
+ return state && state.body || void 0;
280
+ }
255
281
 
256
282
  // src/globals.ts
257
283
  var import_node_crypto = __toESM(require("crypto"));
@@ -317,36 +343,40 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
317
343
  res = await res.catch(handleFetchError);
318
344
  }
319
345
  }
320
- try {
321
- const isCached = cacheKey in res;
322
- if (isCached) {
323
- return responseViaCache(res, outgoing);
324
- }
325
- } catch (e) {
326
- return handleResponseError(e, outgoing);
346
+ if (cacheKey in res) {
347
+ return responseViaCache(res, outgoing);
327
348
  }
328
349
  const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
329
- if (res.body) {
330
- try {
331
- const {
332
- "transfer-encoding": transferEncoding,
333
- "content-encoding": contentEncoding,
334
- "content-length": contentLength,
335
- "x-accel-buffering": accelBuffering,
336
- "content-type": contentType
337
- } = resHeaderRecord;
338
- if (transferEncoding || contentEncoding || contentLength || // nginx buffering variant
339
- accelBuffering && regBuffer.test(accelBuffering) || !regContentType.test(contentType)) {
340
- outgoing.writeHead(res.status, resHeaderRecord);
341
- await writeFromReadableStream(res.body, outgoing);
342
- } else {
343
- const buffer = await res.arrayBuffer();
344
- resHeaderRecord["content-length"] = buffer.byteLength;
345
- outgoing.writeHead(res.status, resHeaderRecord);
346
- outgoing.end(new Uint8Array(buffer));
347
- }
348
- } catch (e) {
349
- handleResponseError(e, outgoing);
350
+ const internalBody = getInternalBody(res);
351
+ if (internalBody) {
352
+ if (internalBody.length) {
353
+ resHeaderRecord["content-length"] = internalBody.length;
354
+ }
355
+ outgoing.writeHead(res.status, resHeaderRecord);
356
+ if (typeof internalBody.source === "string" || internalBody.source instanceof Uint8Array) {
357
+ outgoing.end(internalBody.source);
358
+ } else if (internalBody.source instanceof Blob) {
359
+ outgoing.end(new Uint8Array(await internalBody.source.arrayBuffer()));
360
+ } else {
361
+ await writeFromReadableStream(internalBody.stream, outgoing);
362
+ }
363
+ } else if (res.body) {
364
+ const {
365
+ "transfer-encoding": transferEncoding,
366
+ "content-encoding": contentEncoding,
367
+ "content-length": contentLength,
368
+ "x-accel-buffering": accelBuffering,
369
+ "content-type": contentType
370
+ } = resHeaderRecord;
371
+ if (transferEncoding || contentEncoding || contentLength || // nginx buffering variant
372
+ accelBuffering && regBuffer.test(accelBuffering) || !regContentType.test(contentType)) {
373
+ outgoing.writeHead(res.status, resHeaderRecord);
374
+ await writeFromReadableStream(res.body, outgoing);
375
+ } else {
376
+ const buffer = await res.arrayBuffer();
377
+ resHeaderRecord["content-length"] = buffer.byteLength;
378
+ outgoing.writeHead(res.status, resHeaderRecord);
379
+ outgoing.end(new Uint8Array(buffer));
350
380
  }
351
381
  } else {
352
382
  outgoing.writeHead(res.status, resHeaderRecord);
@@ -357,6 +387,11 @@ var getRequestListener = (fetchCallback, options = {}) => {
357
387
  return async (incoming, outgoing) => {
358
388
  let res;
359
389
  const req = newRequest(incoming);
390
+ outgoing.on("close", () => {
391
+ if (incoming.destroyed) {
392
+ req[getAbortController]().abort();
393
+ }
394
+ });
360
395
  try {
361
396
  res = fetchCallback(req, { incoming, outgoing });
362
397
  if (cacheKey in res) {
@@ -376,7 +411,11 @@ var getRequestListener = (fetchCallback, options = {}) => {
376
411
  return handleResponseError(e, outgoing);
377
412
  }
378
413
  }
379
- return responseViaResponseObject(res, outgoing, options);
414
+ try {
415
+ return responseViaResponseObject(res, outgoing, options);
416
+ } catch (e) {
417
+ return handleResponseError(e, outgoing);
418
+ }
380
419
  };
381
420
  };
382
421
 
package/dist/server.mjs CHANGED
@@ -20,7 +20,7 @@ var Request = class extends GlobalRequest {
20
20
  Object.defineProperty(global, "Request", {
21
21
  value: Request
22
22
  });
23
- var newRequestFromIncoming = (method, url, incoming) => {
23
+ var newRequestFromIncoming = (method, url, incoming, abortController) => {
24
24
  const headerRecord = [];
25
25
  const rawHeaders = incoming.rawHeaders;
26
26
  for (let i = 0; i < rawHeaders.length; i += 2) {
@@ -32,7 +32,8 @@ var newRequestFromIncoming = (method, url, incoming) => {
32
32
  }
33
33
  const init = {
34
34
  method,
35
- headers: headerRecord
35
+ headers: headerRecord,
36
+ signal: abortController.signal
36
37
  };
37
38
  if (!(method === "GET" || method === "HEAD")) {
38
39
  init.body = Readable.toWeb(incoming);
@@ -43,6 +44,8 @@ var getRequestCache = Symbol("getRequestCache");
43
44
  var requestCache = Symbol("requestCache");
44
45
  var incomingKey = Symbol("incomingKey");
45
46
  var urlKey = Symbol("urlKey");
47
+ var abortControllerKey = Symbol("abortControllerKey");
48
+ var getAbortController = Symbol("getAbortController");
46
49
  var requestPrototype = {
47
50
  get method() {
48
51
  return this[incomingKey].method || "GET";
@@ -50,11 +53,17 @@ var requestPrototype = {
50
53
  get url() {
51
54
  return this[urlKey];
52
55
  },
56
+ [getAbortController]() {
57
+ this[getRequestCache]();
58
+ return this[abortControllerKey];
59
+ },
53
60
  [getRequestCache]() {
61
+ this[abortControllerKey] ||= new AbortController();
54
62
  return this[requestCache] ||= newRequestFromIncoming(
55
63
  this.method,
56
64
  this[urlKey],
57
- this[incomingKey]
65
+ this[incomingKey],
66
+ this[abortControllerKey]
58
67
  );
59
68
  }
60
69
  };
@@ -148,18 +157,19 @@ var buildOutgoingHttpHeaders = (headers) => {
148
157
  if (cookies.length > 0) {
149
158
  res["set-cookie"] = cookies;
150
159
  }
151
- res["content-type"] ??= "text/plain;charset=UTF-8";
160
+ res["content-type"] ??= "text/plain; charset=UTF-8";
152
161
  return res;
153
162
  };
154
163
 
155
164
  // src/response.ts
156
165
  var responseCache = Symbol("responseCache");
166
+ var getResponseCache = Symbol("getResponseCache");
157
167
  var cacheKey = Symbol("cache");
158
168
  var GlobalResponse = global.Response;
159
169
  var Response2 = class _Response {
160
170
  #body;
161
171
  #init;
162
- get cache() {
172
+ [getResponseCache]() {
163
173
  delete this[cacheKey];
164
174
  return this[responseCache] ||= new GlobalResponse(this.#body, this.#init);
165
175
  }
@@ -169,7 +179,7 @@ var Response2 = class _Response {
169
179
  const cachedGlobalResponse = init[responseCache];
170
180
  if (cachedGlobalResponse) {
171
181
  this.#init = cachedGlobalResponse;
172
- this.cache;
182
+ this[getResponseCache]();
173
183
  return;
174
184
  } else {
175
185
  this.#init = init.#init;
@@ -178,7 +188,7 @@ var Response2 = class _Response {
178
188
  this.#init = init;
179
189
  }
180
190
  if (typeof body === "string" || body instanceof ReadableStream) {
181
- let headers = init?.headers || { "content-type": "text/plain;charset=UTF-8" };
191
+ let headers = init?.headers || { "content-type": "text/plain; charset=UTF-8" };
182
192
  if (headers instanceof Headers) {
183
193
  headers = buildOutgoingHttpHeaders(headers);
184
194
  }
@@ -201,14 +211,14 @@ var Response2 = class _Response {
201
211
  ].forEach((k) => {
202
212
  Object.defineProperty(Response2.prototype, k, {
203
213
  get() {
204
- return this.cache[k];
214
+ return this[getResponseCache]()[k];
205
215
  }
206
216
  });
207
217
  });
208
218
  ["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
209
219
  Object.defineProperty(Response2.prototype, k, {
210
220
  value: function() {
211
- return this.cache[k]();
221
+ return this[getResponseCache]()[k]();
212
222
  }
213
223
  });
214
224
  });
@@ -217,6 +227,22 @@ Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
217
227
  Object.defineProperty(global, "Response", {
218
228
  value: Response2
219
229
  });
230
+ var stateKey = Reflect.ownKeys(new GlobalResponse()).find(
231
+ (k) => typeof k === "symbol" && k.toString() === "Symbol(state)"
232
+ );
233
+ if (!stateKey) {
234
+ console.warn("Failed to find Response internal state key");
235
+ }
236
+ function getInternalBody(response) {
237
+ if (!stateKey) {
238
+ return;
239
+ }
240
+ if (response instanceof Response2) {
241
+ response = response[getResponseCache]();
242
+ }
243
+ const state = response[stateKey];
244
+ return state && state.body || void 0;
245
+ }
220
246
 
221
247
  // src/globals.ts
222
248
  import crypto from "crypto";
@@ -282,36 +308,40 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
282
308
  res = await res.catch(handleFetchError);
283
309
  }
284
310
  }
285
- try {
286
- const isCached = cacheKey in res;
287
- if (isCached) {
288
- return responseViaCache(res, outgoing);
289
- }
290
- } catch (e) {
291
- return handleResponseError(e, outgoing);
311
+ if (cacheKey in res) {
312
+ return responseViaCache(res, outgoing);
292
313
  }
293
314
  const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
294
- if (res.body) {
295
- try {
296
- const {
297
- "transfer-encoding": transferEncoding,
298
- "content-encoding": contentEncoding,
299
- "content-length": contentLength,
300
- "x-accel-buffering": accelBuffering,
301
- "content-type": contentType
302
- } = resHeaderRecord;
303
- if (transferEncoding || contentEncoding || contentLength || // nginx buffering variant
304
- accelBuffering && regBuffer.test(accelBuffering) || !regContentType.test(contentType)) {
305
- outgoing.writeHead(res.status, resHeaderRecord);
306
- await writeFromReadableStream(res.body, outgoing);
307
- } else {
308
- const buffer = await res.arrayBuffer();
309
- resHeaderRecord["content-length"] = buffer.byteLength;
310
- outgoing.writeHead(res.status, resHeaderRecord);
311
- outgoing.end(new Uint8Array(buffer));
312
- }
313
- } catch (e) {
314
- handleResponseError(e, outgoing);
315
+ const internalBody = getInternalBody(res);
316
+ if (internalBody) {
317
+ if (internalBody.length) {
318
+ resHeaderRecord["content-length"] = internalBody.length;
319
+ }
320
+ outgoing.writeHead(res.status, resHeaderRecord);
321
+ if (typeof internalBody.source === "string" || internalBody.source instanceof Uint8Array) {
322
+ outgoing.end(internalBody.source);
323
+ } else if (internalBody.source instanceof Blob) {
324
+ outgoing.end(new Uint8Array(await internalBody.source.arrayBuffer()));
325
+ } else {
326
+ await writeFromReadableStream(internalBody.stream, outgoing);
327
+ }
328
+ } else if (res.body) {
329
+ const {
330
+ "transfer-encoding": transferEncoding,
331
+ "content-encoding": contentEncoding,
332
+ "content-length": contentLength,
333
+ "x-accel-buffering": accelBuffering,
334
+ "content-type": contentType
335
+ } = resHeaderRecord;
336
+ if (transferEncoding || contentEncoding || contentLength || // nginx buffering variant
337
+ accelBuffering && regBuffer.test(accelBuffering) || !regContentType.test(contentType)) {
338
+ outgoing.writeHead(res.status, resHeaderRecord);
339
+ await writeFromReadableStream(res.body, outgoing);
340
+ } else {
341
+ const buffer = await res.arrayBuffer();
342
+ resHeaderRecord["content-length"] = buffer.byteLength;
343
+ outgoing.writeHead(res.status, resHeaderRecord);
344
+ outgoing.end(new Uint8Array(buffer));
315
345
  }
316
346
  } else {
317
347
  outgoing.writeHead(res.status, resHeaderRecord);
@@ -322,6 +352,11 @@ var getRequestListener = (fetchCallback, options = {}) => {
322
352
  return async (incoming, outgoing) => {
323
353
  let res;
324
354
  const req = newRequest(incoming);
355
+ outgoing.on("close", () => {
356
+ if (incoming.destroyed) {
357
+ req[getAbortController]().abort();
358
+ }
359
+ });
325
360
  try {
326
361
  res = fetchCallback(req, { incoming, outgoing });
327
362
  if (cacheKey in res) {
@@ -341,7 +376,11 @@ var getRequestListener = (fetchCallback, options = {}) => {
341
376
  return handleResponseError(e, outgoing);
342
377
  }
343
378
  }
344
- return responseViaResponseObject(res, outgoing, options);
379
+ try {
380
+ return responseViaResponseObject(res, outgoing, options);
381
+ } catch (e) {
382
+ return handleResponseError(e, outgoing);
383
+ }
345
384
  };
346
385
  };
347
386
 
package/dist/utils.js CHANGED
@@ -76,7 +76,7 @@ var buildOutgoingHttpHeaders = (headers) => {
76
76
  if (cookies.length > 0) {
77
77
  res["set-cookie"] = cookies;
78
78
  }
79
- res["content-type"] ??= "text/plain;charset=UTF-8";
79
+ res["content-type"] ??= "text/plain; charset=UTF-8";
80
80
  return res;
81
81
  };
82
82
  // Annotate the CommonJS export names for ESM import in node:
package/dist/utils.mjs CHANGED
@@ -51,7 +51,7 @@ var buildOutgoingHttpHeaders = (headers) => {
51
51
  if (cookies.length > 0) {
52
52
  res["set-cookie"] = cookies;
53
53
  }
54
- res["content-type"] ??= "text/plain;charset=UTF-8";
54
+ res["content-type"] ??= "text/plain; charset=UTF-8";
55
55
  return res;
56
56
  };
57
57
  export {