@faasjs/http 7.1.0 → 8.0.0-beta.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.
package/README.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @faasjs/http
2
2
 
3
+ FaasJS's http plugin.
4
+
5
+ [![License: MIT](https://img.shields.io/npm/l/@faasjs/http.svg)](https://github.com/faasjs/faasjs/blob/main/packages/http/LICENSE)
6
+ [![NPM Version](https://img.shields.io/npm/v/@faasjs/http.svg)](https://www.npmjs.com/package/@faasjs/http)
7
+
8
+ ## Install
9
+
10
+ ```sh
11
+ npm install @faasjs/http
12
+ ```
13
+
3
14
  ## Functions
4
15
 
5
16
  - [useHttp](functions/useHttp.md)
package/dist/index.cjs CHANGED
@@ -207,7 +207,7 @@ function deepClone(obj) {
207
207
  if (Array.isArray(obj)) return JSON.parse(JSON.stringify(obj));
208
208
  const clone = {};
209
209
  for (const key in obj) {
210
- if (!obj.hasOwnProperty(key)) continue;
210
+ if (!Object.hasOwn(obj, key)) continue;
211
211
  if (typeof obj[key] === "function") {
212
212
  clone[key] = obj[key];
213
213
  continue;
@@ -216,6 +216,30 @@ function deepClone(obj) {
216
216
  }
217
217
  return clone;
218
218
  }
219
+ function createCompressedStream(body, encoding) {
220
+ const compressStream = encoding === "br" ? zlib.createBrotliCompress() : encoding === "gzip" ? zlib.createGzip() : zlib.createDeflate();
221
+ return new ReadableStream({
222
+ async start(controller) {
223
+ try {
224
+ const compressed = await new Promise((resolve, reject) => {
225
+ const chunks = [];
226
+ compressStream.on("data", (chunk) => chunks.push(chunk));
227
+ compressStream.on("end", () => resolve(Buffer.concat(chunks)));
228
+ compressStream.on("error", reject);
229
+ compressStream.write(Buffer.from(body));
230
+ compressStream.end();
231
+ });
232
+ const chunkSize = 16 * 1024;
233
+ for (let i = 0; i < compressed.length; i += chunkSize) {
234
+ controller.enqueue(compressed.subarray(i, i + chunkSize));
235
+ }
236
+ controller.close();
237
+ } catch (error) {
238
+ controller.error(error);
239
+ }
240
+ }
241
+ });
242
+ }
219
243
  var Http = class {
220
244
  type = "http";
221
245
  name = Name;
@@ -315,12 +339,14 @@ var Http = class {
315
339
  }
316
340
  } else if (Object.prototype.toString.call(data.response) === "[object Object]" && data.response.statusCode && data.response.headers)
317
341
  this.response = data.response;
342
+ else if (data.response instanceof ReadableStream)
343
+ this.response.body = data.response;
318
344
  else this.response.body = JSON.stringify({ data: data.response });
319
345
  if (!this.response.statusCode)
320
346
  this.response.statusCode = this.response.body ? 200 : 201;
321
347
  this.response.headers = Object.assign(
322
348
  {
323
- "content-type": "application/json; charset=utf-8",
349
+ "content-type": this.response.body instanceof ReadableStream ? "text/plain; charset=utf-8" : "application/json; charset=utf-8",
324
350
  "cache-control": "no-cache, no-store",
325
351
  "x-faasjs-request-id": data.context.request_id
326
352
  },
@@ -330,26 +356,22 @@ var Http = class {
330
356
  data.response = Object.assign({}, data.response, this.response);
331
357
  const originBody = data.response.body;
332
358
  data.response.originBody = originBody;
333
- if (originBody && !data.response.isBase64Encoded && typeof originBody !== "string")
359
+ if (data.response.body instanceof ReadableStream) {
360
+ data.response.isBase64Encoded = true;
361
+ return;
362
+ }
363
+ if (originBody && typeof originBody !== "string")
334
364
  data.response.body = JSON.stringify(originBody);
335
- if (!data.response.body || data.response.isBase64Encoded || typeof data.response.body !== "string" || data.response.body.length < 1024)
365
+ if (!data.response.body || typeof data.response.body !== "string" || data.response.body.length < 1024)
336
366
  return;
337
367
  const acceptEncoding = this.headers["accept-encoding"] || this.headers["Accept-Encoding"];
338
368
  if (!acceptEncoding || !/(br|gzip|deflate)/.test(acceptEncoding)) return;
339
369
  try {
340
- if (acceptEncoding.includes("br")) {
341
- data.response.headers["Content-Encoding"] = "br";
342
- data.response.body = zlib.brotliCompressSync(originBody).toString("base64");
343
- } else if (acceptEncoding.includes("gzip")) {
344
- data.response.headers["Content-Encoding"] = "gzip";
345
- data.response.body = zlib.gzipSync(originBody).toString("base64");
346
- } else if (acceptEncoding.includes("deflate")) {
347
- data.response.headers["Content-Encoding"] = "deflate";
348
- data.response.body = zlib.deflateSync(originBody).toString("base64");
349
- } else throw Error("No matched compression.");
350
- data.response.isBase64Encoded = true;
370
+ const encoding = acceptEncoding.includes("br") ? "br" : acceptEncoding.includes("gzip") ? "gzip" : "deflate";
371
+ data.response.headers["Content-Encoding"] = encoding;
372
+ data.response.body = createCompressedStream(originBody, encoding);
351
373
  } catch (error) {
352
- console.error(error);
374
+ data.logger.error("Compression failed: %s", error.message);
353
375
  data.response.body = originBody;
354
376
  delete data.response.headers["Content-Encoding"];
355
377
  }
package/dist/index.d.ts CHANGED
@@ -103,7 +103,7 @@ type Response = {
103
103
  headers?: {
104
104
  [key: string]: string;
105
105
  };
106
- body?: string;
106
+ body?: string | ReadableStream;
107
107
  message?: string;
108
108
  };
109
109
  declare class HttpError extends Error {
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { brotliCompressSync, gzipSync, deflateSync } from 'zlib';
1
+ import { createBrotliCompress, createGzip, createDeflate } from 'zlib';
2
2
  import { deepMerge } from '@faasjs/deep_merge';
3
3
  import { usePlugin, useFunc } from '@faasjs/func';
4
4
  import { randomBytes, pbkdf2Sync, createCipheriv, createHmac, createDecipheriv } from 'crypto';
@@ -205,7 +205,7 @@ function deepClone(obj) {
205
205
  if (Array.isArray(obj)) return JSON.parse(JSON.stringify(obj));
206
206
  const clone = {};
207
207
  for (const key in obj) {
208
- if (!obj.hasOwnProperty(key)) continue;
208
+ if (!Object.hasOwn(obj, key)) continue;
209
209
  if (typeof obj[key] === "function") {
210
210
  clone[key] = obj[key];
211
211
  continue;
@@ -214,6 +214,30 @@ function deepClone(obj) {
214
214
  }
215
215
  return clone;
216
216
  }
217
+ function createCompressedStream(body, encoding) {
218
+ const compressStream = encoding === "br" ? createBrotliCompress() : encoding === "gzip" ? createGzip() : createDeflate();
219
+ return new ReadableStream({
220
+ async start(controller) {
221
+ try {
222
+ const compressed = await new Promise((resolve, reject) => {
223
+ const chunks = [];
224
+ compressStream.on("data", (chunk) => chunks.push(chunk));
225
+ compressStream.on("end", () => resolve(Buffer.concat(chunks)));
226
+ compressStream.on("error", reject);
227
+ compressStream.write(Buffer.from(body));
228
+ compressStream.end();
229
+ });
230
+ const chunkSize = 16 * 1024;
231
+ for (let i = 0; i < compressed.length; i += chunkSize) {
232
+ controller.enqueue(compressed.subarray(i, i + chunkSize));
233
+ }
234
+ controller.close();
235
+ } catch (error) {
236
+ controller.error(error);
237
+ }
238
+ }
239
+ });
240
+ }
217
241
  var Http = class {
218
242
  type = "http";
219
243
  name = Name;
@@ -313,12 +337,14 @@ var Http = class {
313
337
  }
314
338
  } else if (Object.prototype.toString.call(data.response) === "[object Object]" && data.response.statusCode && data.response.headers)
315
339
  this.response = data.response;
340
+ else if (data.response instanceof ReadableStream)
341
+ this.response.body = data.response;
316
342
  else this.response.body = JSON.stringify({ data: data.response });
317
343
  if (!this.response.statusCode)
318
344
  this.response.statusCode = this.response.body ? 200 : 201;
319
345
  this.response.headers = Object.assign(
320
346
  {
321
- "content-type": "application/json; charset=utf-8",
347
+ "content-type": this.response.body instanceof ReadableStream ? "text/plain; charset=utf-8" : "application/json; charset=utf-8",
322
348
  "cache-control": "no-cache, no-store",
323
349
  "x-faasjs-request-id": data.context.request_id
324
350
  },
@@ -328,26 +354,22 @@ var Http = class {
328
354
  data.response = Object.assign({}, data.response, this.response);
329
355
  const originBody = data.response.body;
330
356
  data.response.originBody = originBody;
331
- if (originBody && !data.response.isBase64Encoded && typeof originBody !== "string")
357
+ if (data.response.body instanceof ReadableStream) {
358
+ data.response.isBase64Encoded = true;
359
+ return;
360
+ }
361
+ if (originBody && typeof originBody !== "string")
332
362
  data.response.body = JSON.stringify(originBody);
333
- if (!data.response.body || data.response.isBase64Encoded || typeof data.response.body !== "string" || data.response.body.length < 1024)
363
+ if (!data.response.body || typeof data.response.body !== "string" || data.response.body.length < 1024)
334
364
  return;
335
365
  const acceptEncoding = this.headers["accept-encoding"] || this.headers["Accept-Encoding"];
336
366
  if (!acceptEncoding || !/(br|gzip|deflate)/.test(acceptEncoding)) return;
337
367
  try {
338
- if (acceptEncoding.includes("br")) {
339
- data.response.headers["Content-Encoding"] = "br";
340
- data.response.body = brotliCompressSync(originBody).toString("base64");
341
- } else if (acceptEncoding.includes("gzip")) {
342
- data.response.headers["Content-Encoding"] = "gzip";
343
- data.response.body = gzipSync(originBody).toString("base64");
344
- } else if (acceptEncoding.includes("deflate")) {
345
- data.response.headers["Content-Encoding"] = "deflate";
346
- data.response.body = deflateSync(originBody).toString("base64");
347
- } else throw Error("No matched compression.");
348
- data.response.isBase64Encoded = true;
368
+ const encoding = acceptEncoding.includes("br") ? "br" : acceptEncoding.includes("gzip") ? "gzip" : "deflate";
369
+ data.response.headers["Content-Encoding"] = encoding;
370
+ data.response.body = createCompressedStream(originBody, encoding);
349
371
  } catch (error) {
350
- console.error(error);
372
+ data.logger.error("Compression failed: %s", error.message);
351
373
  data.response.body = originBody;
352
374
  delete data.response.headers["Content-Encoding"];
353
375
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faasjs/http",
3
- "version": "7.1.0",
3
+ "version": "v8.0.0-beta.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -30,12 +30,12 @@
30
30
  "dist"
31
31
  ],
32
32
  "peerDependencies": {
33
- "@faasjs/func": ">=7.1.0",
34
- "@faasjs/logger": ">=7.1.0"
33
+ "@faasjs/func": ">=v8.0.0-beta.1",
34
+ "@faasjs/logger": ">=v8.0.0-beta.1"
35
35
  },
36
36
  "devDependencies": {
37
- "@faasjs/func": ">=7.1.0",
38
- "@faasjs/logger": ">=7.1.0"
37
+ "@faasjs/func": ">=v8.0.0-beta.1",
38
+ "@faasjs/logger": ">=v8.0.0-beta.1"
39
39
  },
40
40
  "engines": {
41
41
  "node": ">=24.0.0",