@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 +11 -0
- package/dist/index.cjs +38 -16
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +39 -17
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @faasjs/http
|
|
2
2
|
|
|
3
|
+
FaasJS's http plugin.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/faasjs/faasjs/blob/main/packages/http/LICENSE)
|
|
6
|
+
[](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 (!
|
|
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 (
|
|
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 ||
|
|
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
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
-
|
|
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
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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 (!
|
|
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 (
|
|
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 ||
|
|
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
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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
|
-
|
|
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": "
|
|
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": ">=
|
|
34
|
-
"@faasjs/logger": ">=
|
|
33
|
+
"@faasjs/func": ">=v8.0.0-beta.1",
|
|
34
|
+
"@faasjs/logger": ">=v8.0.0-beta.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@faasjs/func": ">=
|
|
38
|
-
"@faasjs/logger": ">=
|
|
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",
|