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
package/bin/app.js ADDED
@@ -0,0 +1,17 @@
1
+ 'use strict'
2
+
3
+ const Titbit = require('titbit')
4
+
5
+ const app = new Titbit({
6
+ debug: true,
7
+ })
8
+
9
+ app.get('/', async ctx => {
10
+ ctx.send('success')
11
+ })
12
+
13
+ app.post('/', async ctx => {
14
+ ctx.send(ctx.body)
15
+ })
16
+
17
+ app.run(1234)
@@ -0,0 +1,18 @@
1
+ #!/bin/bash
2
+
3
+ if [ "$#" -eq 0 ] ; then
4
+ echo "usage: $0 [PATH]"
5
+ echo "example: $0 /tmp/loadinfo.log"
6
+ exit 0
7
+ fi
8
+
9
+ if [ ! -f "$1" ] ; then
10
+ echo "$1 is not a file"
11
+ exit 1
12
+ fi
13
+
14
+ while clear ; do
15
+ cat "$1"
16
+ sleep 0.35
17
+ done
18
+
package/bin/new-ctl.js ADDED
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict'
4
+
5
+ let simple_mode = false
6
+
7
+ let type_context = `\n//!!注意:以下注释是为了能够在支持jsdoc的代码编辑器中提示以及方便查阅提供,不需要可以去掉。
8
+ /**
9
+ * ---------------------- ctx.ext模块具备的方法 -----------------------------
10
+ *
11
+ * @typedef {object} ext
12
+ * @property {function} extName(filename: string) - 解析文件扩展名。
13
+ * @property {function} makeName(filename: string) - 生成唯一文件名,默认为时间字符串+随机数:2021-01-01_12-12-23_27789.jpg,filename主要用于获取扩展名。
14
+ * @property {function} nrand(n, m) - 返回两个数之间的随机数。
15
+ * @property {function} uuid() - 返回唯一字符串用于唯一ID,支持标准的8-4-4-4-12和短字符串8-2-2-4两种模式(传递参数为true)。
16
+ * @property {function} timestr() - 默认返回年-月-日_时-分-秒,没有空格,方便保存和解析。
17
+ * @property {function} sha1(text, encoding = 'hex')
18
+ * @property {function} sha256(text, encoding = 'hex')
19
+ * @property {function} sha512(text, encoding = 'hex')
20
+ * @property {function} sm3(text, encoding = 'hex')
21
+ * @property {function} hmacsha1(text, key, encoding = 'hex')
22
+ * @property {function} pipe(filename: string, reply: object)
23
+ *
24
+ * 更多参考:{@link https://gitee.com/daoio/titbit/wikis/helper-function}
25
+ */
26
+ /**
27
+ * --------------------------------- 请求上下文 -----------------------------------------
28
+ *
29
+ * @typedef {object} context
30
+ * @property {string} version - 协议版本,字符串类型,为'1.1' 或 '2' 或 '3'。
31
+ * @property {number} major - 协议主要版本号,1、2、3分别表示HTTP/1.1 HTTP/2 HTTP/3。
32
+ * @property {string} method - 请求类型,GET POST等HTTP请求类型,大写字母的字符串。
33
+ * @property {string} path - 具体请求的路径,比如 /x/y。
34
+ * @property {string} routepath - 实际执行请求的路由字符串,比如 /x/:id。
35
+ * @property {boolean} isUpload - 是否为上传文件请求,此时就是检测消息头content-type是否为multipart/form-data格式。
36
+ * @property {object} box - 默认为空对象,可以添加任何属性值,用来动态传递给下一层组件需要使用的信息。
37
+ * @property {object} query - url传递的参数。
38
+ * @property {object} param - 路由参数。
39
+ * @property {object} headers - 指向request.headers。
40
+ * @property {object} files - 上传文件保存的信息。
41
+ * @property {(object|string|buffer|null)} body - body请求体的数据,具体格式需要看content-type,一般为字符串或者对象,也可能是buffer。
42
+ * @property {object} request HTTP/1.1 - 就是http模块request事件的参数IncomingMessage对象,HTTP/2 指向stream对象。
43
+ * @property {object} reply - HTTP/1.1协议,指向response,HTTP/2 指向stream。
44
+ * @property {object} service - 用于依赖注入的对象,指向app.service。
45
+ * @property {function} moveFile(file: object) - 用来移动上传的文件到指定路径,file是通过getFile获取的文件对象。
46
+ * @property {function} getFile(name: string, index = 0) - 根据上传名获取上传的文件,如果index是-1表示获取整个数组。
47
+ * @property {function} sendHeader() - 发送消息头,针对http/2设计,http/1.1只是一个空函数,为了代码保持一致。
48
+ * @property {function} setHeader(key: string, value: string|array)
49
+ * @property {function} send(body: string|object|buffer) - 设置要返回的body数据。
50
+ * @property {function} status(code: null | number) - 设置状态码,默认为null表示返回状态码。
51
+ * @property {ext} ext - 指向ext模块,提供了一些助手函数,具体参考wiki。
52
+ *
53
+ * 更多参考:{@link https://gitee.com/daoio/titbit/blob/master/README.md#%E8%AF%B7%E6%B1%82%E4%B8%8A%E4%B8%8B%E6%96%87}
54
+ */
55
+ `
56
+
57
+ let head_hint = `/**********************************************************************
58
+ 提示:
59
+ 表单提交或异步请求,对应于POST或PUT请求,对应函数post和put,提交的请求体数据通过 ctx.body 获取。
60
+
61
+ 路由参数通过 ctx.param 获取,示例:let id = ctx.param.id
62
+
63
+ url参数(?a=1&b=2)通过 ctx.query 获取,示例:let name = ctx.query.name
64
+
65
+ 使用ctx.getFile(name)获取上传的文件,示例:let f = ctx.getFile('image')
66
+ **********************************************************************/\n\n`
67
+
68
+ function fmt_ctx_param(text) {
69
+ let ctx_param = `
70
+ /**
71
+ * ${text}
72
+ * @param {context} ctx
73
+ * @returns
74
+ */
75
+ `
76
+ return ctx_param
77
+ }
78
+
79
+ const fs = require('fs')
80
+
81
+ function makeController(name) {
82
+ let modname = name
83
+ if (!(/^[A-Z].*/).test(name)) {
84
+ modname = name.substring(0, 1).toUpperCase() + name.substring(1)
85
+ }
86
+
87
+ return `'use strict'\n\n`
88
+ + (simple_mode ? '' : head_hint)
89
+ + `class ${modname} {\n\n`
90
+ + ` constructor() {\n`
91
+ + ` //param用于指定最后的路由参数,默认就是/:id\n`
92
+ + ` //若要改变路由,则可以设置此属性,比如设置为/:name\n`
93
+ + ` //this.param = '/:id'\n`
94
+ + ` }\n\n`
95
+ + ` //控制器类初始化后会执行此函数。\n`
96
+ + ` //service默认是app.service,此参数通过titbit-loader初始化的initArgs选项进行控制。\n`
97
+ + ` async init(service) {\n`
98
+ + ` \n`
99
+ + ` }\n\n`
100
+ + (simple_mode ? '' : ` //以下方法,若不需要,要去掉,避免无意义的路由。\n`)
101
+ + `${fmt_ctx_param('获取资源具体内容')}`
102
+ + ` async get(ctx) {\n\n`
103
+ + ` }\n`
104
+ + `${fmt_ctx_param('创建资源')}`
105
+ + ` async post(ctx) {\n\n`
106
+ + ` }\n`
107
+ + `${fmt_ctx_param('更新资源')}`
108
+ + ` async put(ctx) {\n\n`
109
+ + ` }\n`
110
+ + `${fmt_ctx_param('GET请求,用于获取资源列表')}`
111
+ + ` async list(ctx) {\n\n`
112
+ + ` }\n`
113
+ + `${fmt_ctx_param('删除资源')}`
114
+ + ` async _delete(ctx) {\n\n`
115
+ + ` }\n`
116
+ + `}\n\nmodule.exports = ${modname}\n`
117
+ + (simple_mode ? '' : `${type_context}`)
118
+
119
+ }
120
+
121
+ let limitName = [
122
+ 'async', 'await', 'for', 'of', 'if', 'else', 'switch', 'function', 'delete', 'new', 'case',
123
+ 'require', 'import', 'export', 'exports', 'process', 'global', 'this', 'let', 'const', 'var',
124
+ 'class', 'return', 'module', 'do', 'while', 'catch', 'try', 'break', 'boolean', 'instanceof',
125
+ 'typeof', 'continue', 'fetch', 'globalThis', 'queueMicrotask'
126
+ ]
127
+
128
+ let name_preg = /^[A-Za-z_][A-Za-z0-9_\-]{0,50}$/i
129
+
130
+ function checkName (name) {
131
+ return name_preg.test(name)
132
+ }
133
+
134
+ function parseNameDir (name) {
135
+ let ind = name.indexOf('/')
136
+ let hasJS = (name.length > 3 && name.substring(name.length-3) === '.js')
137
+
138
+ if (ind > 0) {
139
+ let narr = name.split('/')
140
+ let real_name = narr[narr.length-1]
141
+ return {
142
+ dir: `/${narr[narr.length-2]}`,
143
+ name: hasJS ? real_name.substring(0, real_name.length-3) : real_name
144
+ }
145
+ }
146
+
147
+ return {
148
+ dir : '',
149
+ name: hasJS ? name.substring(0, name.length-3) : name
150
+ }
151
+ }
152
+
153
+ function filterName (name) {
154
+ return (limitName.indexOf(name) >= 0 ? `_${name}` : name)
155
+ }
156
+
157
+ let cdir = 'controller'
158
+
159
+ let clist = []
160
+
161
+ //let model_name = ''
162
+
163
+ for (let i = 2; i < process.argv.length; i++) {
164
+ if (process.argv[i].indexOf('--cdir=') === 0) {
165
+
166
+ let t = process.argv[i].substring('--cdir='.length)
167
+
168
+ if (t.length > 0) {
169
+ cdir = t
170
+ }
171
+
172
+ continue
173
+ }
174
+
175
+ if (process.argv[i] === '-s' || process.argv[i] === '--pure' || process.argv[i] === '--simple')
176
+ {
177
+ simple_mode = true
178
+ continue
179
+ }
180
+
181
+ /* if (process.argv.indexOf('--model=') === 0) {
182
+ let mname = process.argv[i].substring('--model='.length)
183
+ if (mname.length > 0 && (/^[a-z0-9_][a-z\-_0-9]{0,100}$/i).test(mname)) {
184
+ model_name = mname
185
+ }
186
+
187
+ continue
188
+ } */
189
+
190
+ clist.push(process.argv[i])
191
+ }
192
+
193
+ try {
194
+ fs.accessSync(cdir)
195
+ } catch (err) {
196
+ fs.mkdirSync(cdir)
197
+ }
198
+
199
+ let nd
200
+ let cpath
201
+
202
+ for (let c of clist) {
203
+ nd = parseNameDir(c)
204
+
205
+ if (!checkName(nd.name)) {
206
+ console.error(`${nd.name} 不符合命名要求,要求字母数字,字母开头,支持连字符和下划线(- 和 _)。(the name is illegal.)`)
207
+ continue
208
+ }
209
+
210
+ let modname = nd.name.replace(/\-+/ig, '')
211
+
212
+ if (nd.dir) {
213
+ try {
214
+ fs.accessSync(`${cdir}${nd.dir}`)
215
+ } catch (err) {
216
+ fs.mkdirSync(`${cdir}${nd.dir}`)
217
+ }
218
+ }
219
+
220
+ cpath = `${cdir}${nd.dir}/${nd.name}.js`
221
+
222
+ try {
223
+ fs.accessSync(cpath)
224
+ console.error(`${c} 已经存在。`)
225
+ continue
226
+ } catch (err) {}
227
+
228
+ try {
229
+ fs.writeFileSync(cpath, makeController(filterName(modname)), {encoding: 'utf8'})
230
+ } catch (err) {
231
+ console.error(err)
232
+ }
233
+
234
+ }
package/bin/newapp.js ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ 'use strict'
3
+
4
+ //process.chdir(__dirname)
5
+
6
+ const fs = require('fs')
7
+
8
+ let fname = 'app.js'
9
+
10
+ if (process.argv.length > 2) {
11
+ fname = process.argv[2]
12
+ }
13
+
14
+ //let curdir = __dirname + '/../../'
15
+ let appfile = __dirname + '/app.js'
16
+
17
+ try {
18
+ fs.accessSync(fname)
19
+ console.log('文件已存在')
20
+ } catch (err) {
21
+ fs.writeFileSync(fname, fs.readFileSync(appfile))
22
+ }
package/demo/allow.js ADDED
@@ -0,0 +1,98 @@
1
+ 'use strict';
2
+
3
+ const titbit = require('../src/topbit.js');
4
+
5
+ const app = new titbit({
6
+ debug : true,
7
+ allow : new Set(['127.0.0.1']),
8
+ maxIPRequest: 2,
9
+ unitTime: 10,
10
+ useLimit: true,
11
+ maxConn: 2000,
12
+ //http2: true,
13
+ showLoadInfo: true,
14
+ loadInfoType : 'text',
15
+ globalLog : true,
16
+ logType: 'stdio',
17
+ loadInfoFile : '/tmp/loadinfo.log'
18
+ });
19
+
20
+ app.use(async (c, next) => {
21
+ console.log('pre middleware start');
22
+ console.log(c.group, c.name, c.method, c.path);
23
+ await next(c);
24
+ console.log('pre middleware end');
25
+ }, {pre : true});
26
+
27
+ app.use(async (c, next) => {
28
+ console.log('middleware 1');
29
+ await next(c);
30
+ console.log('middleware 1 end');
31
+ }, 'home');
32
+
33
+ app.use(async (c, next) => {
34
+ console.log('middleware 2');
35
+ c.body.say = '你好';
36
+ await next(c);
37
+ console.log('middleware 2 end');
38
+ }, {group: 'test', method: 'POST'});
39
+
40
+ app.use(async (c, next) => {
41
+ console.log('middleware 3');
42
+ if (c.query.say == 'hey') {
43
+ c.to('你好,test 接口 GET请求结束。');
44
+ } else {
45
+ await next(c);
46
+ }
47
+ console.log('middleware 3 end');
48
+ }, {group: 'test', method : 'GET'});
49
+
50
+ app.use(async (c, next) => {
51
+ console.log('set body size');
52
+ c.maxBody = 24;
53
+ await next(c);
54
+ }, {name: 'test-post', pre: true});
55
+
56
+ app.use(async (c, next) => {
57
+ console.log('middleware 4');
58
+ c.body.x = 12;
59
+ await next(c);
60
+ console.log('middleware 4 end');
61
+ }, 'test-post');
62
+
63
+ app.get('/', async c => {
64
+ c.to('ok');
65
+ }, 'home');
66
+
67
+ app.get('/test', async c => {
68
+ c.to(c.name);
69
+ }, {group: 'test', name : 'test'});
70
+
71
+ app.post('/test', async c => {
72
+ c.to(c.body);
73
+ }, {group: 'test', name : 'test-post'});
74
+
75
+ app.post('/transmit', async c => {
76
+ c.to('ok');
77
+ }, 'transmit');
78
+
79
+ app.use(async (c, next) => {
80
+ let total = 0;
81
+
82
+ c.box.dataHandle = (data) => {
83
+ total += data.length;
84
+ if (total > 32) {
85
+ c.response.statusCode = 413;
86
+ c.response.end('太多了,限制32字节以内');
87
+ return ;
88
+ }
89
+ };
90
+
91
+ await next(c);
92
+
93
+ console.log(total, 'bytes');
94
+
95
+ }, {pre: true, method: 'POST', name: 'transmit'});
96
+
97
+
98
+ app.daemon(2034, 2);
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIC/jCCAeagAwIBAgIJAM7LJO+3smgrMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
3
+ BAMMCWxvY2FsaG9zdDAeFw0xOTAzMTMxNDI1NDVaFw0xOTA0MTIxNDI1NDVaMBQx
4
+ EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
5
+ ggEBANlxw2tilmgttCHtzCkQRlbLicxSRjXEY/5JXSUZdKNGlBFLovclK/OrpixO
6
+ c9ijw6z6TPT3yvYkF2r1GKWYZWZeSdIfnd3M8UCJr06Jh8DAFZ14YUjyPcEo0Kfi
7
+ rJ/wecxRKsO1MehXo5YfgQ+IruuYYxyEhZOV8cmvXb7gi7hsKTnJ+2Xogef8sxlF
8
+ bHC+ySqHsODA2W1kX03jWUq2jo3j0D1yJ+8B103e2CMeiqjuIhvAzP700IOLNF2G
9
+ fPZ6RMLRWOTMpRMy5DtDKs/mX6Ohm7oVbpqhvC4QqP84+RyU30+/ThnU36K40rCH
10
+ 13VBi/4IThvXjjMCK06famj4bA0CAwEAAaNTMFEwHQYDVR0OBBYEFGpeaaG9leYI
11
+ W9rfUeTlgU7F0FP7MB8GA1UdIwQYMBaAFGpeaaG9leYIW9rfUeTlgU7F0FP7MA8G
12
+ A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBALtt9KQO1erWzNZGFN7h
13
+ NIsxMAg0DifUUR4HzOwVsOSjlxdkzkOylF7yYROptUIluuF90pC7RQ1EztwlPqTI
14
+ XrpLhU/JJcAx80Z+9XJJa3hS+mctaJ+Uv0lLY5uQgrYJCsK+qJ9XMOBjA8Uziyu/
15
+ mFgvfW/5Ts0mwTRn0MKLf2vRIH4F3syeiVLTxDJ0s6fKfrCryNSo8LGYAOfr0rCg
16
+ 4BbTyDt1UB+nTY6xM12zybJ/OtIZtfRG5JZHHsB1kbsOw+WzWrcKbsqncrivGt8m
17
+ XgNCpvSLE4v+giPocOkX6ySq+RCTFvdlhv1bCsHlOW5vMpSur0SQLcnSUnRfk41W
18
+ BuI=
19
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDZccNrYpZoLbQh
3
+ 7cwpEEZWy4nMUkY1xGP+SV0lGXSjRpQRS6L3JSvzq6YsTnPYo8Os+kz098r2JBdq
4
+ 9RilmGVmXknSH53dzPFAia9OiYfAwBWdeGFI8j3BKNCn4qyf8HnMUSrDtTHoV6OW
5
+ H4EPiK7rmGMchIWTlfHJr12+4Iu4bCk5yftl6IHn/LMZRWxwvskqh7DgwNltZF9N
6
+ 41lKto6N49A9cifvAddN3tgjHoqo7iIbwMz+9NCDizRdhnz2ekTC0VjkzKUTMuQ7
7
+ QyrP5l+joZu6FW6aobwuEKj/OPkclN9Pv04Z1N+iuNKwh9d1QYv+CE4b144zAitO
8
+ n2po+GwNAgMBAAECggEAZN35+dlszfzNf6Owvie3iVG3pVlRCmYEwJPFqo0JZyg5
9
+ TWCZwy2yGsG4PvtRj+A/yAEAK+66br3FQy9Y9JAiEX+RnPBfqeEE1JxJ/xObLpWs
10
+ MTUDY/RDI1RMnmRvEW5bAaVxQgHOmen1j5EjrFIKWm2BJFxxHkpDM/yubvn4tl5T
11
+ JxQk+CSNsLFZ57jd8JyIugOOql7HQNyY21Si3c9Q2HXDbXvIv/s0Bw1PB1xGXBbI
12
+ /58wz/dSajNIuYbJB3Q85PRLo12Xkb+3L5GUJDoOqrOG3aZn9OM0uNpvUNaByPyT
13
+ wL86vlyLQAlLreAL0GDCiZAMalp1JKmNNSGqMa33oQKBgQD0Qo3m4+EW0uvijF8S
14
+ dWdHeKT4lmoowpTCQiZpcZmJ1iWkpxAovjMwZf48j+giLIg7cYpxQHGTmryBb3F+
15
+ bV3Vcc4QSD1r8tAgnI+WLA2rn698syuxsAG9UUpzzQgjLRY8298OIJJS3kypfCse
16
+ hjoLwUt6kbopNn/kKXSQ2krc6QKBgQDj5UMi5Yhq5Rvof5r2j+Wr9mlYdEMOV8zc
17
+ u5fmkrSpo/li16z7XHX/e1Srq4EAcbX7XBdZc9G5injVOrtmpeZC0+/8lU6nN4Po
18
+ q0Ab5Wra5Ws5WU7bog2poHac+tWGItds6R5bfwes0f4AtSS3623FnynB9kOPycST
19
+ ZeHSdtIPhQKBgAGtW1AUjH0doaUClbyItdbVyzwxvDTfcSoMTjs3HnjF0ahZxVCi
20
+ TbOtX5uG2W8yoxTVaL/yU1VSIK062KqnkZdfmqyd8l4FYsx2hr3fO5DMHeZbTJeB
21
+ v+FO55X3+HBVZOuyDswICTkscZZQVfN1tHxULXKAAak6yJIGfthnx0/RAoGAJLwb
22
+ 6lAdgT2VFhEbpYrkdqetq3hyJqm4eAw1HBGh1YZ8+JXTaGErFBeJOnLWxH+P2giq
23
+ Kt0kfUf42kYxVwZ+617GXGyk1Qd519Ni7hw48Tfx5LikoXqpwSIAfKViLdEH8KJT
24
+ JmR/lDf1PZ/1X0Av3Z8eWAmeMltPuIK/t/E3QxECgYAl76olBcjS+0LjOp10BnnZ
25
+ M4VM4JyqjXH21OQ7YcckhugHcF12A8Y1gUsZIL/NoIEECFeor4spF2AD74AFzyPw
26
+ +WUR2BETzvsQxEp0F096LXkRT0H8IlT3ZwUbdP0//NQ4KdLyn3o+8NsDXiXqeVpp
27
+ 4Ouzs+qyLyxI2/17yodFRA==
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,15 @@
1
+ 'use strict'
2
+
3
+ class Api {
4
+ constructor() {
5
+
6
+ }
7
+
8
+ async get(ctx) {
9
+ ctx.ok([
10
+ ctx.method, ctx.path, ctx.routepath, ctx.param
11
+ ])
12
+ }
13
+ }
14
+
15
+ module.exports = Api
@@ -0,0 +1,5 @@
1
+ 'use strict'
2
+
3
+ let toolkit = require('../src/topbit.js').extensions
4
+
5
+ console.log(toolkit)
@@ -0,0 +1,161 @@
1
+ 'use strict'
2
+
3
+ const titbit = require('../lib/titbit.js')
4
+
5
+ const app = new titbit({
6
+ debug: true,
7
+ loadInfoFile: '--mem',
8
+ http2: true,
9
+ allowHTTP1: true,
10
+ key: __dirname + '/../cache/rsa/localhost-privkey.pem',
11
+ cert: __dirname + '/../cache/rsa/localhost-cert.pem'
12
+ })
13
+
14
+ /*
15
+ app.midware.addFinal = () => {
16
+ return async (c, next) => {
17
+ return c.reply.end('ok')
18
+ }
19
+ }
20
+
21
+ app.pre(async (c, next) => {
22
+ return c.reply.end('ok')
23
+ })
24
+ */
25
+
26
+ app.get('/home', async c => {
27
+ c.setHeader('x-key', Math.random()).sendHeader().send('home page')
28
+ }, '@home')
29
+
30
+ app.get('/', async c => {
31
+ for (let i = 0; i < 10; i++) {
32
+ c.write(`${i} ${Math.random()}\n`)
33
+ await c.ext.delay()
34
+ }
35
+ c.send('home page')
36
+ }, '@home')
37
+
38
+ app.use(async (ctx, next) => {
39
+ console.log('group', ctx.group, ctx.path)
40
+ await next()
41
+ console.log('group', ctx.group, ctx.path, 'end')
42
+ }, '@home')
43
+
44
+ let mid_timing = async (c, next) => {
45
+ console.log('time start')
46
+ console.time('request')
47
+ await next()
48
+ console.timeEnd('request')
49
+ }
50
+
51
+ app.trace('/o', async c => {})
52
+
53
+ app.use(async (c, next) => {
54
+ console.log('global request')
55
+ await next()
56
+ console.log('global request end\n')
57
+
58
+ }, {pre: true})
59
+
60
+ app.use(async (c, next) => {
61
+ console.log('global pre')
62
+ await next()
63
+ console.log('global pre end')
64
+
65
+ }, {pre: true})
66
+
67
+ app.router.group('/api', (route) => {
68
+ route.get('/test', async c => {
69
+ c.send('api test')
70
+ })
71
+
72
+ route.get('/stream', async c => {
73
+ for (let i = 0; i < 10; i++) {
74
+ await c.ext.delay(30)
75
+ c.write(`${i} ${Math.random()} ${Date.now()}\n`)
76
+ }
77
+ })
78
+
79
+ route.get('/:name', async c => {
80
+ c.send(c.param)
81
+ }, 'name')
82
+
83
+ route.use(async (ctx, next) => {
84
+ console.log('name test')
85
+ await next()
86
+ console.log('name test end')
87
+ }, 'name')
88
+
89
+ route.trace('/o', async c => {})
90
+ })
91
+ .use(async (c, next) => {
92
+ console.log(c.group, c.path, c.routepath)
93
+ await next()
94
+ })
95
+ .pre(async (c, next) => {
96
+ console.log('pre', c.method, c.headers)
97
+ await next()
98
+ })
99
+
100
+ app.middleware([mid_timing,], {pre: true}).group('验证', route => {
101
+ route.use(async (ctx, next) => {
102
+ console.log(' new route use test')
103
+ await next()
104
+ console.log(' new route use end')
105
+ })
106
+
107
+ route.get('/c/:o/:p', async c => {
108
+ console.log(c.group, c.name)
109
+ c.send(c.param)
110
+ })
111
+
112
+ route.middleware([
113
+ async (c, next) => {
114
+ console.log(' group sub test')
115
+ await next()
116
+ console.log(' group sub test end')
117
+ },
118
+
119
+ [
120
+ async (c, next) => {
121
+ console.log(' group sub test 2')
122
+ await next()
123
+ console.log(' group sub test 2 end')
124
+ },
125
+ {pre: false}
126
+ ]
127
+ ], {pre: true, tag: 'sub'}).group('sub', r => {
128
+
129
+ r.get('/oo', async c => {
130
+ c.send(c.group)
131
+ })
132
+
133
+ r.middleware(async (c, next) => {
134
+ console.log('sub sub test')
135
+ await next()
136
+ }).group('/sub', subr => {
137
+ subr.get('/ok', async c => {
138
+ c.send(c.group)
139
+ })
140
+ })
141
+
142
+ })
143
+
144
+ })
145
+
146
+ app.group('测试', route => {
147
+ route.get('/test', async c => {
148
+ console.log(c.group, c.name)
149
+ c.send('test ok')
150
+ }, 'test')
151
+ })
152
+ .use(async (c, next) => {
153
+ console.log('测试组')
154
+ await next()
155
+ })
156
+
157
+ app.daemon({port: 1234}, 2)
158
+
159
+ //app.run(1234)
160
+
161
+ //app.isWorker && console.log(app.midware.midGroup)