birdpack 1.0.2 → 1.0.4

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 CHANGED
@@ -1,4 +1,5 @@
1
1
  const tools = require('./tools');
2
+ const powered = require('./powered');
2
3
  const fs = require('fs');
3
4
  const fileType = require('./fileType');
4
5
 
@@ -9,10 +10,12 @@ module.exports = class{
9
10
  buffers = []
10
11
  body = {}
11
12
  host = ''
12
- url = ''
13
+ path = ''
13
14
  query = {}
14
15
  method = ''
16
+ ip = ''
15
17
  callrouter = ()=>{}
18
+ log = ()=>{}
16
19
  params = {}
17
20
  constructor({req, res}){
18
21
  this.req = req;
@@ -60,8 +63,22 @@ module.exports = class{
60
63
  return false;
61
64
  }
62
65
 
63
- const findHost = this.req.headers.host.indexOf(':');
64
- this.host = findHost === -1 ? this.req.headers.host : this.req.headers.host.slice(0, findHost);
66
+ let ipcf = this.get('cf-connecting-ip');
67
+ let ipx = this.get('x-forwarded-for');
68
+ if(ipcf){
69
+ this.ip = ipcf;
70
+ }else if(ipx){
71
+ this.ip = ipx.split(',')[0];
72
+ }else{
73
+ this.ip = this.res.socket.remoteAddress;
74
+ }
75
+
76
+ if(this.res.socket.servername){
77
+ this.host = this.res.socket.servername;
78
+ }else{
79
+ const findHost = this.req.headers.host.indexOf(':');
80
+ this.host = findHost === -1 ? this.req.headers.host : this.req.headers.host.slice(0, findHost);
81
+ }
65
82
 
66
83
  this.method = this.req.method.toLowerCase();
67
84
 
@@ -96,6 +113,9 @@ module.exports = class{
96
113
  }
97
114
  return true;
98
115
  }
116
+ traffic(f){
117
+ this.log = f;
118
+ }
99
119
  router(call){
100
120
  this.callrouter = call;
101
121
  }
@@ -169,12 +189,14 @@ module.exports = class{
169
189
  }
170
190
 
171
191
  writeHead(){
172
- this.header['x-powered-by'] = `R938`;
192
+ this.header['x-powered-by'] = powered.by;
173
193
  if(this.res.writable){
174
- this.res.writeHead(this.status ? this.status : 200, this.header);
194
+ this.status = this.status ? this.status : 200;
195
+ this.res.writeHead(this.status, this.header);
175
196
  }else if(this.req.destroyed){
176
197
  this.req.destroy();
177
198
  }
199
+ this.log();
178
200
  return this;
179
201
  }
180
202
  write(data, callback){
package/lib/method.js ADDED
@@ -0,0 +1,153 @@
1
+ const tools = require('./tools');
2
+ const METHOD = ['get','post','put','patch','delete','head','options'];
3
+ const fs = require('fs');
4
+
5
+ module.exports = {
6
+ METHOD,
7
+ basic:(app, use, {domain, next})=>{
8
+ for(let x of METHOD){
9
+ use[x] = (url, callback)=>{
10
+ app.set({
11
+ domain,
12
+ method:x,
13
+ url,
14
+ next,
15
+ callback:app.setCall(callback)
16
+ });
17
+ return use;
18
+ }
19
+ }
20
+ },
21
+ directory:(use)=>{
22
+ return (dir, {path, callback, error})=>{
23
+ if(typeof path !== 'string'){
24
+ path = '/';
25
+ }else if(path[path.length-1] != '/'){
26
+ path += '/';
27
+ }
28
+
29
+ let getPath = path + '*';
30
+ if(dir != '' && dir[dir.length-1] != '/'){
31
+ dir += '/';
32
+ }
33
+
34
+ if(typeof callback !== 'function'){
35
+ callback = (req, {load, file})=>{
36
+ req.file(load, {
37
+ error:(code, text)=>{
38
+ error(req, code, text);
39
+ }
40
+ });
41
+ }
42
+ }
43
+ if(typeof error !== 'function'){
44
+ error = (req, code, text)=>{
45
+ req.code(code).send(text);
46
+ }
47
+ }
48
+
49
+ use.get(getPath, (req)=>{
50
+ let searchPath = req.path.search(path);
51
+ let checkPath = req.path.substr(searchPath + path.length);
52
+ if(checkPath != ''){
53
+ let file = tools.checkPath(checkPath);
54
+ if(file !== false){
55
+ let load = `${dir}${file}`;
56
+
57
+ return callback(req, {load, file});
58
+ }
59
+ }
60
+
61
+ error(req, 404, 'File not found.');
62
+ });
63
+ return this;
64
+ }
65
+ },
66
+ websocket:(app, use, domain)=>{
67
+ return (url, a, b, c)=>{
68
+ let typeA = typeof a == 'function';
69
+ let typeB = typeof b == 'function';
70
+ let typeC = typeof c == 'function';
71
+ let callback;
72
+
73
+ if(typeA && typeB && typeC){
74
+ callback = async(core, code) => {
75
+ if(code == 'start'){
76
+ let check = await a(core, core.body);
77
+
78
+ if(check !== true){
79
+ core.stop();
80
+ }
81
+ }else if(code == 'data'){
82
+ await b(core, core.body);
83
+ }else if(code == 'close'){
84
+ await c(core, core.body);
85
+ }
86
+ };
87
+ }else if(typeA){
88
+ callback = a;
89
+ }
90
+
91
+ callback.users = {
92
+ member:{},
93
+ length:0,
94
+ };
95
+
96
+ app.setUpgrade({
97
+ domain,
98
+ url,
99
+ callback: app.setCall(callback)
100
+ });
101
+ return use;
102
+ };
103
+ },
104
+ routes:(use)=>{
105
+ return (dir)=>{
106
+ if(fs.lstatSync(dir).isDirectory()){
107
+ let path = `${dir}/`;
108
+ let list = {};
109
+ fs.readdirSync(path).forEach((file)=>{
110
+ if(fs.existsSync(path + file)){
111
+ let ext = file.split('.').pop();
112
+ if(ext == 'js'){
113
+ let pathFile = path + file;
114
+ list[file.slice(0,-3)] = require(pathFile);
115
+ }
116
+ }
117
+ });
118
+
119
+ for(let x in list){
120
+ let db = x.split('@');
121
+ let method = "get";
122
+ let path = '';
123
+
124
+ if(db.length == 1){
125
+ path = db[0];
126
+ }else if(db.length == 2){
127
+ method = db[0];
128
+ path = db[1];
129
+ }else{
130
+ break;
131
+ }
132
+
133
+ path = path.replace(/[\-\$\"]/g,(a)=>{
134
+ let list={
135
+ '-':'/',
136
+ '$':':'
137
+ };
138
+ if(list.hasOwnProperty(a)){
139
+ return list[a];
140
+ }else{
141
+ return '';
142
+ }
143
+ });
144
+
145
+ if(use[method]){
146
+ use[method](`/${path}`, list[x]);
147
+ }
148
+ }
149
+ }
150
+ return use;
151
+ };
152
+ },
153
+ };
package/lib/powered.js ADDED
@@ -0,0 +1,18 @@
1
+ let package = {};
2
+
3
+ try{
4
+ package = require(`${__dirname}/../package.json`);
5
+ }catch(e){
6
+ console.log('Not have package.json');
7
+ }
8
+
9
+ let version = package.version || '1.0.0';
10
+ let author = package.author || 'R938';
11
+ let name = package.name || 'R938';
12
+
13
+ module.exports = {
14
+ name,
15
+ by:`${author}/${version}`,
16
+ version,
17
+ author
18
+ };
package/lib/server.js CHANGED
@@ -1,6 +1,8 @@
1
+ const fs = require('fs');
1
2
  const core = require('./core');
2
3
  const websocket = require('./websocket');
3
- const R938_METHOD = ['get','post','put','patch','delete','head','options'];
4
+ const powered = require('./powered');
5
+ const methodPlugin = require('./method');
4
6
 
5
7
  module.exports = class{
6
8
  mapws = {}
@@ -9,12 +11,33 @@ module.exports = class{
9
11
  constructor(opt){
10
12
  this.opt = opt || {};
11
13
 
12
- console.log(this.powered());
14
+ this.powered();
15
+ this.dev();
13
16
 
14
17
  this.argv();
15
18
  this.setupMethod();
16
19
  this.setupSSL();
17
20
  }
21
+ dev(){
22
+ if(typeof this.opt.log !== 'string'){
23
+ this.opt.log = 'console';
24
+ }
25
+
26
+ if(this.opt.log == 'console'){
27
+ this.log = (status, text)=>{
28
+ let out = `[${status}] - ${text}`;
29
+ console.log(out);
30
+ }
31
+ }else if(this.opt.log == 'file' && typeof this.opt.logFile == 'string'){
32
+ let file = fs.createWriteStream(this.opt.logFile, { flags: 'a' });
33
+ this.log = (status, text)=>{
34
+ let out = `[${status}] - ${text}`;
35
+ file.write(`${out}\n`);
36
+ }
37
+ }else{
38
+ this.log = ()=>{};
39
+ }
40
+ }
18
41
  argv(){
19
42
  let cmd = {
20
43
  '-u':'use',
@@ -32,19 +55,16 @@ module.exports = class{
32
55
  }
33
56
  }
34
57
  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
- }
58
+ methodPlugin.basic(this, this, {domain:'*'});
59
+ this.routes = methodPlugin.routes(this);
60
+ this.directory = methodPlugin.directory(this);
61
+ this.websocket = methodPlugin.websocket(this, this, '*');
46
62
  }
47
63
  setupSSL(){
64
+ if(this.opt.use !== 'https'){
65
+ return false;
66
+ }
67
+
48
68
  const tls = require('tls');
49
69
  const sslSecure = [];
50
70
  const sslDomain = {};
@@ -98,7 +118,10 @@ module.exports = class{
98
118
  this.server = createServer(options, (req, res)=>{
99
119
  let cc = new core({req, res});
100
120
 
101
- cc.router(()=>{
121
+ cc.traffic(()=>{
122
+ this.traffic(cc);
123
+ });
124
+ cc.router(()=>{
102
125
  let call = this.maps[cc.host];
103
126
  if(!call && this.maps['*']){
104
127
  call = this.maps['*']
@@ -174,6 +197,10 @@ module.exports = class{
174
197
  });
175
198
  this.server.on('upgrade', (req, socket, head) => {
176
199
  const ws = new websocket({req, socket, head});
200
+ ws.traffic(()=>{
201
+ this.traffic(ws);
202
+ });
203
+
177
204
  let call = this.mapws[ws.host];
178
205
  if(!call && this.mapws['*']){
179
206
  call = this.mapws['*']
@@ -181,6 +208,7 @@ module.exports = class{
181
208
 
182
209
  if(call && call.hasOwnProperty(ws.path)){
183
210
  call = call[ws.path].callback;
211
+ this.traffic(ws);
184
212
 
185
213
  const run = this.getCall(call);
186
214
 
@@ -194,6 +222,8 @@ module.exports = class{
194
222
  }
195
223
  listen(port, host){
196
224
  if(this.create()){
225
+ this.logServer('server', `Welcome to Server BirdPack by R938`);
226
+
197
227
  let domain = {};
198
228
  for(let x in this.maps){
199
229
  domain[x] = 1;
@@ -202,21 +232,38 @@ module.exports = class{
202
232
  domain[x] = 1;
203
233
  }
204
234
  for(let x in domain){
205
- this.log('domain', `${x}`);
235
+ this.logServer('server', `Use domian ${x}`);
206
236
  }
207
237
 
238
+ this.logServer('server', `The server is collecting logs via (${this.opt.log})`);
208
239
  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()})`);
240
+ this.logServer('server', `Started on server(${this.opt.use}) port(${this.server._connectionKey.split(':').pop()})`);
210
241
  });
211
242
  }
212
243
  }
213
-
214
- log(status, text){
244
+ logServer(status, text){
215
245
  let out = `[${status}] - ${text}`;
216
246
  console.log(out);
217
247
  }
248
+ traffic(c){
249
+ this.log('client',`${this.getFormattedDateTime()} ${c.status} ${c.method} ${c.path} ${c.ip} ${c.get('user-agent')}`);
250
+ }
251
+ getFormattedDateTime(){
252
+ let now = new Date();
253
+
254
+ let day = String(now.getDate()).padStart(2, '0');
255
+ let month = String(now.getMonth() + 1).padStart(2, '0');
256
+ let year = now.getFullYear();
257
+
258
+ let hours = String(now.getHours()).padStart(2, '0');
259
+ let minutes = String(now.getMinutes()).padStart(2, '0');
260
+ let seconds = String(now.getSeconds()).padStart(2, '0');
261
+
262
+ return `${day}-${month}-${year} ${hours}:${minutes}:${seconds}`;
263
+ }
264
+
218
265
  powered(){
219
- return [
266
+ console.log([
220
267
  `\x1b[32m`,
221
268
  ` __ _________`,
222
269
  ` |__| |_______ \\`,
@@ -224,12 +271,12 @@ module.exports = class{
224
271
  ` | | \\ \\`,
225
272
  ` | |__________/ /`,
226
273
  ` | ______ __/`,
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`,
274
+ ` | | | | \x1b[33m | \x1b[36mFramework: ${powered.name}\x1b[32m`,
275
+ ` | | | | \x1b[33m | \x1b[0mAuthor: ${powered.author}\x1b[32m`,
276
+ ` |__| |__| \x1b[33m | \x1b[0mVersion: ${powered.version}\x1b[0m`,
230
277
  `____________________________________________`,
231
278
  '',
232
- ].join('\n');
279
+ ].join('\n'));
233
280
  }
234
281
 
235
282
  domain(domain){
@@ -238,72 +285,19 @@ module.exports = class{
238
285
  }
239
286
 
240
287
  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
288
  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
- }
289
+ let next = {};
290
+ methodPlugin.basic(this, next, {domain, next:this.setCall(n)});
291
+ next.routes = methodPlugin.routes(next);
292
+ next.directory = methodPlugin.directory(next);
291
293
 
292
294
  return next;
293
295
  }
294
296
  }
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
- }
297
+ methodPlugin.basic(this, config, {domain});
298
+ config.routes = methodPlugin.routes(config);
299
+ config.directory = methodPlugin.directory(config);
300
+ config.websocket = methodPlugin.websocket(this, config, domain);
307
301
 
308
302
  return config;
309
303
  }
@@ -312,7 +306,7 @@ module.exports = class{
312
306
  domain = '*';
313
307
  }
314
308
 
315
- if(typeof method != 'string' || !R938_METHOD.includes(method)){
309
+ if(typeof method != 'string' || !methodPlugin.METHOD.includes(method)){
316
310
  method = 'get';
317
311
  }
318
312
  method = method.toLowerCase();
@@ -386,41 +380,5 @@ module.exports = class{
386
380
  return this.calls[id];
387
381
  }
388
382
  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
383
  }
426
384
  }
package/lib/tools.js CHANGED
@@ -324,7 +324,14 @@ const tools = {
324
324
  .toString('base64')
325
325
  .replace(/[^a-zA-Z0-9]/g, '')
326
326
  .slice(0, 64);
327
- }
327
+ },
328
+ checkPath:(name)=>{
329
+ try{
330
+ name = decodeURIComponent(name);
331
+ return name.replace(/(\.\.)|[\[\n\r\t\*\?\"\<\>\|]/,'') == name ? name : false;
332
+ }catch(e){}
333
+ return false;
334
+ },
328
335
  };
329
336
 
330
337
  module.exports = tools;
package/lib/websocket.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const tools = require('./tools');
2
+ const powered = require('./powered');
2
3
 
3
4
  module.exports = class{
4
5
  status = 0
@@ -6,10 +7,12 @@ module.exports = class{
6
7
  cookie = {}
7
8
  body = {}
8
9
  host = ''
9
- url = ''
10
+ path = ''
10
11
  query = {}
11
12
  method = ''
13
+ ip = ''
12
14
  callback = ()=>{}
15
+ log = ()=>{}
13
16
  constructor({req, socket, head}){
14
17
  this.req = req;
15
18
  this.socket = socket;
@@ -40,8 +43,22 @@ module.exports = class{
40
43
  return false;
41
44
  }
42
45
 
43
- const findHost = this.req.headers.host.indexOf(':');
44
- this.host = findHost === -1 ? this.req.headers.host : this.req.headers.host.slice(0, findHost);
46
+ let ipcf = this.get('cf-connecting-ip');
47
+ let ipx = this.get('x-forwarded-for');
48
+ if(ipcf){
49
+ this.ip = ipcf;
50
+ }else if(ipx){
51
+ this.ip = ipx.split(',')[0];
52
+ }else{
53
+ this.ip = this.socket.remoteAddress;
54
+ }
55
+
56
+ if(this.socket.servername){
57
+ this.host = this.socket.servername;
58
+ }else{
59
+ const findHost = this.req.headers.host.indexOf(':');
60
+ this.host = findHost === -1 ? this.req.headers.host : this.req.headers.host.slice(0, findHost);
61
+ }
45
62
 
46
63
  this.method = this.req.headers.upgrade === 'websocket' ? 'websocket' : this.req.method.toLowerCase();
47
64
 
@@ -79,6 +96,9 @@ module.exports = class{
79
96
  update(call){
80
97
  this.callback = call;
81
98
  }
99
+ traffic(f){
100
+ this.log = f;
101
+ }
82
102
 
83
103
  code(status){
84
104
  this.status = status;
@@ -145,13 +165,15 @@ module.exports = class{
145
165
  }
146
166
 
147
167
  writeHead(){
148
- this.header['x-powered-by'] = `R938`;
168
+ this.header['x-powered-by'] = powered.by;
149
169
 
150
170
  const head = tools.head2line(this.header);
151
171
  const statusLine = `HTTP/1.1 ${this.status} ${tools.statusText(this.status)}`;
152
172
  const headLine = `${statusLine}\r\n${head}\r\n\r\n`;
153
173
  this.write(Buffer.from(headLine));
154
174
 
175
+ this.log();
176
+
155
177
  return this;
156
178
  }
157
179
  write(data, callback){
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name":"birdpack",
3
3
  "description": "BirdPack web framework is a tool for web server via TCP HTTP supporting websocket focusing on speed.",
4
4
  "author":"R938",
5
- "license":"r938",
6
- "version":"1.0.2",
5
+ "license":"R938",
6
+ "version":"1.0.4",
7
7
  "main": "index.js"
8
8
  }