birdpack 1.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.
- package/lib/core.js +411 -0
- package/lib/fileType.json +35 -0
- package/lib/server.js +426 -0
- package/lib/tools.js +330 -0
- package/lib/websocket.js +312 -0
- package/package.json +17 -0
package/lib/server.js
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
const core = require('./core');
|
|
2
|
+
const websocket = require('./websocket');
|
|
3
|
+
const R938_METHOD = ['get','post','put','patch','delete','head','options'];
|
|
4
|
+
|
|
5
|
+
module.exports = class{
|
|
6
|
+
mapws = {}
|
|
7
|
+
maps = {}
|
|
8
|
+
calls = []
|
|
9
|
+
constructor(opt){
|
|
10
|
+
this.opt = opt || {};
|
|
11
|
+
|
|
12
|
+
console.log(this.powered());
|
|
13
|
+
|
|
14
|
+
this.argv();
|
|
15
|
+
this.setupMethod();
|
|
16
|
+
this.setupSSL();
|
|
17
|
+
}
|
|
18
|
+
argv(){
|
|
19
|
+
let cmd = {
|
|
20
|
+
'-u':'use',
|
|
21
|
+
'-p':'port',
|
|
22
|
+
};
|
|
23
|
+
let data = false;
|
|
24
|
+
for(let x of process.argv){
|
|
25
|
+
if(data !== false){
|
|
26
|
+
this.opt[data] = x;
|
|
27
|
+
data = false;
|
|
28
|
+
}else if(cmd[x]){
|
|
29
|
+
data = cmd[x];
|
|
30
|
+
this.opt[data] = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
setupMethod(){
|
|
35
|
+
for(let x of R938_METHOD){
|
|
36
|
+
this[x] = (url, callback)=>{
|
|
37
|
+
this.set({
|
|
38
|
+
domain:'*',
|
|
39
|
+
method:x,
|
|
40
|
+
url,
|
|
41
|
+
callback:this.setCall(callback)
|
|
42
|
+
});
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
setupSSL(){
|
|
48
|
+
const tls = require('tls');
|
|
49
|
+
const sslSecure = [];
|
|
50
|
+
const sslDomain = {};
|
|
51
|
+
|
|
52
|
+
if(Array.isArray(this.opt.ssl) && this.opt.ssl.length > 0){
|
|
53
|
+
for(const x of this.opt.ssl){
|
|
54
|
+
const typeDomain = typeof x.domain;
|
|
55
|
+
if(typeDomain == 'string'){
|
|
56
|
+
sslDomain[x.domain] = sslSecure.length;
|
|
57
|
+
}else if(typeDomain == 'object' && Array.isArray(x.domain)){
|
|
58
|
+
for(let d of x.domain){
|
|
59
|
+
sslDomain[d] = sslSecure.length;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
sslSecure.push(tls.createSecureContext(x));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.opt.SNICallback = function(servername, callback){
|
|
66
|
+
let data = this._SNICallback.prototype.data;
|
|
67
|
+
if(data.domain.hasOwnProperty(servername)){
|
|
68
|
+
callback(null, data.secure[data.domain[servername]]);
|
|
69
|
+
}else{
|
|
70
|
+
callback();
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
this.opt.SNICallback.prototype.data = {
|
|
74
|
+
secure:sslSecure,
|
|
75
|
+
domain:sslDomain
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
create(){
|
|
80
|
+
let use = '';
|
|
81
|
+
if(this.opt.use == 'http'){
|
|
82
|
+
use = 'http';
|
|
83
|
+
}else if(this.opt.use == 'https'){
|
|
84
|
+
use = 'https';
|
|
85
|
+
}else{
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let options = {};
|
|
90
|
+
|
|
91
|
+
for(let x in this.opt){
|
|
92
|
+
if(['SNICallback','connectionsCheckingInterval','headersTimeout','keepAlive','keepAliveInitialDelay','keepAliveTimeout','maxHeaderSize','noDelay','requestTimeout','requireHostHeader'].includes(x)){
|
|
93
|
+
options[x] = this.opt[x];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const {createServer} = require(use);
|
|
98
|
+
this.server = createServer(options, (req, res)=>{
|
|
99
|
+
let cc = new core({req, res});
|
|
100
|
+
|
|
101
|
+
cc.router(()=>{
|
|
102
|
+
let call = this.maps[cc.host];
|
|
103
|
+
if(!call && this.maps['*']){
|
|
104
|
+
call = this.maps['*']
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if(call && call[cc.method]){
|
|
108
|
+
call = call[cc.method];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if(call){
|
|
112
|
+
if(call.fixed && call.fixed.hasOwnProperty(cc.path)){
|
|
113
|
+
call = call.fixed[cc.path];
|
|
114
|
+
}else if(call.params){
|
|
115
|
+
let path = cc.path.split('/').slice(1);
|
|
116
|
+
|
|
117
|
+
let mode = true;
|
|
118
|
+
for(const modes of call.params){
|
|
119
|
+
let status = false;
|
|
120
|
+
for(const route of modes){
|
|
121
|
+
if(!route.url || (mode && route.url.length !== path.length)) continue;
|
|
122
|
+
|
|
123
|
+
let matched = true;
|
|
124
|
+
|
|
125
|
+
for(let i = 0; i < path.length; i++){
|
|
126
|
+
const routeSegment = route.url[i];
|
|
127
|
+
const pathSegment = path[i];
|
|
128
|
+
|
|
129
|
+
if(routeSegment == undefined){
|
|
130
|
+
matched = false;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if(routeSegment === pathSegment){
|
|
135
|
+
continue;
|
|
136
|
+
}else if (routeSegment[0] === ':'){
|
|
137
|
+
cc.param(routeSegment.slice(1), pathSegment);
|
|
138
|
+
}else if(routeSegment === '*'){
|
|
139
|
+
cc.param('*', path.slice(i).join('/'));
|
|
140
|
+
break;
|
|
141
|
+
}else{
|
|
142
|
+
matched = false;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if(matched){
|
|
148
|
+
status = true;
|
|
149
|
+
call = route;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if(status){
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
mode = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if(call){
|
|
162
|
+
if(call.next !== false){
|
|
163
|
+
return this.getCall(call.next)(cc, (data)=>{
|
|
164
|
+
this.getCall(call.callback)(cc, data);
|
|
165
|
+
});
|
|
166
|
+
}else{
|
|
167
|
+
return this.getCall(call.callback)(cc);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
cc.error(404, 'This page isn\'t working');
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
this.server.on('upgrade', (req, socket, head) => {
|
|
176
|
+
const ws = new websocket({req, socket, head});
|
|
177
|
+
let call = this.mapws[ws.host];
|
|
178
|
+
if(!call && this.mapws['*']){
|
|
179
|
+
call = this.mapws['*']
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if(call && call.hasOwnProperty(ws.path)){
|
|
183
|
+
call = call[ws.path].callback;
|
|
184
|
+
|
|
185
|
+
const run = this.getCall(call);
|
|
186
|
+
|
|
187
|
+
ws.update(run);
|
|
188
|
+
run(ws, 'start');
|
|
189
|
+
}else{
|
|
190
|
+
ws.error(404);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
listen(port, host){
|
|
196
|
+
if(this.create()){
|
|
197
|
+
let domain = {};
|
|
198
|
+
for(let x in this.maps){
|
|
199
|
+
domain[x] = 1;
|
|
200
|
+
}
|
|
201
|
+
for(let x in this.mapws){
|
|
202
|
+
domain[x] = 1;
|
|
203
|
+
}
|
|
204
|
+
for(let x in domain){
|
|
205
|
+
this.log('domain', `${x}`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
this.server.listen(port || this.opt.port || process.env.PORT || 3000, host, ()=>{
|
|
209
|
+
this.log('server', `Started on server(${this.opt.use}) port(${this.server._connectionKey.split(':').pop()})`);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
log(status, text){
|
|
215
|
+
let out = `[${status}] - ${text}`;
|
|
216
|
+
console.log(out);
|
|
217
|
+
}
|
|
218
|
+
powered(){
|
|
219
|
+
return [
|
|
220
|
+
`\x1b[32m`,
|
|
221
|
+
` __ _________`,
|
|
222
|
+
` |__| |_______ \\`,
|
|
223
|
+
` __ \\ \\`,
|
|
224
|
+
` | | \\ \\`,
|
|
225
|
+
` | |__________/ /`,
|
|
226
|
+
` | ______ __/`,
|
|
227
|
+
` | | | | \x1b[33m | \x1b[36mBirdPack Framework\x1b[33m | \x1b[32m`,
|
|
228
|
+
` | | | | \x1b[33m | \x1b[0mR938 Service\x1b[33m | \x1b[32m`,
|
|
229
|
+
` |__| |__| \x1b[33m | \x1b[0mVersion: 1.0.0\x1b[33m | \x1b[0m`,
|
|
230
|
+
`____________________________________________`,
|
|
231
|
+
'',
|
|
232
|
+
].join('\n');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
domain(domain){
|
|
236
|
+
if(domain == undefined){
|
|
237
|
+
domain = '*';
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
let config = {
|
|
241
|
+
websocket:(url, a, b, c)=>{
|
|
242
|
+
let typeA = typeof a == 'function';
|
|
243
|
+
let typeB = typeof b == 'function';
|
|
244
|
+
let typeC = typeof c == 'function';
|
|
245
|
+
let callback;
|
|
246
|
+
|
|
247
|
+
if(typeA && typeB && typeC){
|
|
248
|
+
callback = async(core, code) => {
|
|
249
|
+
if(code == 'start'){
|
|
250
|
+
let check = await a(core, core.body);
|
|
251
|
+
|
|
252
|
+
if(check !== true){
|
|
253
|
+
core.stop();
|
|
254
|
+
}
|
|
255
|
+
}else if(code == 'data'){
|
|
256
|
+
await b(core, core.body);
|
|
257
|
+
}else if(code == 'close'){
|
|
258
|
+
await c(core, core.body);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
}else if(typeA){
|
|
262
|
+
callback = a;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
callback.users = {
|
|
266
|
+
member:{},
|
|
267
|
+
length:0,
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
this.setUpgrade({
|
|
271
|
+
domain,
|
|
272
|
+
url,
|
|
273
|
+
callback: this.setCall(callback)
|
|
274
|
+
});
|
|
275
|
+
return config;
|
|
276
|
+
},
|
|
277
|
+
next:(n)=>{
|
|
278
|
+
let next = {};
|
|
279
|
+
for(let x of R938_METHOD){
|
|
280
|
+
next[x] = (url, callback)=>{
|
|
281
|
+
this.set({
|
|
282
|
+
domain,
|
|
283
|
+
method:x,
|
|
284
|
+
url,
|
|
285
|
+
next:this.setCall(n),
|
|
286
|
+
callback:this.setCall(callback)
|
|
287
|
+
});
|
|
288
|
+
return next;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return next;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
for(let x of R938_METHOD){
|
|
297
|
+
config[x] = (url, callback)=>{
|
|
298
|
+
this.set({
|
|
299
|
+
domain,
|
|
300
|
+
method:x,
|
|
301
|
+
url,
|
|
302
|
+
callback:this.setCall(callback)
|
|
303
|
+
});
|
|
304
|
+
return config;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return config;
|
|
309
|
+
}
|
|
310
|
+
set({domain, method, url, next, callback}){
|
|
311
|
+
if(typeof domain != 'string'){
|
|
312
|
+
domain = '*';
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if(typeof method != 'string' || !R938_METHOD.includes(method)){
|
|
316
|
+
method = 'get';
|
|
317
|
+
}
|
|
318
|
+
method = method.toLowerCase();
|
|
319
|
+
|
|
320
|
+
if(typeof url != 'string' && !Array.isArray(url)){
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if(typeof next != 'number'){
|
|
325
|
+
next = false;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if(typeof callback != 'number'){
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if(!this.maps.hasOwnProperty(domain)){
|
|
333
|
+
this.maps[domain] = {};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if(!this.maps[domain].hasOwnProperty(method)){
|
|
337
|
+
this.maps[domain][method] = {
|
|
338
|
+
fixed:{},
|
|
339
|
+
params:[[], []]
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const urlCache = url.split('/').slice(1);
|
|
344
|
+
const mode = url.includes('*') ? 'flexible' : (url.includes(':') ? 'params' : 'fixed');
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
let route = {
|
|
348
|
+
url:urlCache,
|
|
349
|
+
next: next,
|
|
350
|
+
callback: callback,
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
if(mode == 'fixed'){
|
|
354
|
+
this.maps[domain][method].fixed[url] = route;
|
|
355
|
+
}else{
|
|
356
|
+
this.maps[domain][method].params[mode == 'params' ? 0 : 1].push(route);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
setUpgrade({domain, url, callback}){
|
|
360
|
+
if(typeof domain != 'string'){
|
|
361
|
+
domain = '*';
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if(typeof url != 'string' && !Array.isArray(url)){
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if(typeof callback != 'number'){
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if(!this.mapws.hasOwnProperty(domain)){
|
|
373
|
+
this.mapws[domain] = {};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
this.mapws[domain][url] = {
|
|
377
|
+
callback:callback
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
setCall(callback){
|
|
381
|
+
this.calls.push(callback);
|
|
382
|
+
return this.calls.length - 1;
|
|
383
|
+
}
|
|
384
|
+
getCall(id){
|
|
385
|
+
if(this.calls[id]){
|
|
386
|
+
return this.calls[id];
|
|
387
|
+
}
|
|
388
|
+
return ()=>{};
|
|
389
|
+
}
|
|
390
|
+
websocket(url, a, b, c){
|
|
391
|
+
let typeA = typeof a == 'function';
|
|
392
|
+
let typeB = typeof b == 'function';
|
|
393
|
+
let typeC = typeof c == 'function';
|
|
394
|
+
let callback;
|
|
395
|
+
|
|
396
|
+
if(typeA && typeB && typeC){
|
|
397
|
+
callback = async(core, code) => {
|
|
398
|
+
if(code == 'start'){
|
|
399
|
+
let check = await a(core, core.body);
|
|
400
|
+
|
|
401
|
+
if(check !== true){
|
|
402
|
+
core.stop();
|
|
403
|
+
}
|
|
404
|
+
}else if(code == 'data'){
|
|
405
|
+
await b(core, core.body);
|
|
406
|
+
}else if(code == 'close'){
|
|
407
|
+
await c(core, core.body);
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
}else if(typeA){
|
|
411
|
+
callback = a;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
callback.users = {
|
|
415
|
+
member:{},
|
|
416
|
+
length:0,
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
this.setUpgrade({
|
|
420
|
+
domain: '*',
|
|
421
|
+
url,
|
|
422
|
+
callback: this.setCall(callback)
|
|
423
|
+
});
|
|
424
|
+
return this;
|
|
425
|
+
}
|
|
426
|
+
}
|