@faasjs/http 8.0.0-beta.6 → 8.0.0-beta.7
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 +0 -1
- package/dist/index.cjs +364 -426
- package/dist/index.d.ts +149 -153
- package/dist/index.mjs +363 -424
- package/package.json +8 -6
package/dist/index.cjs
CHANGED
|
@@ -1,451 +1,389 @@
|
|
|
1
|
-
'
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
let node_zlib = require("node:zlib");
|
|
3
|
+
let _faasjs_func = require("@faasjs/func");
|
|
4
|
+
let _faasjs_node_utils = require("@faasjs/node-utils");
|
|
5
|
+
let node_crypto = require("node:crypto");
|
|
2
6
|
|
|
3
|
-
|
|
4
|
-
var deep_merge = require('@faasjs/deep_merge');
|
|
5
|
-
var func = require('@faasjs/func');
|
|
6
|
-
var crypto = require('crypto');
|
|
7
|
-
|
|
8
|
-
// src/index.ts
|
|
7
|
+
//#region src/session.ts
|
|
9
8
|
var Session = class {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
hmac.update(signedParts[0]);
|
|
78
|
-
const digest = hmac.digest("hex");
|
|
79
|
-
if (signedParts[1] !== digest) throw Error("Session Not valid");
|
|
80
|
-
const message = Buffer.from(signedParts[0], "base64").toString();
|
|
81
|
-
const parts = message.split("--").map((part2) => Buffer.from(part2, "base64"));
|
|
82
|
-
const cipher = crypto.createDecipheriv(
|
|
83
|
-
this.config.cipherName,
|
|
84
|
-
this.secret,
|
|
85
|
-
parts[1]
|
|
86
|
-
);
|
|
87
|
-
const part = Buffer.from(cipher.update(parts[0])).toString("utf8");
|
|
88
|
-
const final = cipher.final("utf8");
|
|
89
|
-
const decrypt = [part, final].join("");
|
|
90
|
-
return JSON.parse(decrypt);
|
|
91
|
-
}
|
|
92
|
-
read(key) {
|
|
93
|
-
return this.content[key];
|
|
94
|
-
}
|
|
95
|
-
write(key, value) {
|
|
96
|
-
if (value === null || typeof value === "undefined") delete this.content[key];
|
|
97
|
-
else this.content[key] = value;
|
|
98
|
-
this.changed = true;
|
|
99
|
-
return this;
|
|
100
|
-
}
|
|
101
|
-
update() {
|
|
102
|
-
if (this.changed)
|
|
103
|
-
this.cookie.write(
|
|
104
|
-
this.config.key,
|
|
105
|
-
this.encode(JSON.stringify(this.content))
|
|
106
|
-
);
|
|
107
|
-
return this;
|
|
108
|
-
}
|
|
9
|
+
content;
|
|
10
|
+
config;
|
|
11
|
+
secret;
|
|
12
|
+
signedSecret;
|
|
13
|
+
cookie;
|
|
14
|
+
changed;
|
|
15
|
+
constructor(cookie, config) {
|
|
16
|
+
this.cookie = cookie;
|
|
17
|
+
if (!config?.secret) cookie.logger?.warn("Session's secret is missing.");
|
|
18
|
+
this.config = Object.assign({
|
|
19
|
+
key: "key",
|
|
20
|
+
secret: (0, node_crypto.randomBytes)(128).toString("hex"),
|
|
21
|
+
salt: "salt",
|
|
22
|
+
signedSalt: "signedSalt",
|
|
23
|
+
keylen: 64,
|
|
24
|
+
iterations: 100,
|
|
25
|
+
digest: "sha256",
|
|
26
|
+
cipherName: "aes-256-cbc"
|
|
27
|
+
}, config);
|
|
28
|
+
this.secret = (0, node_crypto.pbkdf2Sync)(this.config.secret, this.config.salt, this.config.iterations, this.config.keylen / 2, this.config.digest);
|
|
29
|
+
this.signedSecret = (0, node_crypto.pbkdf2Sync)(this.config.secret, this.config.signedSalt, this.config.iterations, this.config.keylen, this.config.digest);
|
|
30
|
+
this.content = Object.create(null);
|
|
31
|
+
}
|
|
32
|
+
invoke(cookie, logger) {
|
|
33
|
+
try {
|
|
34
|
+
this.content = cookie ? this.decode(cookie) : Object.create(null);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
logger?.error(error);
|
|
37
|
+
this.content = Object.create(null);
|
|
38
|
+
}
|
|
39
|
+
this.changed = false;
|
|
40
|
+
}
|
|
41
|
+
encode(text) {
|
|
42
|
+
if (typeof text !== "string") text = JSON.stringify(text);
|
|
43
|
+
const iv = (0, node_crypto.randomBytes)(16);
|
|
44
|
+
const cipher = (0, node_crypto.createCipheriv)(this.config.cipherName, this.secret, iv);
|
|
45
|
+
const encrypted = Buffer.concat([cipher.update(text), cipher.final()]).toString("base64");
|
|
46
|
+
const main = Buffer.from([encrypted, iv.toString("base64")].join("--")).toString("base64");
|
|
47
|
+
const hmac = (0, node_crypto.createHmac)(this.config.digest, this.signedSecret);
|
|
48
|
+
hmac.update(main);
|
|
49
|
+
return `${main}--${hmac.digest("hex")}`;
|
|
50
|
+
}
|
|
51
|
+
decode(text) {
|
|
52
|
+
text = decodeURIComponent(text);
|
|
53
|
+
const signedParts = text.split("--");
|
|
54
|
+
const hmac = (0, node_crypto.createHmac)(this.config.digest, this.signedSecret);
|
|
55
|
+
hmac.update(signedParts[0]);
|
|
56
|
+
const digest = hmac.digest("hex");
|
|
57
|
+
if (signedParts[1] !== digest) throw Error("Session Not valid");
|
|
58
|
+
const parts = Buffer.from(signedParts[0], "base64").toString().split("--").map((part) => Buffer.from(part, "base64"));
|
|
59
|
+
const cipher = (0, node_crypto.createDecipheriv)(this.config.cipherName, this.secret, parts[1]);
|
|
60
|
+
const decrypt = [Buffer.from(cipher.update(parts[0])).toString("utf8"), cipher.final("utf8")].join("");
|
|
61
|
+
return JSON.parse(decrypt);
|
|
62
|
+
}
|
|
63
|
+
read(key) {
|
|
64
|
+
return this.content[key];
|
|
65
|
+
}
|
|
66
|
+
write(key, value) {
|
|
67
|
+
if (value === null || typeof value === "undefined") delete this.content[key];
|
|
68
|
+
else this.content[key] = value;
|
|
69
|
+
this.changed = true;
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
update() {
|
|
73
|
+
if (this.changed) this.cookie.write(this.config.key, this.encode(JSON.stringify(this.content)));
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
109
76
|
};
|
|
110
77
|
|
|
111
|
-
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/cookie.ts
|
|
112
80
|
var Cookie = class {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (opts.sameSite) cookie += `SameSite=${opts.sameSite};`;
|
|
171
|
-
this.setCookie[key] = cookie;
|
|
172
|
-
return this;
|
|
173
|
-
}
|
|
174
|
-
headers() {
|
|
175
|
-
if (Object.keys(this.setCookie).length === 0) return {};
|
|
176
|
-
return { "Set-Cookie": Object.values(this.setCookie) };
|
|
177
|
-
}
|
|
81
|
+
session;
|
|
82
|
+
content;
|
|
83
|
+
config;
|
|
84
|
+
logger;
|
|
85
|
+
setCookie;
|
|
86
|
+
constructor(config, logger) {
|
|
87
|
+
this.logger = logger;
|
|
88
|
+
this.config = (0, _faasjs_node_utils.deepMerge)({
|
|
89
|
+
path: "/",
|
|
90
|
+
expires: 31536e3,
|
|
91
|
+
secure: true,
|
|
92
|
+
httpOnly: true,
|
|
93
|
+
session: {}
|
|
94
|
+
}, config);
|
|
95
|
+
this.session = new Session(this, this.config.session);
|
|
96
|
+
this.content = Object.create(null);
|
|
97
|
+
this.setCookie = Object.create(null);
|
|
98
|
+
}
|
|
99
|
+
invoke(cookie, logger) {
|
|
100
|
+
this.content = Object.create(null);
|
|
101
|
+
if (cookie) for (const x of cookie.split(";")) {
|
|
102
|
+
const trimX = x.trim();
|
|
103
|
+
const k = /([^=]+)/.exec(trimX);
|
|
104
|
+
if (k !== null) this.content[k[0]] = decodeURIComponent(trimX.replace(`${k[0]}=`, "").replace(/;$/, ""));
|
|
105
|
+
}
|
|
106
|
+
this.setCookie = Object.create(null);
|
|
107
|
+
this.session.invoke(this.read(this.session.config.key), logger);
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
read(key) {
|
|
111
|
+
return this.content[key];
|
|
112
|
+
}
|
|
113
|
+
write(key, value, opts) {
|
|
114
|
+
opts = Object.assign(this.config, opts || {});
|
|
115
|
+
let cookie;
|
|
116
|
+
if (value === null || typeof value === "undefined") {
|
|
117
|
+
opts.expires = "Thu, 01 Jan 1970 00:00:01 GMT";
|
|
118
|
+
cookie = `${key}=;`;
|
|
119
|
+
delete this.content[key];
|
|
120
|
+
} else {
|
|
121
|
+
cookie = `${key}=${encodeURIComponent(value)};`;
|
|
122
|
+
this.content[key] = value;
|
|
123
|
+
}
|
|
124
|
+
if (typeof opts.expires === "number") cookie += `max-age=${opts.expires};`;
|
|
125
|
+
else if (typeof opts.expires === "string") cookie += `expires=${opts.expires};`;
|
|
126
|
+
cookie += `path=${opts.path || "/"};`;
|
|
127
|
+
if (opts.domain) cookie += `domain=${opts.domain};`;
|
|
128
|
+
if (opts.secure) cookie += "Secure;";
|
|
129
|
+
if (opts.httpOnly) cookie += "HttpOnly;";
|
|
130
|
+
if (opts.sameSite) cookie += `SameSite=${opts.sameSite};`;
|
|
131
|
+
this.setCookie[key] = cookie;
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
headers() {
|
|
135
|
+
if (Object.keys(this.setCookie).length === 0) return {};
|
|
136
|
+
return { "Set-Cookie": Object.values(this.setCookie) };
|
|
137
|
+
}
|
|
178
138
|
};
|
|
179
139
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/index.ts
|
|
142
|
+
/**
|
|
143
|
+
* FaasJS's http plugin.
|
|
144
|
+
*
|
|
145
|
+
* [](https://github.com/faasjs/faasjs/blob/main/packages/http/LICENSE)
|
|
146
|
+
* [](https://www.npmjs.com/package/@faasjs/http)
|
|
147
|
+
*
|
|
148
|
+
* ## Install
|
|
149
|
+
*
|
|
150
|
+
* ```sh
|
|
151
|
+
* npm install @faasjs/http
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @packageDocumentation
|
|
155
|
+
*/
|
|
156
|
+
const ContentType = {
|
|
157
|
+
plain: "text/plain",
|
|
158
|
+
html: "text/html",
|
|
159
|
+
xml: "application/xml",
|
|
160
|
+
csv: "text/csv",
|
|
161
|
+
css: "text/css",
|
|
162
|
+
javascript: "application/javascript",
|
|
163
|
+
json: "application/json",
|
|
164
|
+
jsonp: "application/javascript"
|
|
190
165
|
};
|
|
191
|
-
var HttpError = class
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
this.statusCode = statusCode || 500;
|
|
201
|
-
this.message = message;
|
|
202
|
-
}
|
|
166
|
+
var HttpError = class HttpError extends Error {
|
|
167
|
+
statusCode;
|
|
168
|
+
message;
|
|
169
|
+
constructor({ statusCode, message }) {
|
|
170
|
+
super(message);
|
|
171
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, HttpError);
|
|
172
|
+
this.statusCode = statusCode || 500;
|
|
173
|
+
this.message = message;
|
|
174
|
+
}
|
|
203
175
|
};
|
|
204
|
-
|
|
176
|
+
const Name = "http";
|
|
205
177
|
function stringToStream(text) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
});
|
|
178
|
+
return new ReadableStream({ start(controller) {
|
|
179
|
+
try {
|
|
180
|
+
const encoder = new TextEncoder();
|
|
181
|
+
controller.enqueue(encoder.encode(text));
|
|
182
|
+
controller.close();
|
|
183
|
+
} catch (error) {
|
|
184
|
+
controller.error(error);
|
|
185
|
+
}
|
|
186
|
+
} });
|
|
217
187
|
}
|
|
218
188
|
function deepClone(obj) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
189
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
190
|
+
if (Array.isArray(obj)) return JSON.parse(JSON.stringify(obj));
|
|
191
|
+
const clone = {};
|
|
192
|
+
for (const key in obj) {
|
|
193
|
+
if (!Object.hasOwn(obj, key)) continue;
|
|
194
|
+
if (typeof obj[key] === "function") {
|
|
195
|
+
clone[key] = obj[key];
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
clone[key] = deepClone(obj[key]);
|
|
199
|
+
}
|
|
200
|
+
return clone;
|
|
231
201
|
}
|
|
232
202
|
function createCompressedStream(body, encoding) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
controller.error(error);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
});
|
|
203
|
+
const compressStream = encoding === "br" ? (0, node_zlib.createBrotliCompress)() : encoding === "gzip" ? (0, node_zlib.createGzip)() : (0, node_zlib.createDeflate)();
|
|
204
|
+
return new ReadableStream({ async start(controller) {
|
|
205
|
+
try {
|
|
206
|
+
const compressed = await new Promise((resolve, reject) => {
|
|
207
|
+
const chunks = [];
|
|
208
|
+
compressStream.on("data", (chunk) => chunks.push(chunk));
|
|
209
|
+
compressStream.on("end", () => resolve(Buffer.concat(chunks)));
|
|
210
|
+
compressStream.on("error", reject);
|
|
211
|
+
compressStream.write(Buffer.from(body));
|
|
212
|
+
compressStream.end();
|
|
213
|
+
});
|
|
214
|
+
const chunkSize = 16 * 1024;
|
|
215
|
+
for (let i = 0; i < compressed.length; i += chunkSize) controller.enqueue(compressed.subarray(i, i + chunkSize));
|
|
216
|
+
controller.close();
|
|
217
|
+
} catch (error) {
|
|
218
|
+
controller.error(error);
|
|
219
|
+
}
|
|
220
|
+
} });
|
|
255
221
|
}
|
|
256
222
|
var Http = class {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
return this;
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* set Content-Type
|
|
416
|
-
* @param type {string} 类型
|
|
417
|
-
* @param charset {string} 编码
|
|
418
|
-
*/
|
|
419
|
-
setContentType(type, charset = "utf-8") {
|
|
420
|
-
if (ContentType[type])
|
|
421
|
-
this.setHeader("Content-Type", `${ContentType[type]}; charset=${charset}`);
|
|
422
|
-
else this.setHeader("Content-Type", `${type}; charset=${charset}`);
|
|
423
|
-
return this;
|
|
424
|
-
}
|
|
425
|
-
/**
|
|
426
|
-
* set status code
|
|
427
|
-
* @param code {number} 状态码
|
|
428
|
-
*/
|
|
429
|
-
setStatusCode(code) {
|
|
430
|
-
this.response.statusCode = code;
|
|
431
|
-
return this;
|
|
432
|
-
}
|
|
433
|
-
/**
|
|
434
|
-
* set body
|
|
435
|
-
* @param body {*} 内容
|
|
436
|
-
*/
|
|
437
|
-
setBody(body) {
|
|
438
|
-
this.response.body = body;
|
|
439
|
-
return this;
|
|
440
|
-
}
|
|
223
|
+
type = "http";
|
|
224
|
+
name = Name;
|
|
225
|
+
headers = Object.create(null);
|
|
226
|
+
body;
|
|
227
|
+
params = Object.create(null);
|
|
228
|
+
cookie;
|
|
229
|
+
session;
|
|
230
|
+
config;
|
|
231
|
+
response;
|
|
232
|
+
constructor(config) {
|
|
233
|
+
this.name = config?.name || this.type;
|
|
234
|
+
this.config = config?.config || Object.create(null);
|
|
235
|
+
this.cookie = new Cookie(this.config.cookie || {});
|
|
236
|
+
this.session = this.cookie.session;
|
|
237
|
+
this.response = { headers: Object.create(null) };
|
|
238
|
+
}
|
|
239
|
+
async onMount(data, next) {
|
|
240
|
+
data.logger.debug("merge config");
|
|
241
|
+
const prefix = `SECRET_${this.name.toUpperCase()}_`;
|
|
242
|
+
for (let key in process.env) if (key.startsWith(prefix)) {
|
|
243
|
+
const value = process.env[key];
|
|
244
|
+
key = key.replace(prefix, "").toLowerCase();
|
|
245
|
+
if (key.includes("_")) {
|
|
246
|
+
let config = this.config;
|
|
247
|
+
const keys = key.split("_");
|
|
248
|
+
for (const k of keys.slice(0, keys.length - 1)) {
|
|
249
|
+
if (!config[k]) config[k] = Object.create(null);
|
|
250
|
+
config = config[k];
|
|
251
|
+
}
|
|
252
|
+
config[keys[keys.length - 1]] = value;
|
|
253
|
+
} else this.config[key] = value;
|
|
254
|
+
}
|
|
255
|
+
if (!data.config) throw Error(`[${this.name}] Config not found.`);
|
|
256
|
+
if (data.config.plugins?.[this.name || this.type]) this.config = (0, _faasjs_node_utils.deepMerge)(this.config, data.config.plugins[this.name || this.type].config);
|
|
257
|
+
data.logger.debug("prepare cookie & session");
|
|
258
|
+
this.cookie = new Cookie(this.config.cookie || {}, data.logger);
|
|
259
|
+
this.session = this.cookie.session;
|
|
260
|
+
await next();
|
|
261
|
+
}
|
|
262
|
+
async onInvoke(data, next) {
|
|
263
|
+
this.headers = data.event.headers || Object.create(null);
|
|
264
|
+
this.body = data.event.body;
|
|
265
|
+
this.params = data.event.queryString || Object.create(null);
|
|
266
|
+
this.response = { headers: Object.create(null) };
|
|
267
|
+
if (data.event.body) {
|
|
268
|
+
if (this.headers["content-type"]?.includes("application/json") && typeof data.event.body === "string" && data.event.body.length > 1) {
|
|
269
|
+
data.logger.debug("Parse params from json body");
|
|
270
|
+
try {
|
|
271
|
+
this.params = Object.keys(this.params).length ? Object.assign(this.params, JSON.parse(data.event.body)) : JSON.parse(data.event.body);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
data.logger.error("Parse params from json body failed: %s", error.message);
|
|
274
|
+
}
|
|
275
|
+
} else {
|
|
276
|
+
data.logger.debug("Parse params from raw body");
|
|
277
|
+
this.params = data.event.body || Object.create(null);
|
|
278
|
+
}
|
|
279
|
+
if (this.params && typeof this.params === "object" && this.params._) delete this.params._;
|
|
280
|
+
data.event.params = deepClone(this.params);
|
|
281
|
+
data.logger.debug("Params: %j", this.params);
|
|
282
|
+
}
|
|
283
|
+
data.params = data.event.params;
|
|
284
|
+
this.cookie.invoke(this.headers.cookie, data.logger);
|
|
285
|
+
if (this.headers.cookie) {
|
|
286
|
+
data.logger.debug("Cookie: %j", this.cookie.content);
|
|
287
|
+
data.logger.debug("Session: %s %j", this.session.config.key, this.session.content);
|
|
288
|
+
}
|
|
289
|
+
data.cookie = this.cookie;
|
|
290
|
+
data.session = this.session;
|
|
291
|
+
try {
|
|
292
|
+
await next();
|
|
293
|
+
} catch (error) {
|
|
294
|
+
data.response = error;
|
|
295
|
+
}
|
|
296
|
+
this.session.update();
|
|
297
|
+
if (this.response.body && !data.response) data.response = this.response.body;
|
|
298
|
+
if (data.response) if (data.response instanceof Error || data.response.constructor?.name === "Error") {
|
|
299
|
+
data.logger.error(data.response);
|
|
300
|
+
this.response.body = JSON.stringify({ error: { message: data.response.message } });
|
|
301
|
+
try {
|
|
302
|
+
this.response.statusCode = data.response.statusCode || 500;
|
|
303
|
+
} catch (e) {
|
|
304
|
+
data.logger.error(e);
|
|
305
|
+
this.response.statusCode = 500;
|
|
306
|
+
}
|
|
307
|
+
} else if (Object.prototype.toString.call(data.response) === "[object Object]" && data.response.statusCode && data.response.headers) this.response = data.response;
|
|
308
|
+
else if (data.response instanceof ReadableStream) this.response.body = data.response;
|
|
309
|
+
else this.response.body = JSON.stringify({ data: data.response === void 0 ? null : data.response });
|
|
310
|
+
if (!this.response.statusCode) this.response.statusCode = data.response ? 200 : 204;
|
|
311
|
+
this.response.headers = Object.assign({
|
|
312
|
+
"content-type": this.response.body instanceof ReadableStream ? "text/plain; charset=utf-8" : "application/json; charset=utf-8",
|
|
313
|
+
"cache-control": "no-cache, no-store",
|
|
314
|
+
"x-faasjs-request-id": data.context.request_id
|
|
315
|
+
}, this.cookie.headers(), this.response.headers);
|
|
316
|
+
data.response = Object.assign({}, data.response, this.response);
|
|
317
|
+
const originBody = data.response.body;
|
|
318
|
+
data.response.originBody = originBody;
|
|
319
|
+
if (data.response.body instanceof ReadableStream) {
|
|
320
|
+
data.response.isBase64Encoded = true;
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (originBody === void 0 && data.response.statusCode === 204) return;
|
|
324
|
+
if (originBody && typeof originBody !== "string") data.response.body = JSON.stringify(originBody);
|
|
325
|
+
else if (originBody === void 0) data.response.body = JSON.stringify({ data: null });
|
|
326
|
+
if (!data.response.body || typeof data.response.body !== "string" || data.response.body.length < 1024) {
|
|
327
|
+
data.response.body = stringToStream(data.response.body);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const acceptEncoding = this.headers["accept-encoding"] || this.headers["Accept-Encoding"];
|
|
331
|
+
if (!acceptEncoding || !/(br|gzip|deflate)/.test(acceptEncoding)) return;
|
|
332
|
+
try {
|
|
333
|
+
const encoding = acceptEncoding.includes("br") ? "br" : acceptEncoding.includes("gzip") ? "gzip" : "deflate";
|
|
334
|
+
data.response.headers["Content-Encoding"] = encoding;
|
|
335
|
+
data.response.body = createCompressedStream(originBody, encoding);
|
|
336
|
+
} catch (error) {
|
|
337
|
+
data.logger.error("Compression failed: %s", error.message);
|
|
338
|
+
data.response.body = originBody;
|
|
339
|
+
delete data.response.headers["Content-Encoding"];
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* set header
|
|
344
|
+
* @param key {string} key
|
|
345
|
+
* @param value {string} value
|
|
346
|
+
*/
|
|
347
|
+
setHeader(key, value) {
|
|
348
|
+
const headers = this.response.headers || (this.response.headers = Object.create(null));
|
|
349
|
+
headers[key.toLowerCase()] = value;
|
|
350
|
+
return this;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* set Content-Type
|
|
354
|
+
* @param type {string} 类型
|
|
355
|
+
* @param charset {string} 编码
|
|
356
|
+
*/
|
|
357
|
+
setContentType(type, charset = "utf-8") {
|
|
358
|
+
if (ContentType[type]) this.setHeader("Content-Type", `${ContentType[type]}; charset=${charset}`);
|
|
359
|
+
else this.setHeader("Content-Type", `${type}; charset=${charset}`);
|
|
360
|
+
return this;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* set status code
|
|
364
|
+
* @param code {number} 状态码
|
|
365
|
+
*/
|
|
366
|
+
setStatusCode(code) {
|
|
367
|
+
this.response.statusCode = code;
|
|
368
|
+
return this;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* set body
|
|
372
|
+
* @param body {*} 内容
|
|
373
|
+
*/
|
|
374
|
+
setBody(body) {
|
|
375
|
+
this.response.body = body;
|
|
376
|
+
return this;
|
|
377
|
+
}
|
|
441
378
|
};
|
|
442
379
|
function useHttp(config) {
|
|
443
|
-
|
|
380
|
+
return (0, _faasjs_func.usePlugin)(new Http(config));
|
|
444
381
|
}
|
|
445
382
|
|
|
383
|
+
//#endregion
|
|
446
384
|
exports.ContentType = ContentType;
|
|
447
385
|
exports.Cookie = Cookie;
|
|
448
386
|
exports.Http = Http;
|
|
449
387
|
exports.HttpError = HttpError;
|
|
450
388
|
exports.Session = Session;
|
|
451
|
-
exports.useHttp = useHttp;
|
|
389
|
+
exports.useHttp = useHttp;
|