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/http1.js ADDED
@@ -0,0 +1,337 @@
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.request = req;
126
+ ctx.response = res;
127
+ ctx.reply = ctx.response;
128
+
129
+ ctx.path = urlobj.path;
130
+ ctx.query = urlobj.query;
131
+ ctx.routepath = rt.key;
132
+ ctx.requestCall = rt.reqcall.reqCall;
133
+ ctx.name = rt.reqcall.name;
134
+ ctx.group = rt.reqcall.group;
135
+ ctx.param = rt.args;
136
+ rt = null;
137
+
138
+ return self.midware.run(ctx).finally(()=>{
139
+ ctxpool.free(ctx);
140
+ ctx = null;
141
+ });
142
+ };
143
+
144
+ return callback;
145
+ }
146
+
147
+ mid() {
148
+ let self = this;
149
+
150
+ let noBodyMethods = {};
151
+
152
+ ['GET','OPTIONS','HEAD','TRACE'].forEach(a => {
153
+ noBodyMethods[a] = true;
154
+ });
155
+
156
+ return async (ctx, next) => {
157
+ let resolved = false;
158
+ let bodylength = 0;
159
+ let bodyBuffer;
160
+
161
+ await new Promise((rv, rj) => {
162
+ //客户端和服务端解析不会允许非法method
163
+ if ( noBodyMethods[ctx.method] ) {
164
+ //实际上这个回调函数不会执行,因为会立即触发end事件,此处可以保证非法的请求也可以提交数据。
165
+ ctx.request.on('data', data => {
166
+ ctx.response.statusCode = 400;
167
+ ctx.response.end(self.config.badRequest);
168
+ ctx.request.destroy();
169
+ });
170
+ } else {
171
+ let bigBodyEnd = false;
172
+ bodyBuffer = [];
173
+ ctx.request.on('data', data => {
174
+ bodylength += data.length;
175
+ if (bodylength > ctx.maxBody) {
176
+ if (bigBodyEnd) return;
177
+ bigBodyEnd = true;
178
+
179
+ bodyBuffer = null;
180
+ ctx.response.statusCode = 413;
181
+ ctx.response.end('', () => {
182
+ ctx.request.destroy();
183
+ });
184
+ return ;
185
+ }
186
+ bodyBuffer.push(data);
187
+ });
188
+ }
189
+
190
+ //若请求体太大,此时会进行destroy处理,触发close事件,但不会触发end。
191
+ //通过记录resolved状态避免重复调用rv。
192
+ ctx.request.on('close', () => {
193
+ (!resolved) && rv();
194
+ });
195
+
196
+ ctx.request.on('end',() => {
197
+ resolved = true;
198
+ rv();
199
+ });
200
+
201
+ });
202
+
203
+ if (!ctx.response.writable || ctx.response.writableEnded) {
204
+ return;
205
+ }
206
+
207
+ if (bodyBuffer && bodyBuffer.length > 0) {
208
+ ctx.bodyLength = bodylength;
209
+ ctx.rawBody = Buffer.concat(bodyBuffer, bodylength);
210
+ bodyBuffer = null;
211
+ }
212
+
213
+ await next();
214
+ };
215
+
216
+ }
217
+
218
+ /**
219
+ * 运行HTTP/1.1服务
220
+ * @param {number} port 端口号
221
+ * @param {string} host IP地址,可以是IPv4或IPv6
222
+ * 0.0.0.0 对应使用IPv6则是::
223
+ */
224
+ run(port, host) {
225
+ let self = this;
226
+ let serv = null;
227
+
228
+ if (this.config.https) {
229
+ try {
230
+ if (this.config.key && this.config.cert) {
231
+ this.config.server.key = fs.readFileSync(this.config.key);
232
+ this.config.server.cert = fs.readFileSync(this.config.cert);
233
+ }
234
+
235
+ serv = https.createServer(this.config.server, this.onRequest());
236
+
237
+ serv.on('tlsClientError', (err, tls) => {
238
+
239
+ self.config.errorHandle(err, '--ERR-TLS-CLIENT--');
240
+
241
+ if (!tls.destroyed) {
242
+ tls.destroy();
243
+ }
244
+
245
+ });
246
+
247
+ serv.on('secureConnection', (sock) => {
248
+ sock.on('error', err => {
249
+ self.config.errorHandle(err, '--ERR-CONNECTION--');
250
+ });
251
+ });
252
+
253
+ } catch (err) {
254
+ !this.isWorker && console.error(err);
255
+ sendmsg('_server-error', err.message, {autoExit: true, exitCode: 1});
256
+ }
257
+ } else {
258
+ serv = http.createServer(self.config.server, this.onRequest());
259
+ }
260
+
261
+ serv.on('clientError', (err, sock) => {
262
+ if (sock.destroyed) return;
263
+
264
+ self.config.errorHandle(err, '--ERR-CLIENT--');
265
+
266
+ if (err.code === 'ECONNRESET' || !sock.writable) return;
267
+
268
+ if (!sock.destroyed) {
269
+ if (!sock.writableEnded) {
270
+ sock.end('HTTP/1.1 400 Bad request\r\n', () => {
271
+ sock.destroy();
272
+ });
273
+ } else {
274
+ sock.destroy();
275
+ }
276
+ }
277
+
278
+ });
279
+
280
+ serv.on('error', (e) => {
281
+ if (e.code === 'EADDRINUSE') {
282
+ if (process.send !== undefined && typeof process.send === 'function') {
283
+ process.send({type: '_eaddr'}, (err) => {});
284
+ } else {
285
+ console.error('Error: 该端口已被使用,请先停止相关进程');
286
+ process.exit(1);
287
+ }
288
+ } else {
289
+ self.config.errorHandle(e, '--ERR--');
290
+ }
291
+ });
292
+
293
+ serv.setTimeout(this.config.timeout, (sock) => {
294
+ if (!sock.destroyed) {
295
+ if (!sock.pending) {
296
+ sock.end('HTTP/1.1 408 Request timeout\r\n', () => {
297
+ sock.destroy();
298
+ });
299
+ } else {
300
+ sock.destroy();
301
+ }
302
+ }
303
+ });
304
+
305
+ serv.maxHeadersCount = 80;
306
+ serv.headersTimeout = 6000;
307
+ serv.requestTimeout = self.config.requestTimeout;
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 = 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.reply = ctx.stream;
130
+ ctx.request = 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 = {};
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();
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;