topbit 2.0.0 → 3.0.1
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 +132 -177
- package/README.md +801 -592
- package/bin/new-ctl.js +7 -3
- package/demo/allow.js +13 -13
- package/demo/controller/api.js +15 -0
- package/demo/extends.js +5 -0
- package/demo/http2.js +34 -0
- package/demo/http2_proxy_backend.js +45 -0
- package/demo/http2proxy.js +48 -0
- package/demo/http_proxy_backend.js +44 -0
- package/demo/httpproxy.js +47 -0
- package/demo/loader.js +27 -0
- package/demo/log.js +1 -1
- package/demo/memlimit.js +1 -1
- package/demo/min.js +1 -1
- package/demo/serv.js +1 -1
- package/images/topbit-middleware.webp +0 -0
- package/images/topbit.png +0 -0
- package/package.json +7 -6
- package/src/_loadExtends.js +21 -0
- package/src/bodyparser.js +1 -1
- package/src/context1.js +19 -19
- package/src/context2.js +11 -8
- package/src/ctxpool.js +1 -0
- package/src/extends/Http2Pool.js +365 -0
- package/src/extends/__randstring.js +24 -0
- package/src/extends/cookie.js +44 -0
- package/src/extends/cors.js +334 -0
- package/src/extends/errorlog.js +252 -0
- package/src/extends/http2limit.js +126 -0
- package/src/extends/http2proxy.js +691 -0
- package/src/extends/jwt.js +217 -0
- package/src/extends/mixlogger.js +63 -0
- package/src/extends/paramcheck.js +266 -0
- package/src/extends/proxy.js +662 -0
- package/src/extends/realip.js +34 -0
- package/src/extends/referer.js +68 -0
- package/src/extends/resource.js +398 -0
- package/src/extends/session.js +174 -0
- package/src/extends/setfinal.js +50 -0
- package/src/extends/sni.js +48 -0
- package/src/extends/sse.js +293 -0
- package/src/extends/timing.js +111 -0
- package/src/extends/tofile.js +123 -0
- package/src/http1.js +15 -16
- package/src/http2.js +5 -5
- package/src/httpc.js +3 -3
- package/src/lib/npargv.js +354 -0
- package/src/lib/zipdata.js +45 -0
- package/src/middleware1.js +15 -16
- package/src/middleware2.js +4 -9
- package/src/token/token.js +4 -5
- package/src/topbit.js +13 -11
- package/test/{test-helper.js → test-ext.js} +1 -1
- package/test/test-route.js +1 -1
- package/cache/allow.js +0 -130
- package/cache/errserv.js +0 -45
- package/cache/minserv.js +0 -167
- package/cache/router.js +0 -84
- package/cache/servsock.js +0 -286
- package/cache/sni.js +0 -66
- package/images/titbit-middleware.png +0 -0
- package/images/titbit.png +0 -0
- package/tmp/buff-code +0 -134
- package/tmp/devplan +0 -9
- package/tmp/evt-test.js +0 -34
- package/tmp/fastParseUrl.js +0 -302
- package/tmp/router-rule.js +0 -559
- package/tmp/test-cdps.js +0 -122
- package/tmp/titbit.js +0 -1286
- /package/{cache/rsa → demo/cert}/localhost-cert.pem +0 -0
- /package/{cache/rsa → demo/cert}/localhost-privkey.pem +0 -0
package/README.cn.md
CHANGED
|
@@ -1,51 +1,33 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Topbit
|
|
4
4
|
|
|
5
5
|
[English Documentation](README.en.md)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
> **关于类型和TypeScript的支持**
|
|
10
|
-
> 如果关于ECMAScript对类型系统的提案能够通过,则以后可以直接在JavaScript中使用类型,而无需考虑支持TS。
|
|
11
|
-
> 如果后续此提案没有通过,再考虑支持。
|
|
12
|
-
|
|
13
|
-
> 参考连接:<a href="https://github.com/tc39/proposal-type-annotations" target=_blank>JS的类型提案</a>
|
|
14
|
-
|
|
15
|
-
> 有bug或是疑惑请提交issue或者发送私信。
|
|
16
|
-
|
|
17
|
-
> 它非常快,无论是路由查找还是中间件执行过程。
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
**Wiki中有相关主题的说明:[Wiki](https://gitee.com/daoio/titbit/wikis)**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Node.js的Web开发框架,同时支持HTTP/1.1和HTTP/2协议, 提供了强大的中间件机制。
|
|
7
|
+
topbit是基于Node.js的运行于服务端的Web框架,它没有任何第三方依赖,在独特的路由和中间件分组执行机制上进行了极致优化。
|
|
24
8
|
|
|
25
9
|
|
|
26
10
|
**核心功能:**
|
|
27
11
|
|
|
28
12
|
* 请求上下文设计屏蔽接口差异。
|
|
29
13
|
|
|
30
|
-
*
|
|
14
|
+
* 全局中间件模式。
|
|
31
15
|
|
|
32
|
-
*
|
|
16
|
+
* 路由分组和路由命名。
|
|
33
17
|
|
|
34
18
|
* 中间件按照路由分组执行。中间件匹配请求方法和路由来执行。
|
|
35
19
|
|
|
36
|
-
*
|
|
20
|
+
* 开启守护进程,支持多进程集群以及worker进程自动化负载调整。
|
|
37
21
|
|
|
38
22
|
* 显示子进程负载情况。
|
|
39
23
|
|
|
40
24
|
* 默认解析body数据。
|
|
41
25
|
|
|
42
|
-
* 支持通过配置启用HTTP/1.1或是HTTP/2
|
|
26
|
+
* 支持通过配置启用HTTP/1.1或是HTTP/2服务。允许同时支持HTTP/2和HTTP/1.1。
|
|
43
27
|
|
|
44
28
|
* 支持配置启用HTTPS服务(HTTP/2服务必须要开启HTTPS)。
|
|
45
29
|
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
* 限制一段时间内单个IP的最大访问次数。
|
|
30
|
+
* 限制请求数量。限制一段时间内单个IP的最大访问次数。
|
|
49
31
|
|
|
50
32
|
* IP黑名单和IP白名单。
|
|
51
33
|
|
|
@@ -53,52 +35,30 @@ Node.js的Web开发框架,同时支持HTTP/1.1和HTTP/2协议, 提供了强
|
|
|
53
35
|
|
|
54
36
|
* 可选择是否开启自动负载模式:根据负载创建新的子进程处理请求,并在空闲时恢复初始状态。
|
|
55
37
|
|
|
56
|
-
* 可控制子进程最大内存占用,并在超出时自动重启,可控制必须重启的最大内存以及当超出某一个数值但只有连接数为0的时候才会重启的内存。
|
|
57
|
-
|
|
58
38
|
* 默认设定和网络安全相关的配置,避免软件服务层面的DDOS攻击和其他网络安全问题。
|
|
59
39
|
|
|
60
40
|
|
|
61
|
-
## !注意
|
|
62
|
-
|
|
63
|
-
请尽可能使用最新版本。**titbit会先查找路由再进行请求上下文对象的创建,如果没有发现路由,则不会创建请求上下文对象。** 这是为了避免无意义的操作,也会有其他一些错误或恶意请求的检测处理,错误状态码涉及到404和400,因此若需要在这个过程中控制返回的错误信息,需要通过初始化选项中的notFound和badRequest进行设置即可,默认的它们只是一条简短的文本信息。(自己添加的路由内部处理需要返回404则自行控制。)
|
|
64
|
-
|
|
65
|
-
## **v25.x版本变化**
|
|
66
|
-
|
|
67
|
-
v25.0.0版本开始,对请求上下文和其他相关细节进行了更新,数据属性趋向于扁平化,去掉请求上下文的res对象,不再使用ctx.res.body作为收集最终返回数据的属性,直接使用ctx.data。
|
|
68
|
-
|
|
69
|
-
使用ctx.send()函数设置最终返回的数据,代码具备兼容性,没有需要更改的地方,可以直接升级。
|
|
70
|
-
|
|
71
41
|
## 安装
|
|
72
42
|
|
|
73
43
|
```javascript
|
|
74
|
-
npm i
|
|
44
|
+
npm i topbit
|
|
75
45
|
```
|
|
76
46
|
|
|
77
47
|
同样可以通过yarn安装:
|
|
78
48
|
|
|
79
49
|
```javascript
|
|
80
|
-
yarn add
|
|
50
|
+
yarn add topbit
|
|
81
51
|
```
|
|
82
52
|
|
|
83
|
-
## 兼容性
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
从v21.8.1版本之后,到目前为止一直保持兼容更新,所有代码无需考虑兼容性问题,可以无缝升级版本。若后续技术变革导致需要不兼容更新,会给出说明。请注意文档和Wiki。
|
|
87
|
-
|
|
88
|
-
v21.8.1之前,大版本号的版本可以保证兼容性。
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<a href="https://gitee.com/daoio/titbit/wikis/%E7%89%88%E6%9C%AC%E6%94%B9%E8%BF%9B%E8%AF%B4%E6%98%8E?sort_id=3220595" target="_blank">·重要版本改进</a>
|
|
92
|
-
|
|
93
53
|
|
|
94
54
|
## 最小示例
|
|
95
55
|
|
|
96
56
|
```javascript
|
|
97
57
|
'use strict'
|
|
98
58
|
|
|
99
|
-
const
|
|
59
|
+
const Topbit = require('topbit')
|
|
100
60
|
|
|
101
|
-
const app = new
|
|
61
|
+
const app = new Topbit({
|
|
102
62
|
debug: true
|
|
103
63
|
})
|
|
104
64
|
|
|
@@ -106,7 +66,7 @@ app.run(1234)
|
|
|
106
66
|
|
|
107
67
|
```
|
|
108
68
|
|
|
109
|
-
当不填加路由时,
|
|
69
|
+
当不填加路由时,topbit默认添加一个路由:
|
|
110
70
|
|
|
111
71
|
`/*`
|
|
112
72
|
|
|
@@ -118,15 +78,15 @@ app.run(1234)
|
|
|
118
78
|
``` JavaScript
|
|
119
79
|
'use strict'
|
|
120
80
|
|
|
121
|
-
const
|
|
81
|
+
const Topbit = require('topbit')
|
|
122
82
|
|
|
123
|
-
const app = new
|
|
83
|
+
const app = new Topbit({
|
|
124
84
|
debug: true
|
|
125
85
|
})
|
|
126
86
|
|
|
127
87
|
|
|
128
88
|
app.get('/', async ctx => {
|
|
129
|
-
ctx.
|
|
89
|
+
ctx.to('success')
|
|
130
90
|
})
|
|
131
91
|
|
|
132
92
|
//默认监听0.0.0.0,参数和原生接口listen一致。
|
|
@@ -134,23 +94,22 @@ app.run(1234)
|
|
|
134
94
|
|
|
135
95
|
```
|
|
136
96
|
|
|
137
|
-
ctx.data是返回的响应数据,也可以使用ctx.
|
|
138
|
-
> 其实ctx.
|
|
139
|
-
**最好使用ctx.send()设置返回的数据,因为v25.0.0之前的版本使用的是ctx.res.body返回数据,使用send函数保证了兼容性。**
|
|
97
|
+
ctx.data是返回的响应数据,也可以使用ctx.to(data)
|
|
98
|
+
> 其实 ctx.to()内部就是设置ctx.data的值。**推荐使用 ctx.to()设置返回的数据。**
|
|
140
99
|
|
|
141
100
|
## 使用import导入
|
|
142
101
|
|
|
143
102
|
在 `.mjs` 文件中,可以使用ES6的import进行导入:
|
|
144
103
|
|
|
145
104
|
```javascript
|
|
146
|
-
import
|
|
105
|
+
import Topbit from 'topbit'
|
|
147
106
|
|
|
148
|
-
const app = new
|
|
107
|
+
const app = new Topbit({
|
|
149
108
|
debug: true
|
|
150
109
|
})
|
|
151
110
|
|
|
152
111
|
app.get('/', async ctx => {
|
|
153
|
-
ctx.
|
|
112
|
+
ctx.to('success')
|
|
154
113
|
})
|
|
155
114
|
|
|
156
115
|
app.run(1234)
|
|
@@ -172,27 +131,27 @@ GET POST PUT PATCH DELETE OPTIONS TRACE HEAD
|
|
|
172
131
|
|
|
173
132
|
'use strict'
|
|
174
133
|
|
|
175
|
-
const
|
|
134
|
+
const Topbit = require('topibit')
|
|
176
135
|
|
|
177
|
-
const app = new
|
|
136
|
+
const app = new Topbit({
|
|
178
137
|
debug: true
|
|
179
138
|
})
|
|
180
139
|
|
|
181
140
|
app.get('/', async c => {
|
|
182
|
-
c.
|
|
141
|
+
c.to('success')
|
|
183
142
|
})
|
|
184
143
|
|
|
185
144
|
app.get('/p', async c => {
|
|
186
|
-
c.
|
|
145
|
+
c.to(`${c.method} ${c.routepath}`)
|
|
187
146
|
})
|
|
188
147
|
|
|
189
148
|
app.post('/', async c => {
|
|
190
149
|
//返回上传的数据
|
|
191
|
-
c.
|
|
150
|
+
c.to(c.body)
|
|
192
151
|
})
|
|
193
152
|
|
|
194
153
|
app.put('/p', async c => {
|
|
195
|
-
c.
|
|
154
|
+
c.to({
|
|
196
155
|
method : c.method,
|
|
197
156
|
body : c.body,
|
|
198
157
|
query : c.query
|
|
@@ -217,22 +176,22 @@ app.run(8080)
|
|
|
217
176
|
``` JavaScript
|
|
218
177
|
'use strict';
|
|
219
178
|
|
|
220
|
-
const
|
|
179
|
+
const Topbit = require('topbit');
|
|
221
180
|
|
|
222
|
-
let app = new
|
|
181
|
+
let app = new Topbit({
|
|
223
182
|
debug: true
|
|
224
183
|
})
|
|
225
184
|
|
|
226
185
|
app.get('/q', async c => {
|
|
227
186
|
//URL中?后面的查询字符串解析到query中。
|
|
228
187
|
//返回JSON文本,主要区别在于header中content-type为text/json
|
|
229
|
-
c.
|
|
188
|
+
c.to(c.query)
|
|
230
189
|
})
|
|
231
190
|
|
|
232
191
|
app.post('/p', async c => {
|
|
233
192
|
//POST、PUT提交的数据保存到body,如果是表单则会自动解析,否则只是保存原始文本值,
|
|
234
193
|
//可以使用中间件处理各种数据。
|
|
235
|
-
c.
|
|
194
|
+
c.to(c.body)
|
|
236
195
|
})
|
|
237
196
|
|
|
238
197
|
app.run(2019)
|
|
@@ -254,14 +213,14 @@ app.run(2019)
|
|
|
254
213
|
``` JavaScript
|
|
255
214
|
'use strict'
|
|
256
215
|
|
|
257
|
-
const
|
|
216
|
+
const Topbit = require('topbit')
|
|
258
217
|
|
|
259
|
-
let app = new
|
|
218
|
+
let app = new Topbit({debug: true})
|
|
260
219
|
|
|
261
220
|
app.post('/p', async c => {
|
|
262
221
|
//POST、PUT提交的数据保存到body,如果是表单则会自动解析为object,
|
|
263
222
|
//可以使用中间件处理各种数据。
|
|
264
|
-
c.
|
|
223
|
+
c.to(c.body)
|
|
265
224
|
});
|
|
266
225
|
|
|
267
226
|
app.run(2019)
|
|
@@ -296,20 +255,20 @@ app.run(2019)
|
|
|
296
255
|
|
|
297
256
|
body解析模块本质上是一个中间件,这样设计的目的就是为了方便扩展和替换。
|
|
298
257
|
|
|
299
|
-
##
|
|
258
|
+
## to函数返回数据
|
|
300
259
|
|
|
301
|
-
|
|
260
|
+
to函数就是对c.data的包装,其实就是设置了c.data的值。另外还有两个别名的函数:ok、oo。根据场景可以自由选择。
|
|
302
261
|
|
|
303
262
|
``` JavaScript
|
|
304
263
|
|
|
305
264
|
app.get('/', async c => {
|
|
306
|
-
c.
|
|
265
|
+
c.to('success')
|
|
307
266
|
})
|
|
308
267
|
|
|
309
268
|
app.get('/randerr', async c => {
|
|
310
269
|
let n = parseInt(Math.random() * 10)
|
|
311
270
|
if (n >= 5) {
|
|
312
|
-
c.
|
|
271
|
+
c.ok('success')
|
|
313
272
|
} else {
|
|
314
273
|
//返回404状态码
|
|
315
274
|
/*
|
|
@@ -317,7 +276,7 @@ app.get('/randerr', async c => {
|
|
|
317
276
|
c.status(404).data = 'not found'
|
|
318
277
|
*/
|
|
319
278
|
//你可以在v22.4.6以上的版本使用链式调用。
|
|
320
|
-
c.status(404).
|
|
279
|
+
c.status(404).oo('not found')
|
|
321
280
|
}
|
|
322
281
|
})
|
|
323
282
|
|
|
@@ -327,7 +286,7 @@ app.run(1234)
|
|
|
327
286
|
|
|
328
287
|
## 链式调用
|
|
329
288
|
|
|
330
|
-
|
|
289
|
+
可以对setHeader、status、sendHeader使用链式调用。
|
|
331
290
|
|
|
332
291
|
```javascript
|
|
333
292
|
|
|
@@ -336,13 +295,12 @@ app.get('/', async c => {
|
|
|
336
295
|
c.setHeader('content-type', 'text/plain; charset=utf-8')
|
|
337
296
|
.setHeader('x-server', 'nodejs server')
|
|
338
297
|
.status(200)
|
|
339
|
-
.
|
|
298
|
+
.to(`${Date.now()} Math.random()}`)
|
|
340
299
|
|
|
341
300
|
})
|
|
342
301
|
|
|
343
302
|
```
|
|
344
303
|
|
|
345
|
-
|
|
346
304
|
## 路由参数
|
|
347
305
|
|
|
348
306
|
``` JavaScript
|
|
@@ -350,7 +308,7 @@ app.get('/:name/:id', async c => {
|
|
|
350
308
|
//使用:表示路由参数,请求参数被解析到c.param
|
|
351
309
|
let username = c.param.name;
|
|
352
310
|
let uid = c.param.id;
|
|
353
|
-
c.
|
|
311
|
+
c.to(`${username} ${id}`)
|
|
354
312
|
})
|
|
355
313
|
|
|
356
314
|
app.run(8000)
|
|
@@ -366,7 +324,7 @@ app.get('/static/*', async c => {
|
|
|
366
324
|
//*表示的任意路径解析到c.param.starPath
|
|
367
325
|
let spath = c.param.starPath
|
|
368
326
|
|
|
369
|
-
c.
|
|
327
|
+
c.to(spath)
|
|
370
328
|
})
|
|
371
329
|
|
|
372
330
|
```
|
|
@@ -377,7 +335,7 @@ app.get('/static/*', async c => {
|
|
|
377
335
|
|
|
378
336
|
----
|
|
379
337
|
|
|
380
|
-
|
|
338
|
+
路由查找过程,主要是对带参数路由和带 * 的路由进行了严格的顺序控制,而不是按照添加顺序进行匹配。
|
|
381
339
|
|
|
382
340
|
采用之前的版本开发的应用仍然不受影响,不存在兼容性问题。更严格的顺序减少了冲突的可能。
|
|
383
341
|
|
|
@@ -409,13 +367,13 @@ app.get('/static/*', async c => {
|
|
|
409
367
|
|
|
410
368
|
你可以使用app.middleware指定中间件并使用返回的group方法添加分组路由,或者直接使用app.group分组添加路由。
|
|
411
369
|
|
|
412
|
-
**
|
|
370
|
+
**topbit.prototype.middleware(mids, options=null)**
|
|
413
371
|
|
|
414
372
|
- mids是一个数组,每个元素是一个中间件函数或一个数组,数组的第一个元素是中间件,第二个是添加中间件的选项。
|
|
415
373
|
|
|
416
374
|
- options默认为null,传递一个object为针对所有mids的选项,比如{pre: true}
|
|
417
375
|
|
|
418
|
-
**
|
|
376
|
+
**topbit.prototype.group(group_name, callback, prefix=true)**
|
|
419
377
|
|
|
420
378
|
- group_name 是一个字符串,表示路由分组的名称,如果是合法的路径,也作为路由的前缀。
|
|
421
379
|
|
|
@@ -427,16 +385,16 @@ app.get('/static/*', async c => {
|
|
|
427
385
|
```javascript
|
|
428
386
|
'use strict'
|
|
429
387
|
|
|
430
|
-
const
|
|
388
|
+
const Topbit = require('topbit')
|
|
431
389
|
|
|
432
|
-
const app = new
|
|
390
|
+
const app = new Topbit({
|
|
433
391
|
debug: true
|
|
434
392
|
})
|
|
435
393
|
|
|
436
394
|
//中间件函数
|
|
437
395
|
let mid_timing = async (c, next) => {
|
|
438
396
|
console.time('request')
|
|
439
|
-
await next()
|
|
397
|
+
await next(c)
|
|
440
398
|
console.timeEnd('request')
|
|
441
399
|
}
|
|
442
400
|
|
|
@@ -444,11 +402,11 @@ let mid_timing = async (c, next) => {
|
|
|
444
402
|
// /api同时会添加到路由的前缀。
|
|
445
403
|
app.group('/api', route => {
|
|
446
404
|
route.get('/test', async c => {
|
|
447
|
-
c.
|
|
405
|
+
c.to('api test')
|
|
448
406
|
})
|
|
449
407
|
|
|
450
408
|
route.get('/:name', async c => {
|
|
451
|
-
c.
|
|
409
|
+
c.to(c.param)
|
|
452
410
|
})
|
|
453
411
|
})
|
|
454
412
|
|
|
@@ -456,11 +414,11 @@ app.group('/api', route => {
|
|
|
456
414
|
app.use(
|
|
457
415
|
async (c, next) => {
|
|
458
416
|
console.log(c.method, c.headers)
|
|
459
|
-
await next()
|
|
417
|
+
await next(c)
|
|
460
418
|
}, {group: '/sub'}
|
|
461
419
|
).group('/sub', route => {
|
|
462
420
|
route.get('/:id', async c => {
|
|
463
|
-
c.
|
|
421
|
+
c.to(c.param.id)
|
|
464
422
|
})
|
|
465
423
|
})
|
|
466
424
|
|
|
@@ -468,7 +426,7 @@ app.use(
|
|
|
468
426
|
app.group('测试', route => {
|
|
469
427
|
route.get('/test', async c => {
|
|
470
428
|
console.log(c.group, c.name)
|
|
471
|
-
c.
|
|
429
|
+
c.to('test ok')
|
|
472
430
|
}, 'test')
|
|
473
431
|
})
|
|
474
432
|
|
|
@@ -483,24 +441,24 @@ app.run(1234)
|
|
|
483
441
|
```javascript
|
|
484
442
|
'use strict'
|
|
485
443
|
|
|
486
|
-
const
|
|
444
|
+
const Topbit = require('topbit')
|
|
487
445
|
//导入ToFile扩展
|
|
488
|
-
const {ToFile} = require('
|
|
446
|
+
const {ToFile} = require('topbit-toolkit')
|
|
489
447
|
|
|
490
|
-
const app = new
|
|
448
|
+
const app = new Topbit({
|
|
491
449
|
debug: true
|
|
492
450
|
})
|
|
493
451
|
|
|
494
452
|
//中间件函数
|
|
495
453
|
let mid_timing = async (c, next) => {
|
|
496
454
|
console.time('request')
|
|
497
|
-
await next()
|
|
455
|
+
await next(c)
|
|
498
456
|
console.timeEnd('request')
|
|
499
457
|
}
|
|
500
458
|
|
|
501
459
|
let sub_mid_test = async (c, next) => {
|
|
502
460
|
console.log('mid test start')
|
|
503
|
-
await next()
|
|
461
|
+
await next(c)
|
|
504
462
|
console.log('mid test end')
|
|
505
463
|
}
|
|
506
464
|
|
|
@@ -516,18 +474,18 @@ app.middleware([
|
|
|
516
474
|
])
|
|
517
475
|
.group('/api', route => {
|
|
518
476
|
route.get('/test', async c => {
|
|
519
|
-
c.
|
|
477
|
+
c.to('api test')
|
|
520
478
|
})
|
|
521
479
|
|
|
522
480
|
route.get('/:name', async c => {
|
|
523
|
-
c.
|
|
481
|
+
c.to(c.param)
|
|
524
482
|
})
|
|
525
483
|
|
|
526
484
|
//子分组 /sub启用中间件sub_mid_test,同时,子分组会启用上一层的所有中间件。
|
|
527
485
|
route.middleware([sub_mid_test])
|
|
528
486
|
.group('/sub', sub => {
|
|
529
487
|
sub.get('/:key', async c => {
|
|
530
|
-
c.
|
|
488
|
+
c.to(c.param)
|
|
531
489
|
})
|
|
532
490
|
})
|
|
533
491
|
})
|
|
@@ -538,35 +496,35 @@ app.run(1234)
|
|
|
538
496
|
|
|
539
497
|
分组支持嵌套调用,但是层级不能超过9。通常超过3层的嵌套分组就是有问题的,需要重新设计。
|
|
540
498
|
|
|
541
|
-
**这个功能,不如
|
|
499
|
+
**这个功能,不如TopbitLoader扩展的自动加载机制方便易用,但是在实际情况中。有各种各样的需求。并且有时候不得不利用单文件做服务,同时还要能够兼顾框架本身的路由和中间件分组的优势,还要能够方便的编写逻辑明确,结构清晰的代码,因此middleware、group的接口功能可以方便处理,并且若不习惯TopbitLoader的MCM模式(Middleware - Controller - Model,类似MVC的模式),使用这个方式也可以很好的组合其他模块代码。**
|
|
542
500
|
|
|
543
|
-
以上路由指派分组的功能是非侵入式的,它不会影响已有代码,也不会和
|
|
501
|
+
以上路由指派分组的功能是非侵入式的,它不会影响已有代码,也不会和TopbitLoader冲突。
|
|
544
502
|
|
|
545
503
|
**!! 复杂的路由处理函数应该放在单独的模块中,使用一个统一的自动化加载函数来完成。**
|
|
546
504
|
|
|
547
|
-
|
|
505
|
+
支持使用返回值进行添加,也可以不必传递回调函数:
|
|
548
506
|
|
|
549
507
|
```javascript
|
|
550
508
|
'use strict'
|
|
551
509
|
|
|
552
|
-
const
|
|
510
|
+
const Topbit = require('topbit')
|
|
553
511
|
//导入ToFile扩展
|
|
554
|
-
const {ToFile} = require('
|
|
512
|
+
const {ToFile} = require('topbit-toolkit')
|
|
555
513
|
|
|
556
|
-
const app = new
|
|
514
|
+
const app = new Topbit({
|
|
557
515
|
debug: true
|
|
558
516
|
})
|
|
559
517
|
|
|
560
518
|
//中间件函数
|
|
561
519
|
let mid_timing = async (c, next) => {
|
|
562
520
|
console.time('request')
|
|
563
|
-
await next()
|
|
521
|
+
await next(c)
|
|
564
522
|
console.timeEnd('request')
|
|
565
523
|
}
|
|
566
524
|
|
|
567
525
|
let sub_mid_test = async (c, next) => {
|
|
568
526
|
console.log('mid test start')
|
|
569
|
-
await next()
|
|
527
|
+
await next(c)
|
|
570
528
|
console.log('mid test end')
|
|
571
529
|
}
|
|
572
530
|
|
|
@@ -580,18 +538,18 @@ let route = app.middleware([
|
|
|
580
538
|
.group('/api')
|
|
581
539
|
|
|
582
540
|
route.get('/test', async c => {
|
|
583
|
-
c.
|
|
541
|
+
c.to('api test')
|
|
584
542
|
})
|
|
585
543
|
|
|
586
544
|
route.get('/:name', async c => {
|
|
587
|
-
c.
|
|
545
|
+
c.to(c.param)
|
|
588
546
|
})
|
|
589
547
|
|
|
590
548
|
//子分组 /sub启用中间件sub_mid_test,同时,子分组会启用上一层的所有中间件。
|
|
591
549
|
route.middleware([sub_mid_test])
|
|
592
550
|
.group('/sub', sub => {
|
|
593
551
|
sub.get('/:key', async c => {
|
|
594
|
-
c.
|
|
552
|
+
c.to(c.param)
|
|
595
553
|
})
|
|
596
554
|
})
|
|
597
555
|
|
|
@@ -609,9 +567,9 @@ app.run(1234)
|
|
|
609
567
|
``` JavaScript
|
|
610
568
|
'use strict'
|
|
611
569
|
|
|
612
|
-
const
|
|
570
|
+
const Topbit = require('topbit')
|
|
613
571
|
|
|
614
|
-
const app = new
|
|
572
|
+
const app = new Topbit()
|
|
615
573
|
|
|
616
574
|
app.post('/upload', async c => {
|
|
617
575
|
|
|
@@ -625,9 +583,9 @@ app.post('/upload', async c => {
|
|
|
625
583
|
let fname = c.ext.makeName(f.filename)
|
|
626
584
|
|
|
627
585
|
try {
|
|
628
|
-
c.
|
|
586
|
+
c.to(await c.moveFile(f, fname))
|
|
629
587
|
} catch (err) {
|
|
630
|
-
c.status(500).
|
|
588
|
+
c.status(500).to(err.message)
|
|
631
589
|
}
|
|
632
590
|
|
|
633
591
|
}, 'upload-image'); //给路由命名为upload-image,可以在c.name中获取。
|
|
@@ -687,9 +645,9 @@ c.getFile就是通过名称索引,默认索引值是0,如果是一个小于0
|
|
|
687
645
|
```javascript
|
|
688
646
|
'use strict'
|
|
689
647
|
|
|
690
|
-
const
|
|
648
|
+
const Topbit = require('topbit')
|
|
691
649
|
|
|
692
|
-
const app = new
|
|
650
|
+
const app = new Topbit({
|
|
693
651
|
//允许POST或PUT请求提交的数据量最大值为将近20M。
|
|
694
652
|
//单位为字节。
|
|
695
653
|
maxBody: 20000000
|
|
@@ -721,7 +679,7 @@ app.run(1234)
|
|
|
721
679
|
*/
|
|
722
680
|
app.add(async (c, next) => {
|
|
723
681
|
console.log('before');
|
|
724
|
-
await next();
|
|
682
|
+
await next(c);
|
|
725
683
|
console.log('after');
|
|
726
684
|
}, {method: 'POST', group: '/api'});
|
|
727
685
|
|
|
@@ -735,7 +693,7 @@ app.add(async (c, next) => {
|
|
|
735
693
|
//先执行
|
|
736
694
|
app.use(async (c, next) => {
|
|
737
695
|
let start_time = Date.now()
|
|
738
|
-
await next()
|
|
696
|
+
await next(c)
|
|
739
697
|
let end_time = Date.now()
|
|
740
698
|
console.log(end_time - start_time)
|
|
741
699
|
})
|
|
@@ -743,18 +701,16 @@ app.use(async (c, next) => {
|
|
|
743
701
|
//后执行
|
|
744
702
|
app.use(async (c, next) => {
|
|
745
703
|
console.log(c.method, c.path)
|
|
746
|
-
await next()
|
|
704
|
+
await next(c)
|
|
747
705
|
})
|
|
748
706
|
|
|
749
707
|
//use可以级联: app.use(m1).use(m2)
|
|
750
|
-
//在21.5.4版本以后,不过这个功能其实根本不重要
|
|
751
|
-
//因为有titbit-loader扩展,实现的功能要强大的多。
|
|
752
708
|
|
|
753
709
|
```
|
|
754
710
|
|
|
755
|
-
##
|
|
711
|
+
## topbit完整的流程图示
|
|
756
712
|
|
|
757
|
-

|
|
758
714
|
|
|
759
715
|
|
|
760
716
|
> **需要知道的是,其实在内部,body数据接收和解析也都是中间件,只是刻意安排了顺序,分出了pre和use接口。**
|
|
@@ -797,7 +753,7 @@ app.use(proxy, {
|
|
|
797
753
|
let setbodysize = async (c, next) => {
|
|
798
754
|
//设定body最大接收数据为~10k。
|
|
799
755
|
c.maxBody = 10000;
|
|
800
|
-
await next();
|
|
756
|
+
await next(c);
|
|
801
757
|
};
|
|
802
758
|
|
|
803
759
|
//等效于app.pre(setbodysize);
|
|
@@ -805,7 +761,7 @@ app.use(setbodysize, {pre: true});
|
|
|
805
761
|
|
|
806
762
|
```
|
|
807
763
|
|
|
808
|
-
使用pre可以进行更复杂的处理,并且可以拦截并不执行下一层,比如
|
|
764
|
+
使用pre可以进行更复杂的处理,并且可以拦截并不执行下一层,比如topbit-toolkit扩展的proxy模块利用这个特性直接实现了高性能的代理服务,但是仅仅作为框架的一个中间件。其主要操作就是在这一层,直接设置了request的data事件来接收数据,并作其他处理,之后直接返回。
|
|
809
765
|
|
|
810
766
|
**根据不同的请求类型动态限制请求体大小**
|
|
811
767
|
|
|
@@ -813,7 +769,7 @@ app.use(setbodysize, {pre: true});
|
|
|
813
769
|
|
|
814
770
|
```javascript
|
|
815
771
|
|
|
816
|
-
const app = new
|
|
772
|
+
const app = new Topbit({
|
|
817
773
|
//默认最大请求体 ~10M 限制。
|
|
818
774
|
maxBody: 10000000
|
|
819
775
|
})
|
|
@@ -833,7 +789,7 @@ app.pre(async (c, next) => {
|
|
|
833
789
|
c.maxBody = 10000
|
|
834
790
|
}
|
|
835
791
|
|
|
836
|
-
await next()
|
|
792
|
+
await next(c)
|
|
837
793
|
|
|
838
794
|
}, {method: ['POST', 'PUT']})
|
|
839
795
|
|
|
@@ -842,7 +798,7 @@ app.pre(async (c, next) => {
|
|
|
842
798
|
|
|
843
799
|
这些参数若同时出现在文件里会显得很复杂,维护也不方便,但是功能很强,所以若要交给程序自动完成则可以大大简化编码的工作。
|
|
844
800
|
|
|
845
|
-
**完整的项目结构搭建,请配合使用
|
|
801
|
+
**完整的项目结构搭建,请配合使用topbit-loader,此扩展完成了路由、模型的自动加载和中间件自动编排。<a target=_blank href="https://gitee.com/daoio/topbit-loader">topbit-loader</a>**
|
|
846
802
|
|
|
847
803
|
|
|
848
804
|
## HTTPS
|
|
@@ -850,10 +806,10 @@ app.pre(async (c, next) => {
|
|
|
850
806
|
```javascript
|
|
851
807
|
'use strict'
|
|
852
808
|
|
|
853
|
-
const
|
|
809
|
+
const Topbit = require('topbit')
|
|
854
810
|
|
|
855
811
|
//只需要传递证书和密钥文件所在路径
|
|
856
|
-
const app = new
|
|
812
|
+
const app = new Topbit({
|
|
857
813
|
// './xxx.pem'文件也可以
|
|
858
814
|
cert: './xxx.cert',
|
|
859
815
|
key: './xxx.key'
|
|
@@ -870,10 +826,10 @@ app.run(1234)
|
|
|
870
826
|
```javascript
|
|
871
827
|
'use strict'
|
|
872
828
|
|
|
873
|
-
const
|
|
829
|
+
const Topbit = require('topbit')
|
|
874
830
|
|
|
875
831
|
//只需要传递证书和密钥文件所在路径
|
|
876
|
-
const app = new
|
|
832
|
+
const app = new Topbit({
|
|
877
833
|
cert: './xxx.cert',
|
|
878
834
|
key: './xxx.key',
|
|
879
835
|
//启用http2并允许http1,会自动启用兼容模式
|
|
@@ -1067,13 +1023,13 @@ app.run(1234)
|
|
|
1067
1023
|
| isUpload() | 是否为上传文件请求,此时就是检测消息头content-type是否为multipart/form-data格式。 |
|
|
1068
1024
|
| name | 路由名称,默认为空字符串。 |
|
|
1069
1025
|
| group | 路由分组,默认为空字符串。 |
|
|
1070
|
-
|
|
|
1071
|
-
|
|
|
1026
|
+
| res | HTTP/1.1协议,指向response,HTTP/2 指向stream。 |
|
|
1027
|
+
| req | HTTP/1.1 就是http模块request事件的参数IncomingMessage对象,HTTP/2 指向stream对象。 |
|
|
1072
1028
|
| box | 默认为空对象,可以添加任何属性值,用来动态传递给下一层组件需要使用的信息。 |
|
|
1073
1029
|
| service | 用于依赖注入的对象,指向app.service。 |
|
|
1074
|
-
| data | 保存最后要返回到客户端的数据,给data赋值即可,或者直接使用ctx.
|
|
1030
|
+
| data | 保存最后要返回到客户端的数据,给data赋值即可,或者直接使用ctx.to函数。在v24.x版本以前,是ctx\.res\.body。 |
|
|
1075
1031
|
| ext | 提供了一些助手函数,具体参考wiki。 |
|
|
1076
|
-
|
|
|
1032
|
+
| to(data) | 函数,用来设置ctx.data的数据。 |
|
|
1077
1033
|
| write(data) | 直接写入数据到客户端。 |
|
|
1078
1034
|
| moveFile(file:object, target_filepath:string) | 函数,用来移动上传的文件到指定路径。 |
|
|
1079
1035
|
| status() | 函数,设置状态码。 |
|
|
@@ -1090,7 +1046,7 @@ app.run(1234)
|
|
|
1090
1046
|
| pipeText(filepath) | 以text类型流式响应文件数据。 |
|
|
1091
1047
|
| pipeHtml(filepath) | 以html类型流式响应文件数据。 |
|
|
1092
1048
|
|
|
1093
|
-
注意:
|
|
1049
|
+
注意:to函数只是设置ctx.data属性的值,在最后才会返回数据。和直接进行ctx.data赋值没有区别,只是因为函数调用如果出错会更快发现问题,而设置属性值写错了就是添加了一个新的属性,不会报错但是请求不会返回正确的数据。
|
|
1094
1050
|
|
|
1095
1051
|
## 依赖注入
|
|
1096
1052
|
|
|
@@ -1100,9 +1056,9 @@ app.run(1234)
|
|
|
1100
1056
|
|
|
1101
1057
|
'use strict';
|
|
1102
1058
|
|
|
1103
|
-
const
|
|
1059
|
+
const Topbit = require('topbit');
|
|
1104
1060
|
|
|
1105
|
-
|
|
1061
|
+
let app = new Topbit({
|
|
1106
1062
|
debug: true
|
|
1107
1063
|
});
|
|
1108
1064
|
|
|
@@ -1117,7 +1073,7 @@ app.addService('data', {
|
|
|
1117
1073
|
这可能看不出什么作用,毕竟在一个文件中,直接访问变量都可以,如果要做模块分离,就变得非常重要了。
|
|
1118
1074
|
*/
|
|
1119
1075
|
app.get('/info', async c => {
|
|
1120
|
-
c.
|
|
1076
|
+
c.to({
|
|
1121
1077
|
name : c.service.name,
|
|
1122
1078
|
data : c.service.data
|
|
1123
1079
|
})
|
|
@@ -1135,8 +1091,8 @@ app.run(1234)
|
|
|
1135
1091
|
|
|
1136
1092
|
```javascript
|
|
1137
1093
|
'use strict'
|
|
1138
|
-
const
|
|
1139
|
-
const app = new
|
|
1094
|
+
const Topbit = require('topbit')
|
|
1095
|
+
const app = new Topbit({
|
|
1140
1096
|
debug: true
|
|
1141
1097
|
})
|
|
1142
1098
|
|
|
@@ -1156,7 +1112,7 @@ app.run(1234)
|
|
|
1156
1112
|
|
|
1157
1113
|
## app.isMaster和app.isWorker
|
|
1158
1114
|
|
|
1159
|
-
Node.js在v16.x版本开始,cluster模块推荐使用isPrimary代替isMaster,不过isMaster仍然是可用的,在
|
|
1115
|
+
Node.js在v16.x版本开始,cluster模块推荐使用isPrimary代替isMaster,不过isMaster仍然是可用的,在topbit初始化app实例之后,app上有两个getter属性:isMaster和isWorker。作用和cluster上的属性一致,其目的在于:
|
|
1160
1116
|
|
|
1161
1117
|
- 在代码中不必再次编写const cluster = require('cluster')。
|
|
1162
1118
|
|
|
@@ -1203,9 +1159,9 @@ app.daemon(1234, 'localhost', 3)
|
|
|
1203
1159
|
|
|
1204
1160
|
``` JavaScript
|
|
1205
1161
|
|
|
1206
|
-
const
|
|
1162
|
+
const Topbit = require('topbit')
|
|
1207
1163
|
|
|
1208
|
-
const app = new
|
|
1164
|
+
const app = new Topbit({
|
|
1209
1165
|
debug: true,
|
|
1210
1166
|
//全局日志开启
|
|
1211
1167
|
globalLog: true,
|
|
@@ -1214,10 +1170,10 @@ const app = new titbit({
|
|
|
1214
1170
|
logType: 'file'
|
|
1215
1171
|
|
|
1216
1172
|
//返回状态码为2xx或者3xx
|
|
1217
|
-
logFile : '/tmp/
|
|
1173
|
+
logFile : '/tmp/topbit.log',
|
|
1218
1174
|
|
|
1219
1175
|
//错误的日志输出文件,返回状态码4xx或者5xx
|
|
1220
|
-
errorLogFile: '/tmp/
|
|
1176
|
+
errorLogFile: '/tmp/topbit-error.log',
|
|
1221
1177
|
|
|
1222
1178
|
//自定义处理函数,此时logFile和errorLogFile会失效。
|
|
1223
1179
|
//接收参数为(worker, message)
|
|
@@ -1254,10 +1210,10 @@ app.daemon(1234, 3)
|
|
|
1254
1210
|
|
|
1255
1211
|
``` JavaScript
|
|
1256
1212
|
|
|
1257
|
-
const
|
|
1213
|
+
const Topbit = require('topbit')
|
|
1258
1214
|
const cluster = require('cluster')
|
|
1259
1215
|
|
|
1260
|
-
const app = new
|
|
1216
|
+
const app = new Topbit({
|
|
1261
1217
|
debug: true,
|
|
1262
1218
|
loadInfoFile: '/tmp/loadinfo.log'
|
|
1263
1219
|
})
|
|
@@ -1265,7 +1221,7 @@ const app = new titbit({
|
|
|
1265
1221
|
if (cluster.isMaster) {
|
|
1266
1222
|
app.setMsgEvent('test-msg', (worker, msg, handle) => {
|
|
1267
1223
|
//子进程中会通过message事件收到消息
|
|
1268
|
-
worker.
|
|
1224
|
+
worker.to({
|
|
1269
1225
|
id : worker.id,
|
|
1270
1226
|
data : 'ok'
|
|
1271
1227
|
})
|
|
@@ -1273,13 +1229,13 @@ if (cluster.isMaster) {
|
|
|
1273
1229
|
console.log(msg)
|
|
1274
1230
|
})
|
|
1275
1231
|
} else {
|
|
1276
|
-
//接收worker.
|
|
1232
|
+
//接收worker.to发送的消息
|
|
1277
1233
|
process.on('message', msg => {
|
|
1278
1234
|
console.log(msg)
|
|
1279
1235
|
})
|
|
1280
1236
|
|
|
1281
1237
|
setIneterval(() => {
|
|
1282
|
-
process.
|
|
1238
|
+
process.to({
|
|
1283
1239
|
type : 'test-msg',
|
|
1284
1240
|
pid : process.pid,
|
|
1285
1241
|
time : (new Date()).toLocaleString()
|
|
@@ -1292,15 +1248,15 @@ if (cluster.isMaster) {
|
|
|
1292
1248
|
|
|
1293
1249
|
比较麻烦的地方在于,worker进程发送消息比较复杂,在22.4.0版本开始,提供了一个send方法用于快速发送消息。只有在worker进程中才会发送给master进程,所以不必额外进行worker进程检测。
|
|
1294
1250
|
|
|
1295
|
-
## app.
|
|
1251
|
+
## app.to 和 app.workerMsg
|
|
1296
1252
|
|
|
1297
1253
|
现在让我们来改写上面代码的worker进程发送消息的部分:
|
|
1298
1254
|
|
|
1299
1255
|
```javascript
|
|
1300
1256
|
|
|
1301
|
-
const
|
|
1257
|
+
const Topbit = require('topbit')
|
|
1302
1258
|
|
|
1303
|
-
const app = new
|
|
1259
|
+
const app = new Topbit({
|
|
1304
1260
|
debug: true,
|
|
1305
1261
|
loadInfoFile: '/tmp/loadinfo.log'
|
|
1306
1262
|
})
|
|
@@ -1308,7 +1264,7 @@ const app = new titbit({
|
|
|
1308
1264
|
//master进程注册消息事件类型,worker进程不会执行。
|
|
1309
1265
|
app.setMsgEvent('test-msg', (worker, msg, handle) => {
|
|
1310
1266
|
//子进程中会通过message事件收到消息
|
|
1311
|
-
worker.
|
|
1267
|
+
worker.to({
|
|
1312
1268
|
id : worker.id,
|
|
1313
1269
|
data : 'ok'
|
|
1314
1270
|
})
|
|
@@ -1325,7 +1281,7 @@ cluster.isWorker
|
|
|
1325
1281
|
&&
|
|
1326
1282
|
setInterval(() => {
|
|
1327
1283
|
//只有worker会执行。
|
|
1328
|
-
app.
|
|
1284
|
+
app.to('test-msg', {
|
|
1329
1285
|
pid: process.pid,
|
|
1330
1286
|
time: (new Date).toLocaleString()
|
|
1331
1287
|
})
|
|
@@ -1375,14 +1331,14 @@ app.daemon(1234, 2)
|
|
|
1375
1331
|
```javascript
|
|
1376
1332
|
'use strict';
|
|
1377
1333
|
|
|
1378
|
-
const
|
|
1334
|
+
const Topbit = require('topbit');
|
|
1379
1335
|
|
|
1380
1336
|
setTimeout(() => {
|
|
1381
1337
|
//在定时器的循环里抛出异常
|
|
1382
1338
|
throw new Error(`test error`)
|
|
1383
1339
|
}, 2000);
|
|
1384
1340
|
|
|
1385
|
-
const app = new
|
|
1341
|
+
const app = new Topbit({
|
|
1386
1342
|
//调试模式,输出错误信息。
|
|
1387
1343
|
debug: true,
|
|
1388
1344
|
//开启strong模式
|
|
@@ -1404,7 +1360,7 @@ app.run(1234);
|
|
|
1404
1360
|
```javascript
|
|
1405
1361
|
|
|
1406
1362
|
//核心代码示例
|
|
1407
|
-
const app = new
|
|
1363
|
+
const app = new Topbit({
|
|
1408
1364
|
//调试模式,输出错误信息。
|
|
1409
1365
|
debug: true,
|
|
1410
1366
|
//开启strong模式
|
|
@@ -1435,16 +1391,16 @@ const app = new titbit({
|
|
|
1435
1391
|
```javascript
|
|
1436
1392
|
'use strict'
|
|
1437
1393
|
|
|
1438
|
-
const
|
|
1394
|
+
const Topbit = require('topbit')
|
|
1439
1395
|
const http = require('node:http')
|
|
1440
1396
|
const https = require('https')
|
|
1441
1397
|
|
|
1442
|
-
const app = new
|
|
1398
|
+
const app = new Topbit({
|
|
1443
1399
|
//启用调试
|
|
1444
1400
|
debug: true,
|
|
1445
1401
|
})
|
|
1446
1402
|
|
|
1447
|
-
//以下都是http/1.1的服务,若要同时支持http2,需要启用http2服务并兼容http1,若有需要请使用
|
|
1403
|
+
//以下都是http/1.1的服务,若要同时支持http2,需要启用http2服务并兼容http1,若有需要请使用topbit-httpc扩展。
|
|
1448
1404
|
|
|
1449
1405
|
//这种情况下,你需要自己设定相关事件的监听处理。
|
|
1450
1406
|
|
|
@@ -1460,14 +1416,14 @@ https_server.listen(2026)
|
|
|
1460
1416
|
|
|
1461
1417
|
## 请求限流
|
|
1462
1418
|
|
|
1463
|
-
框架层面提供的限流是基于IP地址的计算和过滤,避免同一个IP地址密集的发送请求。若使用HTTP/2协议,则需要配合使用
|
|
1419
|
+
框架层面提供的限流是基于IP地址的计算和过滤,避免同一个IP地址密集的发送请求。若使用HTTP/2协议,则需要配合使用topbit-toolkit扩展的http2limit模块。
|
|
1464
1420
|
|
|
1465
1421
|
```javascript
|
|
1466
1422
|
'use strict';
|
|
1467
1423
|
|
|
1468
|
-
const
|
|
1424
|
+
const Topbit = require('topbit')
|
|
1469
1425
|
|
|
1470
|
-
const app = new
|
|
1426
|
+
const app = new Topbit({
|
|
1471
1427
|
debug : true,
|
|
1472
1428
|
//启用请求限制
|
|
1473
1429
|
useLimit: true,
|
|
@@ -1501,7 +1457,7 @@ const app = new Titbit({
|
|
|
1501
1457
|
|
|
1502
1458
|
|
|
1503
1459
|
app.get('/', async ctx => {
|
|
1504
|
-
ctx.
|
|
1460
|
+
ctx.to('ok')
|
|
1505
1461
|
})
|
|
1506
1462
|
|
|
1507
1463
|
//使用3个worker进程处理请求,每个都支持单位时间内请求6次
|
|
@@ -1512,7 +1468,7 @@ app.daemon(1234, '0.0.0.0', 3)
|
|
|
1512
1468
|
|
|
1513
1469
|
## 其他
|
|
1514
1470
|
|
|
1515
|
-
-
|
|
1471
|
+
- topbit在运行后,会有一个最后包装的中间件做最终的处理,所以设置c.data的值就会返回数据,默认会检测一些简单的文本类型并自动设定content-type(text/plain,text/html,application/json)。注意这是在你没有设置content-type的情况下进行。
|
|
1516
1472
|
|
|
1517
1473
|
- 默认会限制url的最大长度,也会根据硬件情况设定一个最大内存使用率。
|
|
1518
1474
|
|
|
@@ -1529,9 +1485,9 @@ app.daemon(1234, '0.0.0.0', 3)
|
|
|
1529
1485
|
```
|
|
1530
1486
|
'use strict'
|
|
1531
1487
|
|
|
1532
|
-
const
|
|
1488
|
+
const Topbit = require('topbit');
|
|
1533
1489
|
|
|
1534
|
-
let app = new
|
|
1490
|
+
let app = new Topbit();
|
|
1535
1491
|
|
|
1536
1492
|
/*
|
|
1537
1493
|
以下操作可以通过选项memFactor控制,请参考上文的配置选项部分。
|
|
@@ -1549,7 +1505,7 @@ app.secure.diemem = 900_000_000;
|
|
|
1549
1505
|
app.secure.maxrss = 800_000_000;
|
|
1550
1506
|
|
|
1551
1507
|
app.get('/', async c => {
|
|
1552
|
-
c.
|
|
1508
|
+
c.to('ok');
|
|
1553
1509
|
})
|
|
1554
1510
|
|
|
1555
1511
|
app.daemon(8008, 2);
|
|
@@ -1559,4 +1515,3 @@ app.daemon(8008, 2);
|
|
|
1559
1515
|
**注意,这需要你开启loadMonitor选项,这是默认开启的,除非你设置为false**
|
|
1560
1516
|
|
|
1561
1517
|
在服务始化时,会根据系统的可用内存来进行自动的设置,除非你必须要自己控制,否则最好是使用默认的配置。
|
|
1562
|
-
|