Comparing version 1.2.4 to 1.3.5
362
awix.js
/** | ||
* awix 1.2.4 | ||
* awix 1.3.5 | ||
* Copyright (c) [2019.08] BraveWang | ||
* This software is licensed under the Mulan PSL v1. | ||
* You can use this software according to the terms and conditions of the Mulan PSL v1. | ||
* You may obtain a copy of Mulan PSL v1 at: | ||
http://license.coscl.org.cn/MulanPSL | ||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||
* See the Mulan PSL v1 for more details. | ||
* This software is licensed under the MPL-2.0. | ||
* You can use this software according to the terms and conditions of the MPL-2.0. | ||
* See the Mulan PSL v1 for more details: | ||
* https://www.mozilla.org/en-US/MPL/2.0/ | ||
*/ | ||
@@ -51,9 +47,12 @@ const fs = require('fs'); | ||
/* | ||
mem, path | ||
暂时只是实现了mem模式,文件会被放在内存里。 | ||
/** | ||
* 如果需要做后续的处理,请设置此选项为需要处理的函数, | ||
* 传递参数为请求过来的headers和stream发送的headers | ||
* (headers, sentHeaders, reqinfo) | ||
* reqinfo是JSON对象包括: | ||
* time 请求时间 | ||
* ip 客户端IP | ||
*/ | ||
on_finish : null, | ||
*/ | ||
upload_mode : 'mem', | ||
//自动解析上传的文件数据 | ||
@@ -74,7 +73,11 @@ parse_upload : true, | ||
//设置服务器超时,毫秒单位,在具体的请求中,可以通过stream设置具体请求的超时时间 | ||
timeout : 20000, | ||
//设置服务器超时,毫秒单位,在具体的请求中,可以通过stream设置具体请求的超时时间。 | ||
timeout : 15000, | ||
//路径最后的/有没有都认为是同一路径,设置true则会在添加路径的时候去掉末尾的/ | ||
ignore_slash : true, | ||
debug : true, | ||
page_404 : 'page not found', | ||
}; | ||
@@ -102,3 +105,3 @@ | ||
this.helper.extName = function (filename) { | ||
if (filename.search(".") < 0) { | ||
if (filename.indexOf(".") < 0) { | ||
return ''; | ||
@@ -110,3 +113,3 @@ } | ||
} | ||
return name_slice[name_slice.length-1]; | ||
return '.' + name_slice[name_slice.length-1]; | ||
}; | ||
@@ -122,3 +125,3 @@ | ||
hash.update(org_name); | ||
return hash.digest('hex') + '.' + the.helper.extName(filename); | ||
return hash.digest('hex') + the.helper.extName(filename); | ||
}; | ||
@@ -159,2 +162,11 @@ | ||
method : '', | ||
url : { | ||
host : '', | ||
protocol : '', | ||
href : '', | ||
origin : '', | ||
port : '', | ||
}, | ||
//客户端IP | ||
ip : '', | ||
//实际的访问路径 | ||
@@ -208,3 +220,3 @@ path : '', | ||
ctx.setHeaders = function(nobj, val = null) { | ||
ctx.setHeader = function(nobj, val = null) { | ||
if (typeof nobj === 'string' && val != null) { | ||
@@ -405,2 +417,31 @@ ctx.res.headers[nobj] = val; | ||
}; | ||
this.findRealPath = function(path, method) { | ||
var route_path = null; | ||
if (path.length > 1 | ||
&& path[path.length-1] == '/' | ||
&& the.config.ignore_slash | ||
) { | ||
path = path.substring(0, path.length-1); | ||
} | ||
if (the.ApiTable[method][path] !== undefined) { | ||
route_path = path; | ||
} | ||
if (route_path && route_path.indexOf('/:') >= 0) { | ||
route_path = null; | ||
} | ||
var parg = null; | ||
if (route_path === null) { | ||
parg = the.findPath(path, method); | ||
} else { | ||
parg = { | ||
args : {}, | ||
key : route_path | ||
}; | ||
} | ||
return parg; | ||
}; | ||
@@ -414,46 +455,3 @@ /** | ||
this.execRequest = function (ctx) { | ||
var pk = null; | ||
var route_key = null; | ||
/* | ||
路由处理会自动处理末尾的/, | ||
/content/123和/content/123/是同一个请求 | ||
*/ | ||
if (ctx.path.length > 1 | ||
&& ctx.path[ctx.path.length-1] == '/' | ||
&& the.config.ignore_slash | ||
) { | ||
ctx.path = ctx.path.substring(0, ctx.path.length-1); | ||
} | ||
if (the.ApiTable[ctx.method][ctx.path] !== undefined) { | ||
route_key = ctx.path; | ||
} | ||
/* | ||
如果发现了路径,但是路径和带参数的路径一致。 | ||
这需要作为参数处理,此时重置为null。 | ||
*/ | ||
if (route_key && route_key.indexOf('/:') >= 0) { | ||
route_key = null; | ||
} | ||
if (route_key === null) { | ||
pk = the.findPath(ctx.path, ctx.method); | ||
if (pk !== null) { | ||
ctx.args = pk.args; | ||
route_key = pk.key; | ||
} | ||
} | ||
if (route_key === null) { | ||
//res.statusCode = 404; | ||
ctx.stream.respond({ | ||
':status' : 404 | ||
}, {endStream : true}); | ||
return ; | ||
} | ||
ctx.routepath = route_key; | ||
var R = the.ApiTable[ctx.method][route_key]; | ||
var R = the.ApiTable[ctx.method][ctx.routepath]; | ||
ctx.requestCall = R.ReqCall; | ||
@@ -463,10 +461,23 @@ ctx.name = R.name; | ||
ctx.group = '/' + R.routeArr[0]; | ||
if (!the.api_group_table[ctx.group] | ||
|| !the.api_group_table[ctx.group][ctx.routepath] | ||
) { | ||
ctx.group = ''; | ||
} | ||
if ( | ||
(ctx.method === 'POST' || ctx.method === 'PUT' ) | ||
&& ctx.isUpload === true | ||
&& the.config.parse_upload === true | ||
if ((ctx.method == 'POST' || ctx.method == 'PUT' || ctx.method == 'DELETE') | ||
&& !ctx.isUpload && ctx.rawBody.length > 0 | ||
) { | ||
if (ctx.headers['content-type'] && | ||
ctx.headers['content-type'].indexOf('application/x-www-form-urlencoded') >= 0 | ||
) { | ||
ctx.bodyparam = qs.parse( | ||
Buffer.from(ctx.rawBody,'binary').toString('utf8') | ||
); | ||
} else { | ||
ctx.bodyparam = Buffer.from(ctx.rawBody, 'binary').toString('utf8'); | ||
} | ||
} else if (ctx.isUpload && the.config.parse_upload) { | ||
the.parseUploadData(ctx); | ||
ctx.rawBody = ''; //解析文件数据后,清理掉原始数据,这可以减少内存占用。 | ||
ctx.rawBody = ''; | ||
} | ||
@@ -494,2 +505,5 @@ | ||
t.realPath = function(apath) { | ||
if (apath == '/' && the.config.ignore_slash) { | ||
return t.group_name; | ||
} | ||
if (apath[0]!=='/') { | ||
@@ -651,3 +665,5 @@ if (t.group_name!=='/') { | ||
} catch (err) { | ||
console.log(err); | ||
if (the.config.debug) { | ||
console.log(err); | ||
} | ||
if (!ctx.stream.headersSent) { | ||
@@ -770,19 +786,24 @@ ctx.res.headers[':status'] = 500; | ||
this.reqHandler = function (stream, headers) { | ||
var ctx = the.context(); | ||
ctx.method = headers[':method']; | ||
ctx.headers = headers; | ||
ctx.stream = stream; | ||
if (ctx.method === 'POST' || ctx.method === 'PUT' || ctx.method === 'DELETE') { | ||
ctx.isUpload = the.checkUploadHeader(headers['content-type']); | ||
var remote_ip = stream.session.socket.remoteAddress; | ||
if (typeof the.config.on_finish === 'function') { | ||
stream.on('close', () => { | ||
the.config.on_finish( | ||
headers, stream.sentHeaders, | ||
{ | ||
time : (new Date()).toLocaleString("zh-Hans-CN"), | ||
ip : remote_ip | ||
} | ||
); | ||
}); | ||
} | ||
var get_params = url.parse(headers[':path'], true); | ||
if (get_params.pathname == '') { | ||
get_params.pathname = '/'; | ||
if (the.methodList.indexOf(headers[':method']) < 0) { | ||
stream.respond({ | ||
':status' : 405, | ||
'Allow' : the.methodList | ||
}); | ||
stream.end('Method not allowed'); | ||
return ; | ||
} | ||
ctx.path = get_params.pathname; | ||
stream.on('frameError', (err) => { | ||
@@ -792,3 +813,2 @@ stream.close(http2.constants.NGHTTP2_INTERNAL_ERROR); | ||
stream.on('error', (err) => { | ||
ctx.rawBody = ''; | ||
stream.close(http2.constants.NGHTTP2_INTERNAL_ERROR); | ||
@@ -803,21 +823,34 @@ }); | ||
/* stream.on('close', (err) => { | ||
}); */ | ||
var urlobj = url.parse(headers[':path'], true); | ||
if (urlobj.pathname == '') { | ||
urlobj.pathname = '/'; | ||
} | ||
/* | ||
跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。 | ||
并且规范要求,对那些可能会对服务器资源产生改变的请求方法,需要先发送OPTIONS请求获取是否允许跨域以及允许的方法。 | ||
*/ | ||
var real_path = ''; | ||
real_path = the.findRealPath(urlobj.pathname, headers[':method']); | ||
if (the.methodList.indexOf(ctx.method) < 0) { | ||
stream.respond({ | ||
':status' : 405, | ||
'Allow' : the.methodList | ||
}); | ||
stream.end('Method not allowed'); | ||
//stream.close(); | ||
if (real_path === null) { | ||
stream.respond({':status':404}); | ||
stream.end(the.config.page_404); | ||
return ; | ||
} | ||
if (ctx.method == 'GET' || ctx.method == 'OPTIONS') { | ||
var ctx = the.context(); | ||
ctx.method = headers[':method']; | ||
ctx.url.host = headers[':authority']; | ||
ctx.url.protocol = headers[':scheme']; | ||
ctx.url.href = urlobj.href; | ||
ctx.url.origin = `${headers[':scheme']}://${headers[':authority']}${headers[':path']}`; | ||
ctx.ip = stream.session.socket.remoteAddress; | ||
ctx.stream = stream; | ||
ctx.headers = headers; | ||
ctx.path = urlobj.pathname; | ||
ctx.routepath = real_path.key; | ||
ctx.args = real_path.args; | ||
ctx.param = urlobj.query; | ||
if (headers[':method'] == 'GET' || headers[':method'] == 'OPTIONS') { | ||
//应对恶意请求,请求类型不能携带主体数据,这时候如果有数据则立即关闭请求。 | ||
@@ -830,39 +863,28 @@ stream.on('data', (data) => { | ||
}); | ||
} | ||
if (ctx.method == 'OPTIONS') { | ||
if (the.config.cors) { | ||
ctx.setHeaders({ | ||
':status' : 200, | ||
'Access-control-allow-origin' : the.config.cors, | ||
'Access-control-allow-methods' : the.methodList | ||
}); | ||
if (ctx.method == 'OPTIONS') { | ||
if (the.config.cors) { | ||
ctx.setHeaders({ | ||
':status' : 200, | ||
'Access-control-allow-origin' : the.config.cors, | ||
'Access-control-allow-methods' : the.methodList | ||
}); | ||
} | ||
if (the.config.auto_options) { | ||
stream.respond(ctx.res.headers); | ||
stream.end(); | ||
return ; | ||
} | ||
} | ||
if (the.config.auto_options) { | ||
stream.respond(ctx.res.headers); | ||
stream.end(); | ||
return ; | ||
} else { | ||
return the.execRequest(ctx); | ||
} | ||
} | ||
else if (ctx.method=='GET') { | ||
return the.execRequest(ctx); | ||
} else if (ctx.method == 'POST' || ctx.method == 'PUT' || ctx.method == 'DELETE') { | ||
if (parseInt(headers['content-length']) > the.config.body_max_size) { | ||
stream.respond({ | ||
':status' : 413 | ||
}); | ||
stream.end( | ||
'Out of limit('+the.config.body_max_size+' Bytes)' | ||
); | ||
//stream.close(); | ||
return ; | ||
} | ||
stream.on('data',(data) => { | ||
//return the.execRequest(ctx); | ||
} else if (ctx.method == 'POST' | ||
|| ctx.method == 'PUT' | ||
|| ctx.method == 'DELETE' | ||
) { | ||
ctx.isUpload = the.checkUploadHeader(headers['content-type']); | ||
var total_length = 0; | ||
stream.on('data', (data) => { | ||
total_length += data.length; | ||
ctx.rawBody += data.toString('binary'); | ||
if (ctx.rawBody.length > the.config.body_max_size) { | ||
if (total_length > the.config.body_max_size) { | ||
ctx.rawBody = ''; | ||
stream.respond({ | ||
@@ -874,27 +896,12 @@ ':status' : 413 | ||
); | ||
//http2.constants.NGHTTP2_FRAME_SIZE_ERROR | ||
//stream.close(); | ||
} | ||
}); | ||
stream.on('end',() => { | ||
if (stream.closed) { | ||
return ; | ||
} | ||
} | ||
if (! ctx.isUpload) { | ||
if (headers['content-type'] && | ||
headers['content-type'].indexOf('application/x-www-form-urlencoded') >= 0 | ||
) { | ||
ctx.bodyparam = qs.parse( | ||
Buffer.from(ctx.rawBody,'binary').toString('utf8') | ||
); | ||
} else { | ||
ctx.bodyparam = Buffer.from(ctx.rawBody, 'binary').toString('utf8'); | ||
} | ||
} | ||
return the.execRequest(ctx); | ||
}); | ||
} | ||
stream.on('end',() => { | ||
if (stream.closed) { | ||
return ; | ||
} | ||
return the.execRequest(ctx); | ||
}); | ||
}; | ||
@@ -934,18 +941,2 @@ | ||
var serv = null; | ||
if (the.config.https_on) { | ||
try { | ||
the.config.server_options.key = fs.readFileSync(the.config.key); | ||
the.config.server_options.cert = fs.readFileSync(the.config.cert); | ||
serv = http2.createSecureServer(the.config.server_options); | ||
} catch(err) { | ||
console.log(err); | ||
process.exit(-1); | ||
} | ||
} else { | ||
serv = http2.createServer(the.config.server_options); | ||
} | ||
serv.on('stream', the.reqHandler); | ||
var onSession = (sess) => { | ||
@@ -969,7 +960,21 @@ var closeSession = (err) => { | ||
var serv = null; | ||
if (the.config.https_on) { | ||
try { | ||
the.config.server_options.key = fs.readFileSync(the.config.key); | ||
the.config.server_options.cert = fs.readFileSync(the.config.cert); | ||
serv = http2.createSecureServer(the.config.server_options); | ||
} catch(err) { | ||
console.log(err); | ||
process.exit(-1); | ||
} | ||
} else { | ||
serv = http2.createServer(the.config.server_options); | ||
} | ||
serv.on('stream', the.reqHandler); | ||
serv.on('session', onSession); | ||
serv.on('sessionError', (err, sess) => { | ||
//console.log(sess); | ||
//console.log(err); | ||
if (the.config.debug) { | ||
console.log('--DEBUG--SESSION-ERROR--:',err); | ||
} | ||
sess.close(); | ||
@@ -979,3 +984,5 @@ }); | ||
serv.on('tlsClientError', (err, tls) => { | ||
//console.log(err, tls); | ||
if (the.config.debug) { | ||
console.log('--DEBUG--TLS--CONNECT--:', err); | ||
} | ||
}); | ||
@@ -998,3 +1005,2 @@ | ||
} | ||
serv.listen(port, host); | ||
@@ -1008,3 +1014,3 @@ return serv; | ||
*/ | ||
this.ants = function(port = 9876, host = '0.0.0.0', num = 0) { | ||
this.daemon = function(port = 9876, host = '0.0.0.0', num = 0) { | ||
if (process.argv.indexOf('--daemon') > 0) { | ||
@@ -1085,3 +1091,3 @@ | ||
cluster.on('message', (worker, message, handle) => { | ||
if(message.type === 'access') { | ||
if(message.type === 'success') { | ||
console.log(message); | ||
@@ -1088,0 +1094,0 @@ } else { |
{ | ||
"name": "awix", | ||
"version": "1.2.4", | ||
"version": "1.3.5", | ||
"description": "a powerful web framework, build on module http2 and async/await.", | ||
@@ -5,0 +5,0 @@ "main": "awix.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
35354
2
940