topbit 1.0.0 → 2.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 (71) hide show
  1. package/LICENSE +128 -0
  2. package/README.cn.md +1562 -0
  3. package/README.md +1272 -0
  4. package/bin/app.js +17 -0
  5. package/bin/loadinfo.sh +18 -0
  6. package/bin/new-ctl.js +230 -0
  7. package/bin/newapp.js +22 -0
  8. package/cache/allow.js +130 -0
  9. package/cache/errserv.js +45 -0
  10. package/cache/minserv.js +167 -0
  11. package/cache/router.js +84 -0
  12. package/cache/rsa/localhost-cert.pem +19 -0
  13. package/cache/rsa/localhost-privkey.pem +28 -0
  14. package/cache/servsock.js +286 -0
  15. package/cache/sni.js +66 -0
  16. package/demo/allow.js +98 -0
  17. package/demo/group-api.js +161 -0
  18. package/demo/group-api2.js +109 -0
  19. package/demo/log.js +118 -0
  20. package/demo/memlimit.js +31 -0
  21. package/demo/min.js +7 -0
  22. package/demo/serv.js +15 -0
  23. package/images/middleware.jpg +0 -0
  24. package/images/titbit-middleware.png +0 -0
  25. package/images/titbit.png +0 -0
  26. package/package.json +38 -8
  27. package/src/bodyparser.js +420 -0
  28. package/src/connfilter.js +125 -0
  29. package/src/context1.js +166 -0
  30. package/src/context2.js +179 -0
  31. package/src/ctxpool.js +38 -0
  32. package/src/ext.js +318 -0
  33. package/src/fastParseUrl.js +426 -0
  34. package/src/headerLimit.js +18 -0
  35. package/src/http1.js +337 -0
  36. package/src/http2.js +337 -0
  37. package/src/httpc.js +251 -0
  38. package/src/loader/loader.js +999 -0
  39. package/src/logger.js +32 -0
  40. package/src/loggermsg.js +349 -0
  41. package/src/makeId.js +200 -0
  42. package/src/midcore.js +213 -0
  43. package/src/middleware1.js +104 -0
  44. package/src/middleware2.js +121 -0
  45. package/src/monitor.js +380 -0
  46. package/src/movefile.js +30 -0
  47. package/src/optionsCheck.js +54 -0
  48. package/src/randstring.js +23 -0
  49. package/src/router.js +682 -0
  50. package/src/sendmsg.js +27 -0
  51. package/src/strong.js +72 -0
  52. package/src/token/token.js +462 -0
  53. package/src/topbit.js +1291 -0
  54. package/src/versionCheck.js +31 -0
  55. package/test/test-bigctx.js +29 -0
  56. package/test/test-daemon-args.js +7 -0
  57. package/test/test-find.js +69 -0
  58. package/test/test-helper.js +81 -0
  59. package/test/test-route-sort.js +71 -0
  60. package/test/test-route.js +49 -0
  61. package/test/test-route2.js +51 -0
  62. package/test/test-run-args.js +7 -0
  63. package/test/test-url.js +52 -0
  64. package/tmp/buff-code +134 -0
  65. package/tmp/devplan +9 -0
  66. package/tmp/evt-test.js +34 -0
  67. package/tmp/fastParseUrl.js +302 -0
  68. package/tmp/router-rule.js +559 -0
  69. package/tmp/test-cdps.js +122 -0
  70. package/tmp/titbit.js +1286 -0
  71. package/main.js +0 -0
