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/src/http1.js ADDED
@@ -0,0 +1,336 @@
1
+ 'use strict';
2
+
3
+ const http = require('node:http');
4
+ const https = require('node:https');
5
+ const fs = require('node:fs');
6
+ const process = require('node:process');
7
+ const logger = require('./logger.js');
8
+ const {fpurl} = require('./fastParseUrl.js');
9
+ const Context = require('./context1.js');
10
+ const ctxpool = require('./ctxpool.js');
11
+ const checkHeaderLimit = require('./headerLimit.js');
12
+ const sendmsg = require('./sendmsg.js');
13
+
14
+ /**
15
+ * http1会对消息头进行限制,解析时会检测最大限制。
16
+ */
17
+
18
+ class Http1 {
19
+ constructor(options = {}) {
20
+ this.config = options.config;
21
+ this.router = options.router;
22
+ this.midware = options.midware;
23
+ this.events = options.events;
24
+ this.service = options.service;
25
+ this.isWorker = options.isWorker;
26
+
27
+ this.logger = logger;
28
+ ctxpool.max = this.config.maxpool;
29
+
30
+ this.ctxpool = ctxpool;
31
+ this.Context = Context;
32
+ this.fpurl = fpurl;
33
+ this.host = '';
34
+ }
35
+
36
+ requestError(err, handle, headers) {
37
+ this.config.errorHandle(err, '--ERR-REQUEST--');
38
+
39
+ if (!handle.destroyed) {
40
+ handle.destroy();
41
+ }
42
+ }
43
+
44
+ /**
45
+ * request事件的回调函数。
46
+ * @param {req} http.IncomingMessage
47
+ * @param {res} http.ServerResponse
48
+ */
49
+ onRequest() {
50
+ let self = this;
51
+ let protocol = self.config.https ? 'https' : 'http';
52
+
53
+ let callback = (req, res) => {
54
+
55
+ req.on('error', (err) => {
56
+ self.requestError(err, req, req.headers);
57
+ });
58
+
59
+ res.on('error', (err) => {
60
+ self.requestError(err, res, req.headers);
61
+ });
62
+
63
+ let remote_ip = req.socket.remoteAddress || '';
64
+
65
+ if (req.url.length > self.config.maxUrlLength) {
66
+ req.url = req.url.substring(0, self.config.maxUrlLength);
67
+ }
68
+
69
+ if (self.config.globalLog) {
70
+
71
+ let real_ip = '-';
72
+ //req.headers是getter属性,首次获取会进行消息头解析。再次获取会直接从已存储的变量返回。
73
+ let reqHeaders = req.headers;
74
+
75
+ if (self.config.realIP) {
76
+ real_ip = reqHeaders['x-real-ip'] || reqHeaders['x-forwarded-for'] || '-'
77
+ }
78
+
79
+ res.on('finish', () => {
80
+ if (!req || !res || res.destroyed) {
81
+ return;
82
+ }
83
+
84
+ checkHeaderLimit(reqHeaders, 'host', 300);
85
+ checkHeaderLimit(reqHeaders, 'user-agent', 111);
86
+
87
+ self.logger({
88
+ method: req.method,
89
+ status: res.statusCode,
90
+ ip: remote_ip,
91
+ link: `${protocol}://${reqHeaders.host || self.host}${req.url}`,
92
+ agent: reqHeaders['user-agent'] || '-',
93
+ real_ip: real_ip
94
+ });
95
+
96
+ });
97
+ }
98
+
99
+ let urlobj = fpurl(req.url, self.config.autoDecodeQuery,
100
+ self.config.fastParseQuery,
101
+ self.config.maxQuery);
102
+
103
+ let rt = self.router.findRealPath(urlobj.path, req.method);
104
+ if (rt === null) {
105
+ res.statusCode = 404;
106
+ res.end(self.config.notFound, () => {
107
+ !req.destroyed && req.destroy();
108
+ });
109
+ return ;
110
+ }
111
+
112
+ let ctx = ctxpool.getctx () || new Context();
113
+
114
+ ctx.bodyLength = 0;
115
+ ctx.maxBody = self.config.maxBody;
116
+ ctx.service = self.service;
117
+
118
+ ctx.method = req.method;
119
+ ctx.headers = req.headers;
120
+ ctx.host = ctx.headers.host || self.host;
121
+ ctx.protocol = protocol;
122
+ ctx.ip = remote_ip;
123
+
124
+ ctx.port = req.socket.remotePort;
125
+ ctx.req = req;
126
+ ctx.res = res;
127
+
128
+ ctx.path = urlobj.path;
129
+ ctx.query = urlobj.query;
130
+ ctx.routepath = rt.key;
131
+ ctx.requestCall = rt.reqcall.reqCall;
132
+ ctx.name = rt.reqcall.name;
133
+ ctx.group = rt.reqcall.group;
134
+ ctx.param = rt.args;
135
+ rt = null;
136
+
137
+ return self.midware.run(ctx).finally(()=>{
138
+ ctxpool.free(ctx);
139
+ ctx = null;
140
+ });
141
+ };
142
+
143
+ return callback;
144
+ }
145
+
146
+ mid() {
147
+ let self = this;
148
+
149
+ let noBodyMethods = Object.create(null);
150
+
151
+ ['GET','OPTIONS','HEAD','TRACE'].forEach(a => {
152
+ noBodyMethods[a] = true;
153
+ });
154
+
155
+ return async (ctx, next) => {
156
+ let resolved = false;
157
+ let bodylength = 0;
158
+ let bodyBuffer;
159
+
160
+ await new Promise((rv, rj) => {
161
+ //客户端和服务端解析不会允许非法method
162
+ if ( noBodyMethods[ctx.method] ) {
163
+ //实际上这个回调函数不会执行,因为会立即触发end事件,此处可以保证非法的请求也可以提交数据。
164
+ ctx.req.on('data', data => {
165
+ ctx.res.statusCode = 400;
166
+ ctx.res.end(self.config.badRequest);
167
+ ctx.req.destroy();
168
+ });
169
+ } else {
170
+ let bigBodyEnd = false;
171
+ bodyBuffer = [];
172
+ ctx.req.on('data', data => {
173
+ bodylength += data.length;
174
+ if (bodylength > ctx.maxBody) {
175
+ if (bigBodyEnd) return;
176
+ bigBodyEnd = true;
177
+
178
+ bodyBuffer = null;
179
+ ctx.res.statusCode = 413;
180
+ ctx.res.end('', () => {
181
+ ctx.req.destroy();
182
+ });
183
+ return ;
184
+ }
185
+ bodyBuffer.push(data);
186
+ });
187
+ }
188
+
189
+ //若请求体太大,此时会进行destroy处理,触发close事件,但不会触发end。
190
+ //通过记录resolved状态避免重复调用rv。
191
+ ctx.req.on('close', () => {
192
+ (!resolved) && rv();
193
+ });
194
+
195
+ ctx.req.on('end',() => {
196
+ resolved = true;
197
+ rv();
198
+ });
199
+
200
+ });
201
+
202
+ if (!ctx.res.writable || ctx.res.writableEnded) {
203
+ return;
204
+ }
205
+
206
+ if (bodyBuffer && bodyBuffer.length > 0) {
207
+ ctx.bodyLength = bodylength;
208
+ ctx.rawBody = Buffer.concat(bodyBuffer, bodylength);
209
+ bodyBuffer = null;
210
+ }
211
+
212
+ await next(ctx);
213
+ };
214
+
215
+ }
216
+
217
+ /**
218
+ * 运行HTTP/1.1服务
219
+ * @param {number} port 端口号
220
+ * @param {string} host IP地址,可以是IPv4或IPv6
221
+ * 0.0.0.0 对应使用IPv6则是::
222
+ */
223
+ run(port, host) {
224
+ let self = this;
225
+ let serv = null;
226
+
227
+ if (this.config.https) {
228
+ try {
229
+ if (this.config.key && this.config.cert) {
230
+ this.config.server.key = fs.readFileSync(this.config.key);
231
+ this.config.server.cert = fs.readFileSync(this.config.cert);
232
+ }
233
+
234
+ serv = https.createServer(this.config.server, this.onRequest());
235
+
236
+ serv.on('tlsClientError', (err, tls) => {
237
+
238
+ self.config.errorHandle(err, '--ERR-TLS-CLIENT--');
239
+
240
+ if (!tls.destroyed) {
241
+ tls.destroy();
242
+ }
243
+
244
+ });
245
+
246
+ serv.on('secureConnection', (sock) => {
247
+ sock.on('error', err => {
248
+ self.config.errorHandle(err, '--ERR-CONNECTION--');
249
+ });
250
+ });
251
+
252
+ } catch (err) {
253
+ !this.isWorker && console.error(err);
254
+ sendmsg('_server-error', err.message, {autoExit: true, exitCode: 1});
255
+ }
256
+ } else {
257
+ serv = http.createServer(self.config.server, this.onRequest());
258
+ }
259
+
260
+ serv.on('clientError', (err, sock) => {
261
+ if (sock.destroyed) return;
262
+
263
+ self.config.errorHandle(err, '--ERR-CLIENT--');
264
+
265
+ if (err.code === 'ECONNRESET' || !sock.writable) return;
266
+
267
+ if (!sock.destroyed) {
268
+ if (!sock.writableEnded) {
269
+ sock.end('HTTP/1.1 400 Bad request\r\n', () => {
270
+ sock.destroy();
271
+ });
272
+ } else {
273
+ sock.destroy();
274
+ }
275
+ }
276
+
277
+ });
278
+
279
+ serv.on('error', (e) => {
280
+ if (e.code === 'EADDRINUSE') {
281
+ if (process.send !== undefined && typeof process.send === 'function') {
282
+ process.send({type: '_eaddr'}, (err) => {});
283
+ } else {
284
+ console.error('Error: 该端口已被使用,请先停止相关进程');
285
+ process.exit(1);
286
+ }
287
+ } else {
288
+ self.config.errorHandle(e, '--ERR--');
289
+ }
290
+ });
291
+
292
+ serv.setTimeout(this.config.timeout, (sock) => {
293
+ if (!sock.destroyed) {
294
+ if (!sock.pending) {
295
+ sock.end('HTTP/1.1 408 Request timeout\r\n', () => {
296
+ sock.destroy();
297
+ });
298
+ } else {
299
+ sock.destroy();
300
+ }
301
+ }
302
+ });
303
+
304
+ serv.maxHeadersCount = 80;
305
+ serv.headersTimeout = 6000;
306
+ serv.requestTimeout = self.config.requestTimeout;
307
+
308
+ for (let k in this.events) {
309
+ for (let ecall of this.events[k]) {
310
+ if (typeof ecall !== 'function') {
311
+ continue;
312
+ }
313
+ serv.on(k, ecall);
314
+ }
315
+ }
316
+
317
+ this.events = {};
318
+
319
+ //说明是使用unix socket模式监听服务
320
+ if (typeof port === 'string' && port.indexOf('.sock') > 0) {
321
+ this.host = port;
322
+ serv.listen(port);
323
+ } else {
324
+ this.host = host;
325
+ if (port !== 80 && port !== 443) {
326
+ this.host += `:${port}`;
327
+ }
328
+ serv.listen(port, host);
329
+ }
330
+
331
+ return serv;
332
+ }
333
+
334
+ }
335
+
336
+ module.exports = Http1;
package/src/http2.js ADDED
@@ -0,0 +1,337 @@
1
+ 'use strict';
2
+
3
+ const http2 = require('node:http2');
4
+ const fs = require('node:fs');
5
+ const process = require('node:process');
6
+ const logger = require('./logger.js');
7
+ const {fpurl} = require('./fastParseUrl.js');
8
+ const ctxpool = require('./ctxpool.js');
9
+ const Context = require('./context2.js');
10
+ const checkHeaderLimit = require('./headerLimit.js');
11
+ const sendmsg = require('./sendmsg.js');
12
+
13
+ /**
14
+ * 因http2设计缺陷以及Node.js在实现上的细节不健全导致不得不对一些可能的情况做处理。
15
+ */
16
+
17
+ class Httpt {
18
+
19
+ constructor(options) {
20
+ this.config = options.config;
21
+ this.router = options.router;
22
+ this.events = options.events;
23
+ this.midware = options.midware;
24
+ this.service = options.service;
25
+ this.isWorker = options.isWorker;
26
+
27
+ this.logger = logger;
28
+ ctxpool.max = this.config.maxpool;
29
+
30
+ this.ctxpool = ctxpool;
31
+ this.Context = Context;
32
+ this.fpurl = fpurl;
33
+
34
+ this.host = '';
35
+
36
+ this.onRequest = this.onStream;
37
+ }
38
+
39
+ requestError(err, handle, headers) {
40
+ this.config.errorHandle(err, '--ERR-REQUEST--');
41
+
42
+ if (!handle.destroyed) {
43
+ handle.destroy();
44
+ }
45
+ }
46
+
47
+ onStream() {
48
+ let self = this;
49
+
50
+ let callback = (stream, headers) => {
51
+
52
+ stream.on('error', (err) => {
53
+ self.requestError(err, stream, headers);
54
+ });
55
+
56
+ stream.on('frameError', (err) => {
57
+ self.requestError(err, stream, headers);
58
+ });
59
+
60
+ stream.on('aborted', err => {
61
+ err && self.requestError(err, stream, headers);
62
+ !err && stream.destroy();
63
+ });
64
+
65
+ let remote_ip = stream.session.socket.remoteAddress || '';
66
+
67
+ if (headers[':path'].length > self.config.maxUrlLength) {
68
+ headers[':path'] = headers[':path'].substring(0, self.config.maxUrlLength);
69
+ }
70
+
71
+ if (self.config.globalLog) {
72
+
73
+ let real_ip = '-';
74
+
75
+ if (self.config.realIP) {
76
+ real_ip = headers['x-real-ip'] || headers['x-forwarded-for'] || '-';
77
+ }
78
+
79
+ stream.on('close', () => {
80
+
81
+ if (stream && stream.sentHeaders && stream.rstCode === http2.constants.NGHTTP2_NO_ERROR) {
82
+
83
+ //http2请求可以提交超大消息头,而相关设置项没有效果。
84
+ checkHeaderLimit(headers, 'user-agent', 111);
85
+ checkHeaderLimit(headers, ':authority', 300);
86
+
87
+ // typeof stream.sentHeaders[':status'] === 'number'
88
+ self.logger({
89
+ method: headers[':method'],
90
+ status: stream.sentHeaders[':status'] || 0,
91
+ ip: remote_ip,
92
+ link: `${headers[':scheme']}://${headers[':authority'] || self.host}${headers[':path']}`,
93
+ agent: headers['user-agent'] || '-',
94
+ real_ip: real_ip
95
+ });
96
+
97
+ }
98
+ });
99
+ }
100
+
101
+ let urlobj = fpurl(headers[':path'], self.config.autoDecodeQuery,
102
+ self.config.fastParseQuery,
103
+ self.config.maxQuery);
104
+
105
+ let rt = self.router.findRealPath(urlobj.path, headers[':method']);
106
+
107
+ if (rt === null) {
108
+ stream.respond({':status': '404'});
109
+ stream.end(self.config.notFound);
110
+ return ;
111
+ }
112
+
113
+ stream.setTimeout(self.config.streamTimeout, () => {
114
+ stream.close();
115
+ });
116
+
117
+ let ctx = ctxpool.getctx() || new Context();
118
+
119
+ ctx.bodyLength = 0;
120
+ ctx.maxBody = self.config.maxBody;
121
+ ctx.service = self.service;
122
+ ctx.method = headers[':method'];
123
+ ctx.host = headers[':authority'] || headers.host || self.host;
124
+ ctx.protocol = headers[':scheme'];
125
+
126
+ ctx.ip = remote_ip;
127
+ ctx.port = stream.session.socket.remotePort;
128
+ ctx.stream = stream;
129
+ ctx.res = ctx.stream;
130
+ ctx.req = ctx.stream;
131
+
132
+ ctx.dataHeaders = {};
133
+ ctx.headers = headers;
134
+
135
+ ctx.path = urlobj.path;
136
+ ctx.query = urlobj.query;
137
+ ctx.routepath = rt.key;
138
+ ctx.requestCall = rt.reqcall.reqCall;
139
+ ctx.name = rt.reqcall.name;
140
+ ctx.group = rt.reqcall.group;
141
+ ctx.param = rt.args;
142
+ rt = null;
143
+
144
+ return self.midware.run(ctx).finally(() => {
145
+ ctxpool.free(ctx);
146
+ ctx = null;
147
+ });
148
+ };
149
+
150
+ return callback;
151
+ }
152
+
153
+ mid() {
154
+ let self = this;
155
+ let noBodyMethods = Object.create(null);
156
+
157
+ ['GET','OPTIONS','HEAD','TRACE'].forEach(a => {
158
+ noBodyMethods[a] = true;
159
+ });
160
+
161
+ return async (ctx, next) => {
162
+ let resolved = false;
163
+ let bodylength = 0;
164
+ let bodyBuffer;
165
+
166
+ await new Promise((rv, rj) => {
167
+ if (noBodyMethods[ctx.method]) {
168
+ ctx.stream.on('data', data => {
169
+ ctx.stream.respond({':status' : '400'});
170
+ ctx.stream.end(self.config.badRequest);
171
+ ctx.stream.close();
172
+ });
173
+ } else {
174
+ let bigBodyEnd = false;
175
+ bodyBuffer = [];
176
+ ctx.stream.on('data', data => {
177
+ bodylength += data.length;
178
+ if (bodylength > ctx.maxBody) {
179
+ if (bigBodyEnd) return;
180
+ bigBodyEnd = true;
181
+
182
+ bodyBuffer = null;
183
+ ctx.stream.respond({':status' : '413'});
184
+ ctx.stream.end();
185
+ ctx.stream.close();
186
+ return ;
187
+ }
188
+ bodyBuffer.push(data);
189
+ });
190
+ }
191
+
192
+ let handle_error = err => {
193
+ if (!resolved) {
194
+ resolved = true;
195
+ rv();
196
+ }
197
+ };
198
+
199
+ ctx.stream.on('aborted', handle_error);
200
+ ctx.stream.on('error', handle_error);
201
+ ctx.stream.on('frameError', handle_error);
202
+ ctx.stream.on('timeout', handle_error);
203
+
204
+ ctx.stream.on('close', () => {
205
+ (!resolved) && rv();
206
+ });
207
+
208
+ //在内部实现上,http2模块总是会触发end事件,这应该是在finalCloseStream中调用this.push(null)实现的。
209
+ ctx.stream.on('end',() => {
210
+ resolved = true;
211
+ rv();
212
+ });
213
+
214
+ });
215
+
216
+ if (ctx.stream.closed || ctx.stream.destroyed) {
217
+ return;
218
+ }
219
+
220
+ if (bodyBuffer && bodyBuffer.length > 0) {
221
+ ctx.bodyLength = bodylength;
222
+ ctx.rawBody = Buffer.concat(bodyBuffer, bodylength);
223
+ bodyBuffer = null;
224
+ }
225
+
226
+ await next(ctx);
227
+ }
228
+ //end func
229
+ }
230
+
231
+ /**
232
+ * 运行HTTP/2服务
233
+ * @param {number} port 端口号
234
+ * @param {string} host IP地址,可以是IPv4或IPv6
235
+ * 0.0.0.0 对应使用IPv6则是::
236
+ */
237
+ run(port, host) {
238
+ let self = this;
239
+ let serv = null;
240
+
241
+ try {
242
+ if (this.config.https) {
243
+ if (this.config.key && this.config.cert) {
244
+ this.config.server.key = fs.readFileSync(this.config.key);
245
+ this.config.server.cert = fs.readFileSync(this.config.cert);
246
+ }
247
+ serv = http2.createSecureServer(this.config.server);
248
+ } else {
249
+ serv = http2.createServer(this.config.server);
250
+ }
251
+ } catch(err) {
252
+ !this.isWorker && console.error(err);
253
+ sendmsg('_server-error', err.message, {autoExit: true, exitCode: 1});
254
+ }
255
+
256
+ serv.on('stream', this.onStream());
257
+
258
+ serv.on('sessionError', (err, sess) => {
259
+ self.config.errorHandle(err, '--ERR-SESSION--');
260
+ if (!sess.destroyed) {
261
+ sess.destroy();
262
+ }
263
+
264
+ });
265
+
266
+ serv.on('tlsClientError', (err, tls) => {
267
+ self.config.errorHandle(err, '--ERR-TLS-CLIENT--');
268
+ if (!tls.destroyed) {
269
+ tls.destroy();
270
+ }
271
+ });
272
+
273
+ //只监听tlsClientError是不行的,在进行并发压力测试时,会异常退出。
274
+ serv.on('secureConnection', (sock) => {
275
+ //在http2中,要触发超时必须要在此事件内,在connection事件中,会导致segment fault。
276
+ //但是socket超时并非空闲超时,而是只要超过时间就触发,所以在此处不再处理超时。
277
+
278
+ sock.on('error', err => {
279
+ self.config.errorHandle(err, '--ERR-CONNECTION--');
280
+ });
281
+
282
+ });
283
+
284
+ serv.on('unknownProtocol', tls_sock => {
285
+ if (!tls_sock.destroyed) {
286
+ tls_sock.destroy();
287
+ }
288
+ });
289
+
290
+ serv.on('error', (e) => {
291
+ if (e.code === 'EADDRINUSE') {
292
+ if (process.send !== undefined && typeof process.send === 'function') {
293
+ process.send({type: '_eaddr'});
294
+ } else {
295
+ console.error('Error: 该端口已被使用,请先停止相关进程');
296
+ process.exit(1);
297
+ }
298
+ } else {
299
+ self.config.errorHandle(e, '--ERR--');
300
+ }
301
+ });
302
+
303
+ serv.setTimeout(self.config.timeout, session => {
304
+ session.close(() => {
305
+ !session.destroyed && session.destroy();
306
+ });
307
+ });
308
+
309
+ for (let k in this.events) {
310
+ for (let ecall of this.events[k]) {
311
+ if (typeof ecall !== 'function') {
312
+ continue;
313
+ }
314
+ serv.on(k, ecall);
315
+ }
316
+ }
317
+
318
+ this.events = {};
319
+
320
+ //说明是使用unix socket模式监听服务
321
+ if (typeof port === 'string' && port.indexOf('.sock') > 0) {
322
+ this.host = port;
323
+ serv.listen(port);
324
+ } else {
325
+ this.host = host;
326
+ if (port !== 80 && port !== 443) {
327
+ this.host += `:${port}`;
328
+ }
329
+ serv.listen(port, host);
330
+ }
331
+
332
+ return serv;
333
+ }
334
+
335
+ }
336
+
337
+ module.exports = Httpt;