topbit 1.0.0 → 3.0.0

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.
Files changed (89) hide show
  1. package/LICENSE +128 -0
  2. package/README.cn.md +1519 -0
  3. package/README.md +1483 -0
  4. package/bin/app.js +17 -0
  5. package/bin/loadinfo.sh +18 -0
  6. package/bin/new-ctl.js +234 -0
  7. package/bin/newapp.js +22 -0
  8. package/demo/allow.js +98 -0
  9. package/demo/cert/localhost-cert.pem +19 -0
  10. package/demo/cert/localhost-privkey.pem +28 -0
  11. package/demo/controller/api.js +15 -0
  12. package/demo/extends.js +5 -0
  13. package/demo/group-api.js +161 -0
  14. package/demo/group-api2.js +109 -0
  15. package/demo/http2.js +34 -0
  16. package/demo/http2_proxy_backend.js +45 -0
  17. package/demo/http2proxy.js +48 -0
  18. package/demo/http_proxy_backend.js +44 -0
  19. package/demo/httpproxy.js +47 -0
  20. package/demo/loader.js +27 -0
  21. package/demo/log.js +118 -0
  22. package/demo/memlimit.js +31 -0
  23. package/demo/min.js +7 -0
  24. package/demo/serv.js +15 -0
  25. package/images/middleware.jpg +0 -0
  26. package/images/topbit-middleware.png +0 -0
  27. package/images/topbit.png +0 -0
  28. package/package.json +42 -11
  29. package/src/_loadExtends.js +21 -0
  30. package/src/bodyparser.js +420 -0
  31. package/src/connfilter.js +125 -0
  32. package/src/context1.js +166 -0
  33. package/src/context2.js +182 -0
  34. package/src/ctxpool.js +39 -0
  35. package/src/ext.js +318 -0
  36. package/src/extends/Http2Pool.js +365 -0
  37. package/src/extends/__randstring.js +24 -0
  38. package/src/extends/cookie.js +44 -0
  39. package/src/extends/cors.js +334 -0
  40. package/src/extends/errorlog.js +252 -0
  41. package/src/extends/http2limit.js +126 -0
  42. package/src/extends/http2proxy.js +691 -0
  43. package/src/extends/jwt.js +217 -0
  44. package/src/extends/mixlogger.js +63 -0
  45. package/src/extends/paramcheck.js +266 -0
  46. package/src/extends/proxy.js +662 -0
  47. package/src/extends/realip.js +34 -0
  48. package/src/extends/referer.js +68 -0
  49. package/src/extends/resource.js +398 -0
  50. package/src/extends/session.js +174 -0
  51. package/src/extends/setfinal.js +50 -0
  52. package/src/extends/sni.js +48 -0
  53. package/src/extends/sse.js +293 -0
  54. package/src/extends/timing.js +111 -0
  55. package/src/extends/tofile.js +123 -0
  56. package/src/fastParseUrl.js +426 -0
  57. package/src/headerLimit.js +18 -0
  58. package/src/http1.js +336 -0
  59. package/src/http2.js +337 -0
  60. package/src/httpc.js +251 -0
  61. package/src/lib/npargv.js +354 -0
  62. package/src/lib/zipdata.js +45 -0
  63. package/src/loader/loader.js +999 -0
  64. package/src/logger.js +32 -0
  65. package/src/loggermsg.js +349 -0
  66. package/src/makeId.js +200 -0
  67. package/src/midcore.js +213 -0
  68. package/src/middleware1.js +103 -0
  69. package/src/middleware2.js +116 -0
  70. package/src/monitor.js +380 -0
  71. package/src/movefile.js +30 -0
  72. package/src/optionsCheck.js +54 -0
  73. package/src/randstring.js +23 -0
  74. package/src/router.js +682 -0
  75. package/src/sendmsg.js +27 -0
  76. package/src/strong.js +72 -0
  77. package/src/token/token.js +461 -0
  78. package/src/topbit.js +1293 -0
  79. package/src/versionCheck.js +31 -0
  80. package/test/test-bigctx.js +29 -0
  81. package/test/test-daemon-args.js +7 -0
  82. package/test/test-ext.js +81 -0
  83. package/test/test-find.js +69 -0
  84. package/test/test-route-sort.js +71 -0
  85. package/test/test-route.js +49 -0
  86. package/test/test-route2.js +51 -0
  87. package/test/test-run-args.js +7 -0
  88. package/test/test-url.js +52 -0
  89. package/main.js +0 -0
