@faasjs/http 0.0.2-beta.302 → 0.0.2-beta.314
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/dist/index.d.ts +236 -0
- package/dist/index.js +513 -0
- package/dist/index.mjs +498 -0
- package/package.json +12 -13
- package/lib/cookie.d.ts +0 -39
- package/lib/index.d.ts +0 -105
- package/lib/index.es.js +0 -539
- package/lib/index.js +0 -549
- package/lib/session.d.ts +0 -38
- package/lib/validator.d.ts +0 -57
package/lib/index.js
DELETED
|
@@ -1,549 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var func = require('@faasjs/func');
|
|
6
|
-
var deep_merge = require('@faasjs/deep_merge');
|
|
7
|
-
var logger = require('@faasjs/logger');
|
|
8
|
-
var crypto = require('crypto');
|
|
9
|
-
var zlib = require('zlib');
|
|
10
|
-
|
|
11
|
-
class Session {
|
|
12
|
-
constructor(cookie, config) {
|
|
13
|
-
this.cookie = cookie;
|
|
14
|
-
this.config = Object.assign({
|
|
15
|
-
key: 'key',
|
|
16
|
-
secret: crypto.randomBytes(128).toString('hex'),
|
|
17
|
-
salt: 'salt',
|
|
18
|
-
signedSalt: 'signedSalt',
|
|
19
|
-
keylen: 64,
|
|
20
|
-
iterations: 100,
|
|
21
|
-
digest: 'sha256',
|
|
22
|
-
cipherName: 'aes-256-cbc'
|
|
23
|
-
}, config);
|
|
24
|
-
this.secret = crypto.pbkdf2Sync(this.config.secret, this.config.salt, this.config.iterations, this.config.keylen / 2, this.config.digest);
|
|
25
|
-
this.signedSecret = crypto.pbkdf2Sync(this.config.secret, this.config.signedSalt, this.config.iterations, this.config.keylen, this.config.digest);
|
|
26
|
-
this.content = Object.create(null);
|
|
27
|
-
}
|
|
28
|
-
invoke(cookie) {
|
|
29
|
-
try {
|
|
30
|
-
this.content = cookie ? this.decode(cookie) : Object.create(null);
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
console.error(error);
|
|
34
|
-
this.content = Object.create(null);
|
|
35
|
-
}
|
|
36
|
-
this.changed = false;
|
|
37
|
-
}
|
|
38
|
-
encode(text) {
|
|
39
|
-
if (typeof text !== 'string')
|
|
40
|
-
text = JSON.stringify(text);
|
|
41
|
-
const iv = crypto.randomBytes(16);
|
|
42
|
-
const cipher = crypto.createCipheriv(this.config.cipherName, this.secret, iv);
|
|
43
|
-
const encrypted = Buffer.concat([cipher.update(text), cipher.final()]).toString('base64');
|
|
44
|
-
const main = Buffer.from([encrypted, iv.toString('base64')].join('--')).toString('base64');
|
|
45
|
-
const hmac = crypto.createHmac(this.config.digest, this.signedSecret);
|
|
46
|
-
hmac.update(main);
|
|
47
|
-
const digest = hmac.digest('hex');
|
|
48
|
-
return main + '--' + digest;
|
|
49
|
-
}
|
|
50
|
-
decode(text) {
|
|
51
|
-
text = decodeURIComponent(text);
|
|
52
|
-
const signedParts = text.split('--');
|
|
53
|
-
const hmac = crypto.createHmac(this.config.digest, this.signedSecret);
|
|
54
|
-
hmac.update(signedParts[0]);
|
|
55
|
-
const digest = hmac.digest('hex');
|
|
56
|
-
if (signedParts[1] !== digest)
|
|
57
|
-
throw Error('Not valid');
|
|
58
|
-
const message = Buffer.from(signedParts[0], 'base64').toString();
|
|
59
|
-
const parts = message.split('--').map(function (part) {
|
|
60
|
-
return Buffer.from(part, 'base64');
|
|
61
|
-
});
|
|
62
|
-
const cipher = crypto.createDecipheriv(this.config.cipherName, this.secret, parts[1]);
|
|
63
|
-
const part = Buffer.from(cipher.update(parts[0])).toString('utf8');
|
|
64
|
-
const final = cipher.final('utf8');
|
|
65
|
-
const decrypt = [part, final].join('');
|
|
66
|
-
return JSON.parse(decrypt);
|
|
67
|
-
}
|
|
68
|
-
read(key) {
|
|
69
|
-
return this.content[key];
|
|
70
|
-
}
|
|
71
|
-
write(key, value) {
|
|
72
|
-
if (value === null || typeof value === 'undefined')
|
|
73
|
-
delete this.content[key];
|
|
74
|
-
else
|
|
75
|
-
this.content[key] = value;
|
|
76
|
-
this.changed = true;
|
|
77
|
-
return this;
|
|
78
|
-
}
|
|
79
|
-
update() {
|
|
80
|
-
if (this.changed)
|
|
81
|
-
this.cookie.write(this.config.key, this.encode(JSON.stringify(this.content)));
|
|
82
|
-
return this;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
class Cookie {
|
|
87
|
-
constructor(config) {
|
|
88
|
-
this.config = deep_merge.deepMerge({
|
|
89
|
-
path: '/',
|
|
90
|
-
expires: 31536000,
|
|
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) {
|
|
100
|
-
this.content = Object.create(null);
|
|
101
|
-
// 解析 cookie
|
|
102
|
-
if (cookie)
|
|
103
|
-
cookie.split(';').forEach(x => {
|
|
104
|
-
x = x.trim();
|
|
105
|
-
const k = /([^=]+)/.exec(x);
|
|
106
|
-
if (k !== null)
|
|
107
|
-
this.content[k[0]] = decodeURIComponent(x.replace(`${k[0]}=`, '').replace(/;$/, ''));
|
|
108
|
-
});
|
|
109
|
-
this.setCookie = Object.create(null);
|
|
110
|
-
// 预读取 session
|
|
111
|
-
this.session.invoke(this.read(this.session.config.key));
|
|
112
|
-
return this;
|
|
113
|
-
}
|
|
114
|
-
read(key) {
|
|
115
|
-
return this.content[key];
|
|
116
|
-
}
|
|
117
|
-
write(key, value, opts) {
|
|
118
|
-
opts = Object.assign(this.config, opts || {});
|
|
119
|
-
let cookie;
|
|
120
|
-
if (value === null || typeof value === 'undefined') {
|
|
121
|
-
opts.expires = 'Thu, 01 Jan 1970 00:00:01 GMT';
|
|
122
|
-
cookie = `${key}=;`;
|
|
123
|
-
delete this.content[key];
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
cookie = `${key}=${encodeURIComponent(value)};`;
|
|
127
|
-
this.content[key] = value;
|
|
128
|
-
}
|
|
129
|
-
if (typeof opts.expires === 'number')
|
|
130
|
-
cookie += `max-age=${opts.expires};`;
|
|
131
|
-
else if (typeof opts.expires === 'string')
|
|
132
|
-
cookie += `expires=${opts.expires};`;
|
|
133
|
-
cookie += `path=${opts.path || '/'};`;
|
|
134
|
-
if (opts.domain)
|
|
135
|
-
cookie += `domain=${opts.domain};`;
|
|
136
|
-
if (opts.secure)
|
|
137
|
-
cookie += 'Secure;';
|
|
138
|
-
if (opts.httpOnly)
|
|
139
|
-
cookie += 'HttpOnly;';
|
|
140
|
-
if (opts.sameSite)
|
|
141
|
-
cookie += `SameSite=${opts.sameSite};`;
|
|
142
|
-
this.setCookie[key] = cookie;
|
|
143
|
-
return this;
|
|
144
|
-
}
|
|
145
|
-
headers() {
|
|
146
|
-
if (Object.keys(this.setCookie).length === 0)
|
|
147
|
-
return {};
|
|
148
|
-
else
|
|
149
|
-
return { 'Set-Cookie': Object.values(this.setCookie) };
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
class Validator {
|
|
154
|
-
constructor(config, logger) {
|
|
155
|
-
this.paramsConfig = config.params;
|
|
156
|
-
this.cookieConfig = config.cookie;
|
|
157
|
-
this.sessionConfig = config.session;
|
|
158
|
-
this.before = config.before;
|
|
159
|
-
this.logger = logger;
|
|
160
|
-
}
|
|
161
|
-
async valid(request) {
|
|
162
|
-
if (this.before) {
|
|
163
|
-
const result = await this.before(request);
|
|
164
|
-
if (result)
|
|
165
|
-
throw new HttpError(result);
|
|
166
|
-
}
|
|
167
|
-
this.request = request;
|
|
168
|
-
if (this.paramsConfig && request.params) {
|
|
169
|
-
this.logger.debug('Valid Params');
|
|
170
|
-
this.validContent('params', request.params, '', this.paramsConfig);
|
|
171
|
-
}
|
|
172
|
-
if (this.cookieConfig && request.cookie) {
|
|
173
|
-
this.logger.debug('Valid Cookie');
|
|
174
|
-
if (request.cookie == null)
|
|
175
|
-
throw Error('Not found Cookie');
|
|
176
|
-
this.validContent('cookie', request.cookie.content, '', this.cookieConfig);
|
|
177
|
-
}
|
|
178
|
-
if (this.sessionConfig && request.session) {
|
|
179
|
-
this.logger.debug('Valid Session');
|
|
180
|
-
if (request.session == null)
|
|
181
|
-
throw Error('Not found Session');
|
|
182
|
-
this.validContent('session', request.session.content, '', this.sessionConfig);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
validContent(type, params, baseKey, config) {
|
|
186
|
-
if (config.whitelist) {
|
|
187
|
-
const paramsKeys = Object.keys(params);
|
|
188
|
-
const rulesKeys = Object.keys(config.rules);
|
|
189
|
-
const diff = paramsKeys.filter(k => !rulesKeys.includes(k));
|
|
190
|
-
if (diff.length > 0)
|
|
191
|
-
if (config.whitelist === 'error') {
|
|
192
|
-
const diffKeys = diff.map(k => `${baseKey}${k}`);
|
|
193
|
-
const error = Error(`[${type}] Not permitted keys: ${diffKeys.join(', ')}`);
|
|
194
|
-
if (config.onError) {
|
|
195
|
-
const res = config.onError(`${type}.whitelist`, baseKey, diffKeys);
|
|
196
|
-
if (res)
|
|
197
|
-
throw new HttpError(res);
|
|
198
|
-
}
|
|
199
|
-
throw error;
|
|
200
|
-
}
|
|
201
|
-
else if (config.whitelist === 'ignore')
|
|
202
|
-
for (const key of diff)
|
|
203
|
-
delete params[key];
|
|
204
|
-
}
|
|
205
|
-
for (const key in config.rules) {
|
|
206
|
-
const rule = config.rules[key];
|
|
207
|
-
if (!rule)
|
|
208
|
-
continue;
|
|
209
|
-
let value = params[key];
|
|
210
|
-
// default
|
|
211
|
-
if (rule.default)
|
|
212
|
-
if (type === 'cookie' || type === 'session')
|
|
213
|
-
this.logger.warn('Cookie and Session not support default rule.');
|
|
214
|
-
else if (typeof value === 'undefined' && rule.default) {
|
|
215
|
-
value = typeof rule.default === 'function' ? rule.default(this.request) : rule.default;
|
|
216
|
-
params[key] = value;
|
|
217
|
-
}
|
|
218
|
-
// required
|
|
219
|
-
if (rule.required)
|
|
220
|
-
if (typeof value === 'undefined' || value === null) {
|
|
221
|
-
const error = Error(`[${type}] ${baseKey}${key} is required.`);
|
|
222
|
-
if (config.onError) {
|
|
223
|
-
const res = config.onError(`${type}.rule.required`, `${baseKey}${key}`, value);
|
|
224
|
-
if (res)
|
|
225
|
-
throw new HttpError(res);
|
|
226
|
-
}
|
|
227
|
-
throw error;
|
|
228
|
-
}
|
|
229
|
-
if (typeof value !== 'undefined' && value !== null) {
|
|
230
|
-
// type
|
|
231
|
-
if (rule.type)
|
|
232
|
-
if (type === 'cookie')
|
|
233
|
-
this.logger.warn('Cookie not support type rule');
|
|
234
|
-
else {
|
|
235
|
-
let typed = true;
|
|
236
|
-
switch (rule.type) {
|
|
237
|
-
case 'array':
|
|
238
|
-
typed = Array.isArray(value);
|
|
239
|
-
break;
|
|
240
|
-
case 'object':
|
|
241
|
-
typed = Object.prototype.toString.call(value) === '[object Object]';
|
|
242
|
-
break;
|
|
243
|
-
default:
|
|
244
|
-
typed = typeof value === rule.type;
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
if (!typed) {
|
|
248
|
-
const error = Error(`[${type}] ${baseKey}${key} must be a ${rule.type}.`);
|
|
249
|
-
if (config.onError) {
|
|
250
|
-
const res = config.onError(`${type}.rule.type`, `${baseKey}${key}`, value);
|
|
251
|
-
if (res)
|
|
252
|
-
throw new HttpError(res);
|
|
253
|
-
}
|
|
254
|
-
throw error;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
// in
|
|
258
|
-
if ((rule.in) && !rule.in.includes(value)) {
|
|
259
|
-
const error = Error(`[${type}] ${baseKey}${key} must be in ${rule.in.join(', ')}.`);
|
|
260
|
-
if (config.onError) {
|
|
261
|
-
const res = config.onError(`${type}.rule.in`, `${baseKey}${key}`, value);
|
|
262
|
-
if (res)
|
|
263
|
-
throw new HttpError(res);
|
|
264
|
-
}
|
|
265
|
-
throw error;
|
|
266
|
-
}
|
|
267
|
-
// nest config
|
|
268
|
-
if (rule.config)
|
|
269
|
-
if (type === 'cookie')
|
|
270
|
-
this.logger.warn('Cookie not support nest rule.');
|
|
271
|
-
else if (Array.isArray(value))
|
|
272
|
-
// array
|
|
273
|
-
for (const val of value)
|
|
274
|
-
this.validContent(type, val, (baseKey ? `${baseKey}.${key}.` : `${key}.`), rule.config);
|
|
275
|
-
else if (typeof value === 'object')
|
|
276
|
-
// object
|
|
277
|
-
this.validContent(type, value, (baseKey ? `${baseKey}.${key}.` : `${key}.`), rule.config);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const ContentType = {
|
|
284
|
-
plain: 'text/plain',
|
|
285
|
-
html: 'text/html',
|
|
286
|
-
xml: 'application/xml',
|
|
287
|
-
csv: 'text/csv',
|
|
288
|
-
css: 'text/css',
|
|
289
|
-
javascript: 'application/javascript',
|
|
290
|
-
json: 'application/json',
|
|
291
|
-
jsonp: 'application/javascript'
|
|
292
|
-
};
|
|
293
|
-
class HttpError extends Error {
|
|
294
|
-
constructor({ statusCode, message }) {
|
|
295
|
-
super(message);
|
|
296
|
-
if (Error.captureStackTrace)
|
|
297
|
-
Error.captureStackTrace(this, HttpError);
|
|
298
|
-
this.statusCode = statusCode || 500;
|
|
299
|
-
this.message = message;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
const Name = 'http';
|
|
303
|
-
class Http {
|
|
304
|
-
/**
|
|
305
|
-
* 创建 Http 插件实例
|
|
306
|
-
* @param config {object} 配置项
|
|
307
|
-
* @param config.name {string} 配置名
|
|
308
|
-
* @param config.config {object} 网关配置
|
|
309
|
-
* @param config.config.method {string} 请求方法,默认为 POST
|
|
310
|
-
* @param config.config.path {string} 请求路径,默认为云函数文件路径
|
|
311
|
-
* @param config.config.ignorePathPrefix {string} 排除的路径前缀,当设置 path 时无效
|
|
312
|
-
* @param config.config.cookie {object} Cookie 配置
|
|
313
|
-
* @param config.validator {object} 入参校验配置
|
|
314
|
-
* @param config.validator.params {object} params 校验配置
|
|
315
|
-
* @param config.validator.params.whitelist {string} 白名单配置
|
|
316
|
-
* @param config.validator.params.onError {function} 自定义报错
|
|
317
|
-
* @param config.validator.params.rules {object} 参数校验规则
|
|
318
|
-
* @param config.validator.cookie {object} cookie 校验配置
|
|
319
|
-
* @param config.validator.cookie.whitelist {string} 白名单配置
|
|
320
|
-
* @param config.validator.cookie.onError {function} 自定义报错
|
|
321
|
-
* @param config.validator.cookie.rules {object} 参数校验规则
|
|
322
|
-
* @param config.validator.session {object} session 校验配置
|
|
323
|
-
* @param config.validator.session.whitelist {string} 白名单配置
|
|
324
|
-
* @param config.validator.session.onError {function} 自定义报错
|
|
325
|
-
* @param config.validator.session.rules {object} 参数校验规则
|
|
326
|
-
* @param config.validator.before {function} 参数校验前自定义函数
|
|
327
|
-
*/
|
|
328
|
-
constructor(config) {
|
|
329
|
-
this.type = Name;
|
|
330
|
-
this.name = Name;
|
|
331
|
-
this.name = (config === null || config === void 0 ? void 0 : config.name) || this.type;
|
|
332
|
-
this.config = ((config === null || config === void 0 ? void 0 : config.config)) || Object.create(null);
|
|
333
|
-
if ((config === null || config === void 0 ? void 0 : config.validator))
|
|
334
|
-
this.validatorOptions = config.validator;
|
|
335
|
-
this.logger = new logger.Logger(this.name);
|
|
336
|
-
this.headers = Object.create(null);
|
|
337
|
-
this.cookie = new Cookie(this.config.cookie || {});
|
|
338
|
-
this.session = this.cookie.session;
|
|
339
|
-
}
|
|
340
|
-
async onDeploy(data, next) {
|
|
341
|
-
var _a;
|
|
342
|
-
await next();
|
|
343
|
-
this.logger.debug('组装网关配置');
|
|
344
|
-
this.logger.debug('%j', data);
|
|
345
|
-
const config = data.config.plugins ?
|
|
346
|
-
deep_merge.deepMerge(data.config.plugins[this.name || this.type], { config: this.config }) :
|
|
347
|
-
{ config: this.config };
|
|
348
|
-
// 根据文件及文件夹名生成路径
|
|
349
|
-
if (!config.config.path) {
|
|
350
|
-
config.config.path = '/' + ((_a = data.name) === null || _a === void 0 ? void 0 : _a.replace(/_/g, '/').replace(/\/index$/, ''));
|
|
351
|
-
if (config.config.path === '/index')
|
|
352
|
-
config.config.path = '/';
|
|
353
|
-
if (config.config.ignorePathPrefix) {
|
|
354
|
-
config.config.path = config.config.path.replace(new RegExp('^' + config.config.ignorePathPrefix), '');
|
|
355
|
-
if (config.config.path === '')
|
|
356
|
-
config.config.path = '/';
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
this.logger.debug('组装完成 %j', config);
|
|
360
|
-
// 引用服务商部署插件
|
|
361
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
362
|
-
const Provider = require(config.provider.type).Provider;
|
|
363
|
-
const provider = new Provider(config.provider.config);
|
|
364
|
-
// 部署网关
|
|
365
|
-
await provider.deploy(this.type, data, config);
|
|
366
|
-
}
|
|
367
|
-
async onMount(data, next) {
|
|
368
|
-
this.logger.debug('[onMount] merge config');
|
|
369
|
-
if (data.config.plugins && data.config.plugins[this.name || this.type])
|
|
370
|
-
this.config = deep_merge.deepMerge(this.config, data.config.plugins[this.name || this.type].config);
|
|
371
|
-
this.logger.debug('[onMount] prepare cookie & session');
|
|
372
|
-
this.cookie = new Cookie(this.config.cookie || {});
|
|
373
|
-
this.session = this.cookie.session;
|
|
374
|
-
if (this.validatorOptions) {
|
|
375
|
-
this.logger.debug('[onMount] prepare validator');
|
|
376
|
-
this.validator = new Validator(this.validatorOptions, this.logger);
|
|
377
|
-
}
|
|
378
|
-
await next();
|
|
379
|
-
}
|
|
380
|
-
async onInvoke(data, next) {
|
|
381
|
-
var _a, _b;
|
|
382
|
-
this.headers = data.event.headers || Object.create(null);
|
|
383
|
-
this.body = data.event.body;
|
|
384
|
-
this.params = Object.create(null);
|
|
385
|
-
this.response = { headers: Object.create(null) };
|
|
386
|
-
if (data.event.body) {
|
|
387
|
-
if (data.event.headers && data.event.headers['content-type'] && data.event.headers['content-type'].includes('application/json')) {
|
|
388
|
-
this.logger.debug('[onInvoke] Parse params from json body');
|
|
389
|
-
this.params = JSON.parse(data.event.body);
|
|
390
|
-
}
|
|
391
|
-
else {
|
|
392
|
-
this.logger.debug('[onInvoke] Parse params from raw body');
|
|
393
|
-
this.params = data.event.body;
|
|
394
|
-
}
|
|
395
|
-
this.logger.debug('[onInvoke] Params: %j', this.params);
|
|
396
|
-
}
|
|
397
|
-
else if (data.event.queryString) {
|
|
398
|
-
this.logger.debug('[onInvoke] Parse params from queryString');
|
|
399
|
-
this.params = data.event.queryString;
|
|
400
|
-
this.logger.debug('[onInvoke] Params: %j', this.params);
|
|
401
|
-
}
|
|
402
|
-
this.cookie.invoke(this.headers.cookie);
|
|
403
|
-
if (this.headers.cookie) {
|
|
404
|
-
this.logger.debug('[onInvoke] Cookie: %j', this.cookie.content);
|
|
405
|
-
this.logger.debug('[onInvoke] Session: %j', this.session.content);
|
|
406
|
-
}
|
|
407
|
-
if (this.validator) {
|
|
408
|
-
this.logger.debug('[onInvoke] Valid request');
|
|
409
|
-
try {
|
|
410
|
-
await this.validator.valid({
|
|
411
|
-
headers: this.headers,
|
|
412
|
-
params: this.params,
|
|
413
|
-
cookie: this.cookie,
|
|
414
|
-
session: this.session
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
catch (error) {
|
|
418
|
-
this.logger.error(error);
|
|
419
|
-
data.response = {
|
|
420
|
-
statusCode: error.statusCode || 500,
|
|
421
|
-
headers: { 'Content-Type': 'application/json; charset=utf-8' },
|
|
422
|
-
body: JSON.stringify({ error: { message: error.message } })
|
|
423
|
-
};
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
try {
|
|
428
|
-
await next();
|
|
429
|
-
}
|
|
430
|
-
catch (error) {
|
|
431
|
-
data.response = error;
|
|
432
|
-
}
|
|
433
|
-
// update session
|
|
434
|
-
this.session.update();
|
|
435
|
-
// 处理 body
|
|
436
|
-
if (data.response)
|
|
437
|
-
if (data.response instanceof Error || ((_a = data.response.constructor) === null || _a === void 0 ? void 0 : _a.name) === 'Error') {
|
|
438
|
-
// 当结果是错误类型时
|
|
439
|
-
this.logger.error(data.response);
|
|
440
|
-
this.response.body = JSON.stringify({ error: { message: data.response.message } });
|
|
441
|
-
try {
|
|
442
|
-
this.response.statusCode = data.response.statusCode || 500;
|
|
443
|
-
}
|
|
444
|
-
catch (error) {
|
|
445
|
-
this.response.statusCode = 500;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
else if (Object.prototype.toString.call(data.response) === '[object Object]' && data.response.statusCode && data.response.headers)
|
|
449
|
-
// 当返回结果是响应结构体时
|
|
450
|
-
this.response = data.response;
|
|
451
|
-
else
|
|
452
|
-
this.response.body = JSON.stringify({ data: data.response });
|
|
453
|
-
// 处理 statusCode
|
|
454
|
-
if (!this.response.statusCode)
|
|
455
|
-
this.response.statusCode = this.response.body ? 200 : 201;
|
|
456
|
-
// 处理 headers
|
|
457
|
-
this.response.headers = Object.assign({
|
|
458
|
-
'Content-Type': 'application/json; charset=utf-8',
|
|
459
|
-
'Cache-Control': 'no-cache, no-store'
|
|
460
|
-
}, this.cookie.headers(), this.response.headers);
|
|
461
|
-
data.response = this.response;
|
|
462
|
-
if (process.env.FaasMode === 'local') {
|
|
463
|
-
this.logger.debug('[onInvoke] Response: %j', data.response);
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
466
|
-
// 判断是否需要压缩
|
|
467
|
-
if (data.response.isBase64Encoded ||
|
|
468
|
-
typeof data.response.body !== 'string' ||
|
|
469
|
-
!((_b = data.response.headers['Content-Type']) === null || _b === void 0 ? void 0 : _b.includes('json')) ||
|
|
470
|
-
data.response.body.length < 100)
|
|
471
|
-
return;
|
|
472
|
-
const acceptEncoding = this.headers['accept-encoding'] || this.headers['Accept-Encoding'];
|
|
473
|
-
if (!acceptEncoding || !/(br|gzip|deflate)/.test(acceptEncoding))
|
|
474
|
-
return;
|
|
475
|
-
const originBody = data.response.body;
|
|
476
|
-
try {
|
|
477
|
-
if (acceptEncoding.includes('br')) {
|
|
478
|
-
data.response.headers['Content-Encoding'] = 'br';
|
|
479
|
-
data.response.body = zlib.brotliCompressSync(originBody).toString('base64');
|
|
480
|
-
}
|
|
481
|
-
else if (acceptEncoding.includes('gzip')) {
|
|
482
|
-
data.response.headers['Content-Encoding'] = 'gzip';
|
|
483
|
-
data.response.body = zlib.gzipSync(originBody).toString('base64');
|
|
484
|
-
}
|
|
485
|
-
else if (acceptEncoding.includes('deflate')) {
|
|
486
|
-
data.response.headers['Content-Encoding'] = 'deflate';
|
|
487
|
-
data.response.body = zlib.deflateSync(originBody).toString('base64');
|
|
488
|
-
}
|
|
489
|
-
else
|
|
490
|
-
throw Error('No matched compression.');
|
|
491
|
-
data.response.isBase64Encoded = true;
|
|
492
|
-
data.response.originBody = originBody;
|
|
493
|
-
}
|
|
494
|
-
catch (error) {
|
|
495
|
-
console.error(error);
|
|
496
|
-
// 若压缩失败还原
|
|
497
|
-
data.response.body = originBody;
|
|
498
|
-
delete data.response.headers['Content-Encoding'];
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
/**
|
|
502
|
-
* 设置 header
|
|
503
|
-
* @param key {string} key
|
|
504
|
-
* @param value {*} value
|
|
505
|
-
*/
|
|
506
|
-
setHeader(key, value) {
|
|
507
|
-
this.response.headers[key] = value;
|
|
508
|
-
return this;
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* 设置 Content-Type
|
|
512
|
-
* @param type {string} 类型
|
|
513
|
-
* @param charset {string} 编码
|
|
514
|
-
*/
|
|
515
|
-
setContentType(type, charset = 'utf-8') {
|
|
516
|
-
if (ContentType[type])
|
|
517
|
-
this.setHeader('Content-Type', `${ContentType[type]}; charset=${charset}`);
|
|
518
|
-
else
|
|
519
|
-
this.setHeader('Content-Type', `${type}; charset=${charset}`);
|
|
520
|
-
return this;
|
|
521
|
-
}
|
|
522
|
-
/**
|
|
523
|
-
* 设置状态码
|
|
524
|
-
* @param code {number} 状态码
|
|
525
|
-
*/
|
|
526
|
-
setStatusCode(code) {
|
|
527
|
-
this.response.statusCode = code;
|
|
528
|
-
return this;
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* 设置 body
|
|
532
|
-
* @param body {*} 内容
|
|
533
|
-
*/
|
|
534
|
-
setBody(body) {
|
|
535
|
-
this.response.body = body;
|
|
536
|
-
return this;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
function useHttp(config) {
|
|
540
|
-
return func.usePlugin(new Http(config));
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
exports.ContentType = ContentType;
|
|
544
|
-
exports.Cookie = Cookie;
|
|
545
|
-
exports.Http = Http;
|
|
546
|
-
exports.HttpError = HttpError;
|
|
547
|
-
exports.Session = Session;
|
|
548
|
-
exports.Validator = Validator;
|
|
549
|
-
exports.useHttp = useHttp;
|
package/lib/session.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Cookie } from './cookie';
|
|
2
|
-
export declare type SessionOptions = {
|
|
3
|
-
key: string;
|
|
4
|
-
secret: string;
|
|
5
|
-
salt?: string;
|
|
6
|
-
signedSalt?: string;
|
|
7
|
-
keylen?: number;
|
|
8
|
-
iterations?: number;
|
|
9
|
-
digest?: string;
|
|
10
|
-
cipherName?: string;
|
|
11
|
-
};
|
|
12
|
-
export declare type SessionContent = string | number | {
|
|
13
|
-
[key: string]: any;
|
|
14
|
-
} | null | undefined;
|
|
15
|
-
export declare class Session<S extends Record<string, string> = any, C extends Record<string, string> = any> {
|
|
16
|
-
content: Record<string, string>;
|
|
17
|
-
readonly config: {
|
|
18
|
-
key: string;
|
|
19
|
-
secret: string;
|
|
20
|
-
salt: string;
|
|
21
|
-
signedSalt: string;
|
|
22
|
-
keylen: number;
|
|
23
|
-
iterations: number;
|
|
24
|
-
digest: string;
|
|
25
|
-
cipherName: string;
|
|
26
|
-
};
|
|
27
|
-
private readonly secret;
|
|
28
|
-
private readonly signedSecret;
|
|
29
|
-
private readonly cookie;
|
|
30
|
-
private changed?;
|
|
31
|
-
constructor(cookie: Cookie<C, S>, config: SessionOptions);
|
|
32
|
-
invoke(cookie?: string): void;
|
|
33
|
-
encode(text: SessionContent): string;
|
|
34
|
-
decode(text: string): SessionContent;
|
|
35
|
-
read(key: string): string;
|
|
36
|
-
write(key: string, value?: string): Session<S, C>;
|
|
37
|
-
update(): Session<S, C>;
|
|
38
|
-
}
|
package/lib/validator.d.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { Cookie } from './cookie';
|
|
2
|
-
import { Session } from './session';
|
|
3
|
-
import { Logger } from '@faasjs/logger';
|
|
4
|
-
export declare type ValidatorRuleOptions = {
|
|
5
|
-
type?: 'string' | 'number' | 'boolean' | 'object' | 'array';
|
|
6
|
-
required?: boolean;
|
|
7
|
-
in?: any[];
|
|
8
|
-
default?: any;
|
|
9
|
-
config?: Partial<ValidatorOptions>;
|
|
10
|
-
};
|
|
11
|
-
export declare type ValidatorOptions<Content = Record<string, any>> = {
|
|
12
|
-
whitelist?: 'error' | 'ignore';
|
|
13
|
-
rules: {
|
|
14
|
-
[k in keyof Content]?: ValidatorRuleOptions;
|
|
15
|
-
};
|
|
16
|
-
onError?: (type: string, key: string | string[], value?: any) => {
|
|
17
|
-
statusCode?: number;
|
|
18
|
-
message: any;
|
|
19
|
-
} | void;
|
|
20
|
-
};
|
|
21
|
-
declare type Request<TParams extends Record<string, any> = any, TCookie extends Record<string, string> = any, TSession extends Record<string, string> = any> = {
|
|
22
|
-
headers: {
|
|
23
|
-
[key: string]: string;
|
|
24
|
-
};
|
|
25
|
-
params?: TParams;
|
|
26
|
-
cookie?: Cookie<TCookie, TSession>;
|
|
27
|
-
session?: Session<TSession, TCookie>;
|
|
28
|
-
};
|
|
29
|
-
export declare type BeforeOption<TParams extends Record<string, any> = any, TCookie extends Record<string, string> = any, TSession extends Record<string, string> = any> = (request: Request<TParams, TCookie, TSession>) => Promise<void | {
|
|
30
|
-
statusCode?: number;
|
|
31
|
-
message: string;
|
|
32
|
-
}>;
|
|
33
|
-
export declare type ValidatorConfig<TParams extends Record<string, any> = any, TCookie extends Record<string, string> = any, TSession extends Record<string, string> = any> = {
|
|
34
|
-
params?: ValidatorOptions<TParams>;
|
|
35
|
-
cookie?: ValidatorOptions<TCookie>;
|
|
36
|
-
session?: ValidatorOptions<TSession>;
|
|
37
|
-
before?: BeforeOption;
|
|
38
|
-
};
|
|
39
|
-
export declare class Validator<TParams extends Record<string, any> = any, TCookie extends Record<string, string> = any, TSession extends Record<string, string> = any> {
|
|
40
|
-
before?: BeforeOption<TParams, TCookie, TSession>;
|
|
41
|
-
paramsConfig?: ValidatorOptions<TParams>;
|
|
42
|
-
cookieConfig?: ValidatorOptions<TCookie>;
|
|
43
|
-
sessionConfig?: ValidatorOptions<TSession>;
|
|
44
|
-
private request;
|
|
45
|
-
private readonly logger;
|
|
46
|
-
constructor(config: {
|
|
47
|
-
params?: ValidatorOptions<TParams>;
|
|
48
|
-
cookie?: ValidatorOptions<TCookie>;
|
|
49
|
-
session?: ValidatorOptions<TSession>;
|
|
50
|
-
before?: BeforeOption<TParams, TCookie, TSession>;
|
|
51
|
-
}, logger: Logger);
|
|
52
|
-
valid(request: Request<TParams, TCookie, TSession>): Promise<void>;
|
|
53
|
-
validContent(type: string, params: {
|
|
54
|
-
[key: string]: any;
|
|
55
|
-
}, baseKey: string, config: ValidatorOptions): void;
|
|
56
|
-
}
|
|
57
|
-
export {};
|