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,182 @@
1
+ 'use strict'
2
+
3
+ const ext = require('./ext.js')
4
+ const moveFile = require('./movefile.js')
5
+
6
+ class Context {
7
+
8
+ constructor() {
9
+ this.version = '2'
10
+
11
+ //协议主版本号
12
+ this.major = 2
13
+
14
+ this.maxBody = 0
15
+
16
+ this.method = ''
17
+
18
+ this.host = ''
19
+
20
+ this.protocol = ''
21
+
22
+ this.ip = ''
23
+
24
+ //实际的访问路径
25
+ this.path = ''
26
+
27
+ this.name = ''
28
+
29
+ this.headers = {}
30
+
31
+ //实际执行请求的路径
32
+ this.routepath = ''
33
+
34
+ this.param = {}
35
+
36
+ this.query = {}
37
+
38
+ this.body = {}
39
+
40
+ this.isUpload = false
41
+
42
+ this.group = ''
43
+
44
+ this.rawBody = ''
45
+
46
+ this.bodyLength = 0
47
+
48
+ this.files = {}
49
+
50
+ this.requestCall = null
51
+
52
+ this.ext = ext
53
+
54
+ this.port = 0
55
+
56
+ this.data = ''
57
+ this.dataEncoding = 'utf8'
58
+ this.dataHeaders = {}
59
+
60
+ //在请求时指向实际的stream
61
+ this.stream = null
62
+
63
+ this.req = null
64
+
65
+ this.res = null
66
+
67
+ this.box = {}
68
+
69
+ this.service = null
70
+
71
+ this.user = null
72
+ }
73
+
74
+ json(data) {
75
+ return this.setHeader('content-type', 'application/json').to(data)
76
+ }
77
+
78
+ text(data, encoding='utf-8') {
79
+ return this.setHeader('content-type', `text/plain;charset=${encoding}`).to(data)
80
+ }
81
+
82
+ html(data, encoding='utf-8') {
83
+ return this.setHeader('content-type', `text/html;charset=${encoding}`).to(data)
84
+ }
85
+
86
+ to(d) {
87
+ this.data = d
88
+ }
89
+
90
+ getFile(name, ind=0) {
91
+ if (ind < 0) {
92
+ return this.files[name] || []
93
+ }
94
+
95
+ if (this.files[name] === undefined) {
96
+ return null
97
+ }
98
+
99
+ if (ind >= this.files[name].length) {
100
+ return null
101
+ }
102
+
103
+ return this.files[name][ind]
104
+ }
105
+
106
+ setHeader(nobj, val=null) {
107
+ if (typeof nobj === 'string' && val != null) {
108
+ this.dataHeaders[nobj] = val
109
+ } else if (typeof nobj === 'object') {
110
+ for(let k in nobj) {
111
+ this.dataHeaders[k] = nobj[k]
112
+ }
113
+ }
114
+
115
+ return this
116
+ }
117
+
118
+ sendHeader() {
119
+ if (this.stream && !this.stream.headersSent) {
120
+ this.stream.respond(this.dataHeaders)
121
+ }
122
+
123
+ return this
124
+ }
125
+
126
+ status(stcode = null) {
127
+ if (stcode === null) {
128
+ let st = this.dataHeaders[':status']
129
+ return st ? parseInt(st) : 200
130
+ }
131
+
132
+ this.dataHeaders[':status'] = (typeof stcode === 'string' ? stcode : stcode.toString())
133
+
134
+ return this
135
+ }
136
+
137
+ moveFile(upf, target) {
138
+ return moveFile(this, upf, target)
139
+ }
140
+
141
+ /**
142
+ * @param {(fs.ReadStream|string)} filename
143
+ * @param {object} options
144
+ * */
145
+ pipe(filename, options={}) {
146
+ if (!this.stream.headersSent) {
147
+ this.sendHeader()
148
+ }
149
+
150
+ return ext.pipe(filename, this.res, options)
151
+ }
152
+
153
+ pipeJson(filename) {
154
+ return this.setHeader('content-type', 'application/json').pipe(filename)
155
+ }
156
+
157
+ pipeText(filename, encoding='utf-8') {
158
+ return this.setHeader('content-type', `text/plain;charset=${encoding}`).pipe(filename)
159
+ }
160
+
161
+ pipeHtml(filename, encoding='utf-8') {
162
+ return this.setHeader('content-type', `text/html;charset=${encoding}`).pipe(filename)
163
+ }
164
+
165
+ removeHeader(name) {
166
+ this.dataHeaders[name]!==undefined && (delete this.dataHeaders[name]);
167
+ return this
168
+ }
169
+
170
+ write(data) {
171
+ this.stream && !this.stream.headersSent && this.stream.respond(this.dataHeaders)
172
+
173
+ this.stream.write(data)
174
+ return this
175
+ }
176
+
177
+ }
178
+
179
+ Context.prototype.oo = Context.prototype.to
180
+ Context.prototype.ok = Context.prototype.to
181
+
182
+ module.exports = Context
package/src/ctxpool.js ADDED
@@ -0,0 +1,39 @@
1
+ 'use strict'
2
+
3
+ let ctxpool = new function () {
4
+
5
+ this.max = 9999
6
+
7
+ this.pool = []
8
+
9
+ this.getctx = () => {
10
+ if (this.pool.length > 0) {
11
+ return this.pool.pop()
12
+ }
13
+
14
+ return null
15
+ }
16
+
17
+ this.free = (ctx) => {
18
+ if (this.pool.length < this.max) {
19
+ ctx.body = {}
20
+ ctx.files = {}
21
+ ctx.query = {}
22
+ ctx.box = {}
23
+ ctx.isUpload = false
24
+ ctx.user = null
25
+ ctx.dataEncoding = 'utf8'
26
+ ctx.data = null
27
+
28
+ this.pool.push(ctx)
29
+ }
30
+
31
+ }
32
+
33
+ this.clear = () => {
34
+ while(this.pool.pop()) {}
35
+ }
36
+
37
+ }
38
+
39
+ module.exports = ctxpool
package/src/ext.js ADDED
@@ -0,0 +1,318 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('crypto');
4
+ const fs = require('fs');
5
+ const randstring = require('./randstring.js');
6
+ const makeId = require('./makeId.js');
7
+
8
+ const ext = {}
9
+
10
+ ext.randstring = randstring
11
+ ext.makeId = makeId.serialId
12
+ ext.serialId = makeId.serialId
13
+ ext.bigId = makeId.bigId
14
+
15
+ /**
16
+ * @param {string} fname 文件名称
17
+ */
18
+ ext.extName = function (fname) {
19
+ let ind = fname.length - 2
20
+
21
+ while (ind > 0 && fname[ind] !== '.') {
22
+ ind -= 1
23
+ }
24
+
25
+ if (ind <= 0) return ''
26
+
27
+ return fname.substring(ind)
28
+ }
29
+
30
+ let fmtbits = n => {
31
+ return n < 10 ? `0${n}` : n
32
+ }
33
+
34
+ /**
35
+ * @param {string} filename 文件名称
36
+ * @param {string} pre_str 前缀字符串
37
+ */
38
+ ext.makeName = function(filename = '') {
39
+ let tm = new Date()
40
+
41
+ let orgname = `${tm.getFullYear()}-${fmtbits(tm.getMonth()+1)}-${fmtbits(tm.getDate())}_`
42
+ + `${fmtbits(tm.getHours())}-${fmtbits(tm.getMinutes())}-${fmtbits(tm.getSeconds())}`
43
+ + `_${tm.getMilliseconds()}`
44
+ + `${parseInt(Math.random() * 1000) + 1}${parseInt(Math.random() * 100000) + 10000}`
45
+
46
+ if (filename) return (orgname + ext.extName(filename))
47
+
48
+ return orgname
49
+ }
50
+
51
+ /**
52
+ * @param {string} filename 文件名
53
+ * @param {string} encoding 文件编码
54
+ */
55
+ ext.readFile = function (filename, encoding = 'utf8') {
56
+ return new Promise((rv, rj) => {
57
+ fs.readFile(filename, {encoding:encoding}, (err, data) => {
58
+ if (err) {
59
+ rj(err)
60
+ } else {
61
+ rv(data)
62
+ }
63
+ })
64
+ })
65
+ }
66
+
67
+ ext.readb = (filename) => {
68
+ return new Promise((rv,rj) => {
69
+ fs.readFile(filename,(err,data) => {
70
+ if (err) {
71
+ rj(err)
72
+ } else {
73
+ rv(data)
74
+ }
75
+ })
76
+ })
77
+ }
78
+
79
+ /**
80
+ * @param {string} filename 文件名
81
+ * @param {string} encoding 文件编码
82
+ */
83
+ ext.writeFile = function (filename, data, encoding = 'utf8') {
84
+ return new Promise((rv, rj) => {
85
+ fs.writeFile(filename, data, {encoding:encoding}, err => {
86
+ if (err) {
87
+ rj(err)
88
+ } else {
89
+ rv(data)
90
+ }
91
+ })
92
+ })
93
+ }
94
+
95
+ let _ctype_map = {
96
+ ".png" : "image/png",
97
+ ".jpeg" : "image/jpeg",
98
+ ".jpg" : "image/jpeg",
99
+ ".gif" : "image/gif",
100
+ ".ico" : "image/x-icon",
101
+ ".bmp" : "image/bmp",
102
+ ".svg" : "image/svg+xml",
103
+ ".webp" : "image/webp",
104
+
105
+ ".js" : "text/javascript",
106
+ ".html" : "text/html",
107
+ ".css" : "text/css",
108
+ ".xml" : "text/xml",
109
+ ".json" : "application/json",
110
+ ".txt" : "text/plain",
111
+ ".c" : "text/plain",
112
+ ".h" : "text/plain",
113
+ ".sh" : "text/plain",
114
+
115
+ ".crt" : "application/x-x509-ca-cert",
116
+ ".cert" : "application/x-x509-ca-cert",
117
+ ".cer" : "application/x-x509-ca-cert",
118
+ ".zip" : "application/zip",
119
+ ".tgz" : "application/x-compressed",
120
+ ".gz" : "application/x-gzip",
121
+
122
+ ".mp3" : "audio/mpeg",
123
+ ".wav" : "audio/wav",
124
+ ".midi" : "audio/midi",
125
+ ".wav" : "audio/wav",
126
+ ".flac" : "audio/flac",
127
+
128
+ ".mp4" : "video/mp4",
129
+ ".webm" : "video/webm",
130
+
131
+ '.ttf' : 'font/ttf',
132
+ '.wtf' : 'font/wtf',
133
+ '.woff' : 'font/woff',
134
+ '.woff2' : 'font/woff2',
135
+ '.ttc' : 'font/ttc',
136
+ }
137
+
138
+ let ctype_extname = {}
139
+
140
+ for (let k in _ctype_map) {
141
+ ctype_extname[_ctype_map[k]] = k
142
+ }
143
+
144
+ /**
145
+ * @param {string} extname 文件扩展名
146
+ */
147
+ ext.ctype = (extname) => {
148
+ if (_ctype_map[extname] === undefined) {
149
+ return 'application/octet-stream'
150
+ }
151
+
152
+ return _ctype_map[extname]
153
+ }
154
+
155
+ ext.extnameType = (ctype) => {
156
+ return ctype_extname[ctype] || ''
157
+ }
158
+
159
+ let __aesIV = '1283634750392757'
160
+ let __aag = 'aes-256-cbc'
161
+
162
+ Object.defineProperty(ext, 'aesIv', {
163
+ set: (iv) => {
164
+ __aesIV = iv
165
+ },
166
+
167
+ get: () => {
168
+ return __aesIV
169
+ }
170
+ })
171
+
172
+ Object.defineProperty(ext, 'algorithm', {
173
+ set: (a) => {
174
+ __aag = a
175
+ },
176
+
177
+ get: () => {
178
+ return __aag
179
+ }
180
+ })
181
+
182
+ /*
183
+ *key 必须是32位
184
+ * */
185
+ ext.aesEncrypt = function (data, key, encoding = 'base64url') {
186
+ var h = crypto.createCipheriv(__aag, key, __aesIV)
187
+ let hd = h.update(data, 'utf8', encoding)
188
+ hd += h.final(encoding)
189
+ return hd
190
+ }
191
+
192
+ ext.aesDecrypt = function (data, key, encoding = 'base64url') {
193
+ var h = crypto.createDecipheriv(__aag, key, __aesIV)
194
+ let hd = h.update(data, encoding, 'utf8')
195
+ hd += h.final('utf8')
196
+ return hd
197
+ }
198
+
199
+ ext.md5 = (data, encoding = 'hex') => {
200
+ let h = crypto.createHash('md5')
201
+ h.update(data)
202
+ return h.digest(encoding)
203
+ }
204
+
205
+ ext.sha1 = (data, encoding = 'hex') => {
206
+ let h = crypto.createHash('sha1')
207
+ h.update(data)
208
+ return h.digest(encoding)
209
+ }
210
+
211
+ ext.sha256 = (data, encoding = 'hex') => {
212
+ let h = crypto.createHash('sha256')
213
+ h.update(data)
214
+ return h.digest(encoding)
215
+ }
216
+
217
+ ext.sha512 = (data, encoding = 'hex') => {
218
+ let h = crypto.createHash('sha512')
219
+ h.update(data)
220
+ return h.digest(encoding)
221
+ }
222
+
223
+ ext.sm3 = (data, encoding = 'hex') => {
224
+ let h = crypto.createHash('sm3')
225
+ h.update(data)
226
+ return h.digest(encoding)
227
+ }
228
+
229
+ ext.hmacsha1 = (data, key, encoding = 'hex') => {
230
+ let h = crypto.createHmac('sha1', key)
231
+ h.update(data)
232
+ return h.digest(encoding)
233
+ }
234
+
235
+ ext.timestr = function (m = 'long') {
236
+ let t = new Date()
237
+
238
+ let year = t.getFullYear()
239
+ let month = t.getMonth() + 1
240
+ let day = t.getDate()
241
+ let hour = t.getHours()
242
+ let min = t.getMinutes()
243
+ let sec = t.getSeconds()
244
+
245
+ let mt = `${year}-${month > 9 ? '' : '0'}${month}-${day > 9 ? '' : '0'}${day}`
246
+
247
+ if (m === 'short') {
248
+ return mt
249
+ }
250
+
251
+ let md = `${mt}_${hour > 9 ? '' : '0'}${hour}`
252
+
253
+ if (m === 'middle') {
254
+ return md
255
+ }
256
+
257
+ return `${md}-${min > 9 ? '' : '0'}${min}-${sec > 9 ? '' : '0'}${sec}`
258
+ }
259
+
260
+ ext.nrand = function (f, t) {
261
+ let discount = t - f
262
+ return parseInt((Math.random() * discount) + f)
263
+ }
264
+
265
+ let uuidSerial = makeId.serialId
266
+
267
+ //8-4-4-4-12
268
+ ext.uuid = (short_mode=false) => {
269
+ if (short_mode) {
270
+ let id = uuidSerial(18)
271
+
272
+ return id.substring(0,8) + '-' + id.substring(8,10) + '-' + id.substring(10,12) + '-'
273
+ + id.substring(12, 14) + '-' + id.substring(14,18)
274
+ }
275
+
276
+ let id = uuidSerial(20)
277
+
278
+ return id.substring(0,8) + '-' + id.substring(8,12) + '-' + id.substring(12,16) + '-' + id.substring(16, 20)
279
+ + '-' + makeId(12)
280
+ }
281
+
282
+ ext.pipe = (filename, dest, options={}) => {
283
+ let fread
284
+ if (!options || typeof options !== 'object') otpions = {}
285
+
286
+ if (typeof filename === 'string') {
287
+ fread = fs.createReadStream(filename, options)
288
+ } else if (filename instanceof fs.ReadStream) {
289
+ fread = filename
290
+ } else {
291
+ throw new Error(`${filename}:filename必须是字符串或fs.ReadStream实例。`)
292
+ }
293
+
294
+ let end_writer = options.endWrite === undefined ? true : !!options.endWrite
295
+
296
+ return new Promise((rv, rj) => {
297
+ fread.pipe(dest, {end: end_writer})
298
+
299
+ fread.on('error', err => {
300
+ rj(err)
301
+ })
302
+
303
+ fread.on('end', () => {
304
+ rv()
305
+ })
306
+
307
+ })
308
+ }
309
+
310
+ ext.delay = (tms=100) => {
311
+ return new Promise((rv, rj) => {
312
+ setTimeout(() => {
313
+ rv()
314
+ }, tms)
315
+ })
316
+ }
317
+
318
+ module.exports = ext