@@ -0,0 +1,426 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ *
5
+ * 此函数是专门为了解析请求的路径和查询字符串部分而设计,因为url.parse在后续版本要抛弃,而URL解析后的searchParams无法和之前的程序兼容。
6
+ *
7
+ *
8
+ * 通过maxArgs控制最大解析的参数个数。
9
+ *
10
+ * 为了更快的处理,fpqs和fpurl以两个独立函数的方式编写,虽然有很多代码的逻辑重复。
11
+ *
12
+ * fpqs主要是针对content-type为application/x-www-form-urlencoded这种格式提供的。
13
+ *
14
+ */
15
+
16
+ /* let httpchar = ['h', 't', 't', 'p', ':', '/', '/']
17
+ let httpschar = ['h', 't', 't', 'p', 's', ':', '/', '/']
18
+
19
+ let simpleCheckHttpUrl = (str) => {
20
+ if (str.length < 7) return false
21
+
22
+ for (let i = 0; i < 4; i++) {
23
+ if (httpchar[i] !== str[i]) return false
24
+ }
25
+
26
+ if (str[4] === 's') {
27
+ if (str[5] === ':' && str[6] === '/' && str[7] === '/') return true
28
+ } else if (str[4] === ':') {
29
+ if (str[5] === '/' && str[6] === '/') return true
30
+ }
31
+
32
+ return false
33
+ }
34
+ */
35
+
36
+ let http_url_preg = /^https?:\/\//
37
+
38
+ /* let chararr = [
39
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
40
+ 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd',
41
+ 'e', 'f'
42
+ ]
43
+
44
+ let charMap = {}
45
+ chararr.forEach(x => {
46
+ charMap[x] = true
47
+ }) */
48
+
49
+ const isHexTable = new Int8Array([
50
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
51
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
52
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32 - 47
53
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
54
+ 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64 - 79
55
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80 - 95
56
+ 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96 - 111
57
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112 - 127
58
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128 ...
59
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ... 256
66
+ ]);
67
+
68
+ // %
69
+ const CHAR_PERCENT = 37
70
+
71
+ // &
72
+ const CHAR_AMPERSAND = 38
73
+
74
+ // =
75
+ const CHAR_EQUAL = 61
76
+
77
+ //这个函数没有对状态使用单独的变量标记
78
+ let is_encoded = (str) => {
79
+ let i = 0
80
+ let state = 0
81
+ let code = 0
82
+ //let start_ind = str.indexOf('%')
83
+ //if (start_ind < 0) return false
84
+ let isEncode = false
85
+
86
+ for (; i < str.length; ++i) {
87
+ //如果计数超过2说明是16进制的数字
88
+ if (state > 2) {
89
+ state = 0
90
+ isEncode = true
91
+ //return true
92
+ }
93
+
94
+ code = str.charCodeAt(i)
95
+ if (state > 0) {
96
+ //console.log(isHexTable[code], code)
97
+ if (isHexTable[code] === 1) {
98
+ state++
99
+ continue
100
+ }
101
+ else {
102
+ state = 0
103
+ //这说明不是合法的编码,decodeURIComponent会出错
104
+ return false
105
+ }
106
+ }
107
+
108
+ if (code === CHAR_PERCENT) {
109
+ state = 1
110
+ }
111
+ }
112
+
113
+ return isEncode
114
+ }
115
+
116
+ function fpqs(search, obj, autoDecode=true, maxArgs=0) {
117
+ let ind = 0
118
+ let and_ind = 0
119
+ let last_ind = 0
120
+ let val
121
+ let org_val
122
+ let t
123
+ let count = 0
124
+ let send = search.length
125
+
126
+ while (and_ind < send) {
127
+ and_ind = search.indexOf('&', last_ind)
128
+
129
+ if (and_ind < 0) and_ind = send
130
+
131
+ if (maxArgs > 0 && count >= maxArgs) {
132
+ return
133
+ }
134
+
135
+ if (and_ind === last_ind) {
136
+ last_ind++
137
+ continue
138
+ }
139
+
140
+ ind = last_ind
141
+
142
+ while (ind < and_ind && search[ind] !== '=') ind++
143
+
144
+ if (last_ind >= ind) {
145
+ last_ind = and_ind + 1
146
+ continue
147
+ }
148
+
149
+ t = search.substring(last_ind, ind)
150
+
151
+ org_val = ind < and_ind ? search.substring(ind+1, and_ind) : ''
152
+
153
+ if (autoDecode) {
154
+ if (org_val.length > 2 && is_encoded(org_val)) {
155
+ try {
156
+ val = decodeURIComponent(org_val)
157
+ } catch (err) {
158
+ val = org_val
159
+ }
160
+ } else {
161
+ val = org_val
162
+ }
163
+ } else {
164
+ val = org_val
165
+ }
166
+
167
+ if (Array.isArray(obj[t])) {
168
+ obj[ t ].push(val)
169
+ } else {
170
+ if (obj[ t ] !== undefined) {
171
+ obj[ t ] = [ obj[ t ], val ]
172
+ } else {
173
+ count++
174
+ obj[ t ] = val
175
+ }
176
+ }
177
+
178
+ last_ind = and_ind + 1
179
+ }
180
+
181
+ }
182
+
183
+ /**
184
+ *
185
+ * @param {string} org_url
186
+ * url可能是完整的格式,一般来说是/开始的路径,这两种都是协议允许的格式。
187
+ *
188
+ * */
189
+ function fpurl(org_url, autoDecode=false, fastMode=true, maxArgs=0) {
190
+ let urlobj = {
191
+ path : '/',
192
+ query : {},
193
+ hash : ''
194
+ }
195
+
196
+ let hash_index = org_url.indexOf('#')
197
+ let url = org_url
198
+
199
+ if (hash_index >= 0) {
200
+ urlobj.hash = org_url.substring(hash_index+1)
201
+ url = org_url.substring(0, hash_index)
202
+ org_url = url
203
+ }
204
+
205
+ let ind = url.indexOf('?')
206
+ let search = ''
207
+
208
+ if (ind === 0) {
209
+ urlobj.path = '/'
210
+ search = url.substring(1)
211
+ } else {
212
+ if (ind > 0) {
213
+ search = url.substring(ind+1)
214
+ url = org_url.substring(0, ind)
215
+
216
+ if (url[0] !== '/' && http_url_preg.test(url)) {
217
+ let slash_index = url.indexOf('/', 8)
218
+
219
+ //while (slash_index < ind && url[slash_index] !== '/') {slash_index++}
220
+
221
+ if (slash_index >= 0) {
222
+ urlobj.path = url.substring(slash_index)
223
+ } else {
224
+ urlobj.path = '/'
225
+ }
226
+ } else {
227
+ urlobj.path = url
228
+ }
229
+
230
+ } else {
231
+ if (url[0] !== '/' && http_url_preg.test(url)) {
232
+ let slash_index = url.indexOf('/', 8)
233
+ slash_index > 0 && (urlobj.path = url.substring(slash_index))
234
+ slash_index < 0 && (urlobj.path = '/')
235
+ } else {
236
+ urlobj.path = url || '/'
237
+ }
238
+ return urlobj
239
+ }
240
+ }
241
+
242
+ let query = urlobj.query
243
+ let and_ind = 0
244
+ let last_ind = 0
245
+ let val
246
+ let org_val
247
+ let t
248
+
249
+ let send = search.length
250
+ let count = 0
251
+
252
+ while (and_ind < send) {
253
+ if (maxArgs > 0 && count >= maxArgs) {
254
+ break
255
+ }
256
+
257
+ and_ind = search.indexOf('&', last_ind)
258
+ if (and_ind < 0) and_ind = send
259
+
260
+ if (and_ind === last_ind) {
261
+ last_ind++
262
+ continue
263
+ }
264
+
265
+ ind = last_ind
266
+
267
+ while (ind < and_ind && search[ind] !== '=') ind++
268
+
269
+ if (last_ind >= ind) {
270
+ last_ind = and_ind + 1
271
+ continue
272
+ }
273
+
274
+ t = search.substring(last_ind, ind)
275
+
276
+ val = search.slice(ind+1, and_ind)
277
+
278
+ if (autoDecode && is_encoded(val)) {
279
+ try {
280
+ val = decodeURIComponent(val)
281
+ } catch (err) {
282
+ //val = org_val
283
+ }
284
+ }
285
+
286
+ if (query[t] === undefined || fastMode) {
287
+ query[t] = val
288
+ count++
289
+ } else {
290
+ if (!Array.isArray(query[t])) {
291
+ query[t] = [ query[t] ]
292
+ }
293
+ query[t].push(val)
294
+ count++
295
+ }
296
+
297
+ last_ind = and_ind + 1
298
+ }
299
+
300
+ return urlobj
301
+ }
302
+
303
+ module.exports = {
304
+ fpurl,
305
+ fpqs
306
+ }
307
+
308
+ /* let code = 0
309
+ let isEncode = false
310
+ let encodeCheck = 0
311
+ let lastPos = 0
312
+ let pairStart = 0
313
+ let buf = ''
314
+ let out = []
315
+ let seenSep = false
316
+ let args_count = 0
317
+ let i = 0
318
+ for (; i < search.length; i++) {
319
+ if (maxArgs > 0 && args_count >= maxArgs) break
320
+ code = search.charCodeAt(i)
321
+
322
+ if (code === CHAR_AMPERSAND) {
323
+ if (pairStart === i) {
324
+ //空的匹配,比如&&连续
325
+ lastPos = pairStart = i + 1
326
+ continue
327
+ }
328
+
329
+ if (encodeCheck === 3) {
330
+ isEncode = true
331
+ }
332
+
333
+ if (lastPos < i)
334
+ buf = search.slice(lastPos, i)
335
+
336
+ if (isEncode) {
337
+ try {
338
+ buf = decodeURIComponent(buf)
339
+ } catch (err){
340
+
341
+ }
342
+ }
343
+
344
+ out.push(buf);
345
+
346
+ !seenSep && out.push('');
347
+
348
+ seenSep = false
349
+ buf = ''
350
+ isEncode = false;
351
+ encodeCheck = 0
352
+ lastPos = pairStart = i + 1
353
+ continue
354
+ }
355
+
356
+ // Try matching key/value separator (e.g. '=') if we haven't already
357
+ if (!seenSep && code === CHAR_EQUAL) {
358
+ // Key/value separator match!
359
+ if (encodeCheck === 3) {
360
+ isEncode = true
361
+ }
362
+
363
+ if (lastPos < i) buf = search.slice(lastPos, i)
364
+ if (isEncode) {
365
+ try {
366
+ buf = decodeURIComponent(buf)
367
+ } catch(err){}
368
+ }
369
+
370
+ out.push(buf)
371
+
372
+ args_count++
373
+ seenSep = true
374
+ buf = ''
375
+ isEncode = false
376
+ encodeCheck = 0
377
+ lastPos = i + 1
378
+ continue
379
+ }
380
+
381
+ // Try to match an (valid) encoded byte (once) to minimize unnecessary
382
+ // calls to string decoding functions
383
+ if (code === CHAR_PERCENT) {
384
+ encodeCheck === 0 && (encodeCheck = 1)
385
+ }
386
+ else if (encodeCheck > 0 && encodeCheck < 3) {
387
+ if (isHexTable[code] === 1) {
388
+ ++encodeCheck
389
+ } else {
390
+ encodeCheck = 0
391
+ }
392
+ }
393
+ }
394
+
395
+ if (pairStart !== i) {
396
+ if (lastPos < i)
397
+ buf = search.slice(lastPos, i)
398
+
399
+ if (isEncode) {
400
+ try {
401
+ buf = decodeURIComponent(buf)
402
+ } catch (err) {}
403
+ }
404
+ out.push(buf)
405
+ if (!seenSep) out.push('')
406
+ //console.log(pairStart, i, buf)
407
+ }
408
+
409
+ let oend = out.length-1
410
+
411
+ for (let i = 0; i < oend; i+=2) {
412
+ code = out[i]
413
+ //if (!code) continue
414
+
415
+ if (fastMode || query[code] === undefined) {
416
+ query[code] = out[i+1]
417
+ } else {
418
+ if (!Array.isArray(query[code])) {
419
+ query[code] = [ query[code], out[i+1] ]
420
+ } else {
421
+ query[code].push(out[i+1])
422
+ }
423
+ }
424
+ }
425
+
426
+ return urlobj */
@@ -0,0 +1,18 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * 目的在于检测消息头长度,如果没有设置则不会进行任何操作。
5
+ *
6
+ * @param {object} headers
7
+ * @param {string} k
8
+ * @param {number} maxLength
9
+ */
10
+ module.exports = (headers, k, maxLength) => {
11
+
12
+ if (!headers[k]) return;
13
+
14
+ let h = headers[k];
15
+
16
+ if (h.length > maxLength) headers[k] = h.substring(0, maxLength);
17
+
18
+ }