topbit 3.1.6 → 3.1.8
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.cn.md +16 -3
- package/README.md +15 -2
- package/demo/http2.js +17 -1
- package/demo/rule.js +17 -0
- package/docs/en/topbit-token.md +2 -3
- package/docs/topbit-token.md +2 -3
- package/package.json +1 -1
- package/src/extends/paramcheck.js +93 -44
- package/src/httpc.js +1 -1
- package/test/test-bigctx.js +16 -13
- package/test/test-daemon-args.js +2 -2
package/README.cn.md
CHANGED
|
@@ -2047,8 +2047,21 @@ app.use(pck, {method: 'GET'})
|
|
|
2047
2047
|
let pmbody = new ParamCheck({
|
|
2048
2048
|
key: 'body',
|
|
2049
2049
|
rule: {
|
|
2050
|
-
username: {
|
|
2051
|
-
|
|
2050
|
+
username: {
|
|
2051
|
+
must: true,
|
|
2052
|
+
//min length
|
|
2053
|
+
min: 5,
|
|
2054
|
+
//max length
|
|
2055
|
+
max: 30
|
|
2056
|
+
},
|
|
2057
|
+
passwd: {
|
|
2058
|
+
must: true,
|
|
2059
|
+
min: 7,
|
|
2060
|
+
max: 20
|
|
2061
|
+
},
|
|
2062
|
+
mobile: {
|
|
2063
|
+
regex: /^(12|13|15|16|17|18|19)[0-9]{9}$/
|
|
2064
|
+
}
|
|
2052
2065
|
}
|
|
2053
2066
|
})
|
|
2054
2067
|
|
|
@@ -2065,7 +2078,7 @@ JWT 协议的 Token 验证与签发。推荐使用 `Topbit.Token` 替代。
|
|
|
2065
2078
|
const Topbit = require('topbit')
|
|
2066
2079
|
const {JWT} = Topbit.extensions
|
|
2067
2080
|
|
|
2068
|
-
let j = new
|
|
2081
|
+
let j = new KWT({
|
|
2069
2082
|
timeout: 7200000, // 超时时间
|
|
2070
2083
|
})
|
|
2071
2084
|
j.alg = 'hs512' // 设置算法
|
package/README.md
CHANGED
|
@@ -1999,8 +1999,21 @@ app.use(pck, {method: 'GET'})
|
|
|
1999
1999
|
let pmbody = new ParamCheck({
|
|
2000
2000
|
key: 'body',
|
|
2001
2001
|
rule: {
|
|
2002
|
-
username: {
|
|
2003
|
-
|
|
2002
|
+
username: {
|
|
2003
|
+
must: true,
|
|
2004
|
+
//min length
|
|
2005
|
+
min: 5,
|
|
2006
|
+
//max length
|
|
2007
|
+
max: 30
|
|
2008
|
+
},
|
|
2009
|
+
passwd: {
|
|
2010
|
+
must: true,
|
|
2011
|
+
min: 7,
|
|
2012
|
+
max: 20
|
|
2013
|
+
},
|
|
2014
|
+
mobile: {
|
|
2015
|
+
regex: /^(12|13|15|16|17|18|19)[0-9]{9}$/
|
|
2016
|
+
}
|
|
2004
2017
|
}
|
|
2005
2018
|
})
|
|
2006
2019
|
|
package/demo/http2.js
CHANGED
|
@@ -5,12 +5,17 @@
|
|
|
5
5
|
process.chdir(__dirname)
|
|
6
6
|
|
|
7
7
|
let Topbit = require('../src/topbit.js')
|
|
8
|
-
let {Loader} = Topbit
|
|
8
|
+
let {Loader, npargv} = Topbit
|
|
9
|
+
|
|
10
|
+
let {args} = npargv({
|
|
11
|
+
'--httpc': 'httpc'
|
|
12
|
+
})
|
|
9
13
|
|
|
10
14
|
let app = new Topbit({
|
|
11
15
|
debug: true,
|
|
12
16
|
globalLog: true,
|
|
13
17
|
logType: 'stdio',
|
|
18
|
+
allowHTTP1: args.httpc,
|
|
14
19
|
loadInfoFile: '--mem',
|
|
15
20
|
cert: './cert/localhost-cert.pem',
|
|
16
21
|
key: './cert/localhost-privkey.pem',
|
|
@@ -25,8 +30,19 @@ if (app.isWorker) {
|
|
|
25
30
|
let ld = new Loader()
|
|
26
31
|
|
|
27
32
|
ld.init(app)
|
|
33
|
+
|
|
34
|
+
app.get('/httpc/:id', async ctx => {
|
|
35
|
+
console.log(ctx.headers, ctx.method, ctx.path, ctx.name, ctx.group)
|
|
36
|
+
ctx.to({
|
|
37
|
+
major: ctx.major,
|
|
38
|
+
protocol: ctx.protocol,
|
|
39
|
+
port: ctx.port,
|
|
40
|
+
group: ctx.group
|
|
41
|
+
})
|
|
42
|
+
})
|
|
28
43
|
}
|
|
29
44
|
|
|
45
|
+
|
|
30
46
|
app.sched('none')
|
|
31
47
|
|
|
32
48
|
app.autoWorker(3)
|
package/demo/rule.js
CHANGED
|
@@ -93,6 +93,23 @@ let pmbody = new ParamCheck({
|
|
|
93
93
|
},
|
|
94
94
|
passwd: {
|
|
95
95
|
must: true
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
mobile: {
|
|
99
|
+
errorMessage: '手机号不符合要求',
|
|
100
|
+
regex: /^(12|13|14|15|16|17|18|19)[0-9]{9}$/,
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
detail: {
|
|
104
|
+
errorMessage: 'detail长度0~10',
|
|
105
|
+
min: 0,
|
|
106
|
+
max: 10
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
age: {
|
|
110
|
+
to: 'int',
|
|
111
|
+
min: 15,
|
|
112
|
+
max: 95
|
|
96
113
|
}
|
|
97
114
|
}
|
|
98
115
|
})
|
package/docs/en/topbit-token.md
CHANGED
|
@@ -52,9 +52,8 @@ module.exports = token
|
|
|
52
52
|
async post(c) {
|
|
53
53
|
// After successful login
|
|
54
54
|
const userinfo = { uid: 1, name: 'Alice', role: 'admin' }
|
|
55
|
-
const t = token.
|
|
56
|
-
c.
|
|
57
|
-
c.to({ok: true})
|
|
55
|
+
const t = token.makeToken(userinfo)
|
|
56
|
+
c.to({ok: true, token: t})
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
// All protected routes automatically use token.mid()
|
package/docs/topbit-token.md
CHANGED
|
@@ -59,9 +59,8 @@ class User {
|
|
|
59
59
|
role : 'admin',
|
|
60
60
|
// expires 可单独设置更长时间
|
|
61
61
|
}
|
|
62
|
-
let t = token.
|
|
63
|
-
c.
|
|
64
|
-
c.to({ok: true, msg: 'login success'})
|
|
62
|
+
let t = token.makeToken(userinfo) // 签发 Token
|
|
63
|
+
c.to({ok: true, msg: 'login success', token: t})
|
|
65
64
|
}
|
|
66
65
|
}
|
|
67
66
|
|
package/package.json
CHANGED
|
@@ -30,7 +30,7 @@ class ParamCheck {
|
|
|
30
30
|
|
|
31
31
|
case 'rule':
|
|
32
32
|
if (typeof options[k] === 'object') {
|
|
33
|
-
this.rule = options[k]
|
|
33
|
+
this.rule = {...options[k]}
|
|
34
34
|
}
|
|
35
35
|
break
|
|
36
36
|
|
|
@@ -51,17 +51,20 @@ class ParamCheck {
|
|
|
51
51
|
this.deleteDeny = !!options[k]
|
|
52
52
|
break
|
|
53
53
|
|
|
54
|
-
default:
|
|
54
|
+
default:
|
|
55
55
|
this[k] = options[k]
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
this.ruleKeys = Object.keys(this.rule)
|
|
60
|
+
|
|
59
61
|
let data_type = ''
|
|
60
|
-
for (let k
|
|
62
|
+
for (let k of this.ruleKeys) {
|
|
61
63
|
data_type = typeof this.rule[k]
|
|
62
64
|
|
|
63
65
|
if (data_type === 'string' || data_type === 'number') {
|
|
64
66
|
this.rule[k] = {
|
|
67
|
+
__is_regex__: false,
|
|
65
68
|
__is_value__: true,
|
|
66
69
|
__value__: this.rule[k],
|
|
67
70
|
__type__: data_type === 'string' ? TYPE_STRING : TYPE_NUMBER
|
|
@@ -70,6 +73,20 @@ class ParamCheck {
|
|
|
70
73
|
continue
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
if (this.rule[k] instanceof RegExp) {
|
|
77
|
+
this.rule[k] = {
|
|
78
|
+
__is_regex__: true,
|
|
79
|
+
__is_value__: false,
|
|
80
|
+
regex: this.rule[k]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (this.rule[k].regex && this.rule[k].regex instanceof RegExp) {
|
|
87
|
+
this.rule[k].__is_regex__ = true
|
|
88
|
+
}
|
|
89
|
+
|
|
73
90
|
this.rule[k].__is_value__ = false
|
|
74
91
|
|
|
75
92
|
if (this.rule[k].callback && typeof this.rule[k].callback === 'function') {
|
|
@@ -82,11 +99,11 @@ class ParamCheck {
|
|
|
82
99
|
}
|
|
83
100
|
|
|
84
101
|
/**
|
|
85
|
-
*
|
|
102
|
+
*
|
|
86
103
|
* @param {object} obj c.param or c.query
|
|
87
104
|
* @param {*} k key name
|
|
88
105
|
* @param {*} rule filter rule
|
|
89
|
-
*
|
|
106
|
+
*
|
|
90
107
|
* rule描述了如何进行数据的过滤,如果rule是字符串或数字则要求严格相等。
|
|
91
108
|
* 否则rule应该是一个object,可以包括的属性如下:
|
|
92
109
|
* - callback 用于过滤的回调函数,在验证时,会传递数据,除此之外没有其他参数。
|
|
@@ -108,7 +125,7 @@ class ParamCheck {
|
|
|
108
125
|
ost.ok = false
|
|
109
126
|
return false
|
|
110
127
|
}
|
|
111
|
-
|
|
128
|
+
|
|
112
129
|
if (rule.default !== undefined) {
|
|
113
130
|
obj[k] = rule.default
|
|
114
131
|
return true
|
|
@@ -117,49 +134,80 @@ class ParamCheck {
|
|
|
117
134
|
} else {
|
|
118
135
|
//数据初始必然是字符串,转换只能是整数或浮点数或boolean。
|
|
119
136
|
if (rule.to) {
|
|
120
|
-
|
|
137
|
+
let is_number = typeof obj[k] === 'number'
|
|
138
|
+
|
|
139
|
+
if (is_number) {
|
|
140
|
+
if (rule.to === 'int') {
|
|
141
|
+
obj[k] = Math.floor(obj[k])
|
|
142
|
+
} else if (rule.to === 'boolean' || rule.to === 'bool') {
|
|
143
|
+
obj[k] = !!obj[k]
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
switch(rule.to) {
|
|
147
|
+
case 'int':
|
|
148
|
+
obj[k] = parseInt(obj[k])
|
|
149
|
+
if (isNaN(obj[k])) {
|
|
150
|
+
if (rule.default !== undefined) {
|
|
151
|
+
obj[k] = rule.default
|
|
152
|
+
return true
|
|
153
|
+
}
|
|
154
|
+
ost.ok = false
|
|
155
|
+
return false
|
|
156
|
+
}
|
|
157
|
+
break
|
|
158
|
+
|
|
159
|
+
case 'float':
|
|
160
|
+
obj[k] = parseFloat(obj[k])
|
|
161
|
+
if (isNaN(obj[k])) {
|
|
162
|
+
if (rule.default !== undefined) {
|
|
163
|
+
obj[k] = rule.default
|
|
164
|
+
return true
|
|
165
|
+
}
|
|
166
|
+
ost.ok = false
|
|
167
|
+
return false
|
|
168
|
+
}
|
|
169
|
+
break
|
|
170
|
+
|
|
171
|
+
case 'boolean':
|
|
172
|
+
case 'bool':
|
|
173
|
+
obj[k] = (obj[k] === 'true' || obj[k] === true || obj[k] == 1) ? true : false
|
|
174
|
+
break
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (rule.min !== undefined && obj[k] < rule.min) {
|
|
121
179
|
ost.ok = false
|
|
122
180
|
return false
|
|
123
181
|
}
|
|
124
182
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return false
|
|
135
|
-
}
|
|
136
|
-
break
|
|
137
|
-
|
|
138
|
-
case 'float':
|
|
139
|
-
obj[k] = parseFloat(obj[k])
|
|
140
|
-
if (isNaN(obj[k])) {
|
|
141
|
-
if (rule.default !== undefined) {
|
|
142
|
-
obj[k] = rule.default
|
|
143
|
-
return true
|
|
144
|
-
}
|
|
145
|
-
ost.ok = false
|
|
146
|
-
return false
|
|
147
|
-
}
|
|
148
|
-
break
|
|
149
|
-
|
|
150
|
-
case 'boolean':
|
|
151
|
-
case 'bool':
|
|
152
|
-
obj[k] = obj[k] === 'true' ? true : false
|
|
153
|
-
break
|
|
183
|
+
if (rule.max !== undefined && obj[k] > rule.max) {
|
|
184
|
+
ost.ok = false
|
|
185
|
+
return false
|
|
186
|
+
}
|
|
187
|
+
} else if (typeof obj[k] === 'string') {
|
|
188
|
+
//data is string min and max mean's length
|
|
189
|
+
if (rule.min !== undefined && obj[k].length < rule.min) {
|
|
190
|
+
ost.ok = false
|
|
191
|
+
return false
|
|
154
192
|
}
|
|
155
|
-
}
|
|
156
193
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
194
|
+
if (rule.max !== undefined && obj[k].length > rule.max) {
|
|
195
|
+
ost.ok = false
|
|
196
|
+
return false
|
|
197
|
+
}
|
|
198
|
+
} else if (typeof obj[k] === 'number') {
|
|
199
|
+
if (rule.min !== undefined && obj[k] < rule.min) {
|
|
200
|
+
ost.ok = false
|
|
201
|
+
return false
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (rule.max !== undefined && obj[k] > rule.max) {
|
|
205
|
+
ost.ok = false
|
|
206
|
+
return false
|
|
207
|
+
}
|
|
160
208
|
}
|
|
161
209
|
|
|
162
|
-
if (rule.
|
|
210
|
+
if (rule.__is_regex__ && !rule.regex.test(obj[k])) {
|
|
163
211
|
ost.ok = false
|
|
164
212
|
return false
|
|
165
213
|
}
|
|
@@ -170,10 +218,11 @@ class ParamCheck {
|
|
|
170
218
|
if (rule.callback(obj, k, method) !== false) {
|
|
171
219
|
return true
|
|
172
220
|
}
|
|
221
|
+
|
|
173
222
|
ost.ok = false
|
|
174
223
|
return false
|
|
175
224
|
}
|
|
176
|
-
|
|
225
|
+
|
|
177
226
|
} else if (rule.__type__ === TYPE_STRING) {
|
|
178
227
|
if (obj[k] === undefined || obj[k] !== rule.__value__) {
|
|
179
228
|
ost.ok = false
|
|
@@ -194,7 +243,7 @@ class ParamCheck {
|
|
|
194
243
|
let ost = {ok: true, key: ''}
|
|
195
244
|
|
|
196
245
|
if (this.key !== 'body' || (c.body !== c.rawBody && typeof c.body === 'object')) {
|
|
197
|
-
for (let k
|
|
246
|
+
for (let k of this.ruleKeys) {
|
|
198
247
|
if (!this.checkData(d, k, this.rule[k], c.method, ost)) {
|
|
199
248
|
return ost
|
|
200
249
|
}
|
|
@@ -248,7 +297,7 @@ class ParamCheck {
|
|
|
248
297
|
|
|
249
298
|
await next(c)
|
|
250
299
|
}
|
|
251
|
-
|
|
300
|
+
|
|
252
301
|
}
|
|
253
302
|
|
|
254
303
|
return async (c, next) => {
|
package/src/httpc.js
CHANGED
package/test/test-bigctx.js
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
'use'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const Topbit = require('../src/topbit.js');
|
|
4
|
+
|
|
5
|
+
let app = new Topbit({
|
|
4
6
|
debug: true,
|
|
5
7
|
//http2: true
|
|
6
8
|
});
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
let start_time = Date.now()
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
let ctx = null
|
|
11
13
|
|
|
12
|
-
let total = 20000
|
|
14
|
+
let total = 20000
|
|
13
15
|
|
|
14
|
-
for (let i=0
|
|
15
|
-
ctx = new app.httpServ.Context()
|
|
16
|
+
for (let i=0; i < total; i++) {
|
|
17
|
+
ctx = new app.httpServ.Context()
|
|
16
18
|
ctx.path = '/';
|
|
17
19
|
ctx.ip = '127.0.0.1';
|
|
18
|
-
ctx.requestCall =
|
|
19
|
-
c.
|
|
20
|
-
}
|
|
20
|
+
ctx.requestCall = c => {
|
|
21
|
+
c.to('success')
|
|
22
|
+
}
|
|
23
|
+
|
|
21
24
|
ctx.box.rand = Math.random()
|
|
22
|
-
ctx = null
|
|
25
|
+
ctx = null
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
let end_time = Date.now()
|
|
26
29
|
|
|
27
30
|
let rtm = end_time - start_time;
|
|
28
31
|
|
|
29
|
-
console.log(rtm, 'ms', `${parseInt(total * 1000 / rtm)}/s`)
|
|
32
|
+
console.log(rtm, 'ms', `${parseInt(total * 1000 / rtm)}/s`)
|
package/test/test-daemon-args.js
CHANGED