package/src/httpc.js ADDED
@@ -0,0 +1,251 @@
1
+ 'use strict'
2
+
3
+ const http2 = require('node:http2')
4
+ const fs = require('node:fs')
5
+ const process = require('node:process');
6
+ const checkHeaderLimit = require('./headerLimit.js')
7
+ const sendmsg = require('./sendmsg.js');
8
+
9
+ let Httpc = function () {
10
+ if ( !(this instanceof Httpc) ) {
11
+ return new Httpc()
12
+ }
13
+
14
+ this.logger = null
15
+ this.config = null
16
+ this.fpurl = null
17
+ this.host = ''
18
+ }
19
+
20
+ /**
21
+ *
22
+ * @param {object} app titbit实例
23
+ */
24
+
25
+ Httpc.prototype.init = function (app) {
26
+ app.config.server.allowHTTP1 = true
27
+
28
+ app.httpServ.run = this.run
29
+
30
+ app.httpServ.onRequest = this.onRequest
31
+ }
32
+
33
+ Httpc.prototype.onRequest = function () {
34
+ let self = this
35
+
36
+ let callback = (req, res) => {
37
+ req.on('error', (err) => {
38
+ self.requestError(err, req, req.headers)
39
+ })
40
+
41
+ res.on('error', (err) => {
42
+ self.requestError(err, res, req.headers)
43
+ })
44
+
45
+ req.on('aborted', err => {
46
+ err && self.requestError(err, req, req.headers)
47
+ !err && req.destroy()
48
+ })
49
+
50
+ let remote_ip = req.socket.remoteAddress || ''
51
+
52
+ if (req.url.length > self.config.maxUrlLength) {
53
+ req.url = req.url.substring(0, self.config.maxUrlLength)
54
+ }
55
+
56
+ if (self.config.globalLog) {
57
+
58
+ let real_ip = '-'
59
+ if (self.config.realIP) {
60
+ real_ip = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || '-'
61
+ }
62
+
63
+ res.on('finish', () => {
64
+ if (!req || !res) return;
65
+
66
+ checkHeaderLimit(req.headers, 'user-agent', 111)
67
+
68
+ if (req.httpVersion[0] === '1') {
69
+ checkHeaderLimit(req.headers, 'host', 300)
70
+
71
+ self.logger({
72
+ method : req.method,
73
+ status : res.statusCode,
74
+ ip : remote_ip,
75
+ link: `https://${req.headers.host || self.host}${req.url}`,
76
+ agent : req.headers['user-agent'] || '-',
77
+ real_ip : real_ip,
78
+ })
79
+
80
+ } else {
81
+
82
+ if (res.stream.rstCode == http2.constants.NGHTTP2_NO_ERROR) {
83
+ checkHeaderLimit(req.headers, ':authority', 300)
84
+
85
+ self.logger({
86
+ method : req.method,
87
+ status : res.statusCode,
88
+ ip : remote_ip,
89
+ link : `https://${req.authority}${req.url}`,
90
+ agent : req.headers['user-agent'] || '-',
91
+ real_ip : real_ip,
92
+ })
93
+
94
+ }
95
+
96
+ }
97
+
98
+ })
99
+
100
+ }
101
+
102
+ let urlobj = self.fpurl(req.url, self.config.autoDecodeQuery,
103
+ self.config.fastParseQuery,
104
+ self.config.maxQuery)
105
+
106
+ let rt = self.router.findRealPath(urlobj.path, req.method)
107
+
108
+ if (rt === null) {
109
+ res.statusCode = 404
110
+ res.end(self.config.notFound)
111
+ return
112
+ }
113
+
114
+ let ctx = self.ctxpool.getctx() || new self.Context()
115
+
116
+ if (req.httpVersion[0] === '1') {
117
+ ctx.version = '1.1'
118
+ ctx.major = 1
119
+ ctx.host = req.headers.host || self.host
120
+ } else {
121
+ ctx.version = '2'
122
+ ctx.major = 2
123
+ ctx.host = req.authority
124
+ }
125
+
126
+ ctx.bodyLength = 0
127
+ ctx.maxBody = self.config.maxBody
128
+ ctx.service = self.service
129
+
130
+ ctx.method = req.method
131
+ ctx.protocol = 'https'
132
+ ctx.ip = remote_ip
133
+
134
+ ctx.port = req.socket.remotePort
135
+ ctx.request = req
136
+ ctx.response = res
137
+ ctx.stream = res
138
+ ctx.reply = ctx.response
139
+ ctx.headers = req.headers
140
+
141
+ ctx.path = urlobj.path
142
+ ctx.query = urlobj.query
143
+ ctx.routepath = rt.key
144
+ ctx.requestCall = rt.reqcall.reqCall
145
+ ctx.name = rt.reqcall.name
146
+ ctx.group = rt.reqcall.group
147
+ ctx.param = rt.args
148
+ rt = null
149
+
150
+ return self.midware.run(ctx).finally(()=>{
151
+ ctx.stream = null
152
+ self.ctxpool.free(ctx)
153
+ ctx = null
154
+ })
155
+
156
+ }
157
+
158
+ return callback
159
+ }
160
+
161
+ /**
162
+ * 运行HTTP/1.1服务
163
+ * @param {number} port 端口号
164
+ * @param {string} host IP地址,可以是IPv4或IPv6
165
+ * 0.0.0.0 对应使用IPv6则是::
166
+ */
167
+ Httpc.prototype.run = function (port, host) {
168
+ let self = this
169
+ let serv = null
170
+
171
+ if (this.config.key && this.config.cert) {
172
+ try {
173
+ this.config.server.key = fs.readFileSync(this.config.key)
174
+ this.config.server.cert = fs.readFileSync(this.config.cert)
175
+ } catch (err) {
176
+ !this.isWorker && console.error(err)
177
+ sendmsg('_server-error', err.message, {autoExit: true, exitCode: 1})
178
+ }
179
+ } else if (!this.config.server.SNICallback || typeof this.config.server.SNICallback !== 'function') {
180
+ !this.isWorker && console.error('APLN协议需要启用HTTPS,请设置cert和key 或 server.SNICallback。')
181
+ sendmsg('_server-error', '请设置cert和key或server.SNICallback。', {autoExit: true, exitCode: 1})
182
+ }
183
+
184
+ this.config.server.allowHTTP1 = true
185
+
186
+ serv = http2.createSecureServer(this.config.server, this.onRequest())
187
+
188
+ serv.on('tlsClientError', (err, tls) => {
189
+ self.config.errorHandle(err, '--ERR-TLS-CLIENT--');
190
+ !tls.destroyed && tls.destroy();
191
+ })
192
+
193
+ serv.on('secureConnection', (sock) => {
194
+ sock.on('error', err => {
195
+ self.config.errorHandle(err, '--ERR-CONNECTION--')
196
+ })
197
+ })
198
+
199
+ serv.on('clientError', (err, sock) => {
200
+ !sock.destroyed && sock.destroy()
201
+ })
202
+
203
+ serv.on('unknownProtocol', tls_sock => {
204
+ !tls_sock.destroyed && tls_sock.destroy()
205
+ })
206
+
207
+ serv.on('error', (e) => {
208
+ if (e.code === 'EADDRINUSE') {
209
+ if (process.send !== undefined && typeof process.send === 'function') {
210
+ process.send({type: '_eaddr'}, (err) => {})
211
+ } else {
212
+ console.error('该端口已被使用,请先停止进程')
213
+ process.exit(1)
214
+ }
215
+ } else {
216
+ self.config.errorHandle(e, '--ERR--')
217
+ }
218
+ })
219
+
220
+ serv.setTimeout(this.config.timeout, (sock) => {
221
+ !sock.destroyed && sock.destroy()
222
+ })
223
+
224
+ for (let k in this.events) {
225
+ for (let ecall of this.events[k]) {
226
+ if (typeof ecall !== 'function') {
227
+ continue
228
+ }
229
+
230
+ serv.on(k, ecall)
231
+ }
232
+ }
233
+
234
+ this.events = {}
235
+
236
+ //说明是使用unix socket模式监听服务
237
+ if (typeof port === 'string' && port.indexOf('.sock') > 0) {
238
+ serv.listen(port)
239
+ } else {
240
+ this.host = host
241
+ if (port !== 443) {
242
+ this.host += `:${port}`
243
+ }
244
+
245
+ serv.listen(port, host)
246
+ }
247
+
248
+ return serv
249
+ }
250
+
251
+ module.exports = Httpc