/* * sers.ServiceStation.js * Date : 2022-05-07 * Version: 2.1.18-preview9 * author : Lith * email : serset@yeah.net */ ; sers = { version: '2.1.18-preview9' }; /* * vit.js 扩展 * author : Lith * email : serset@yeah.net */ ; (function (vit) { // vit工具函数 ; (function () { vit.stringToBytes = function (str) { if (!str) return []; var bytes = new Array(); var len, c; len = str.length; for (var i = 0; i < len; i++) { c = str.charCodeAt(i); if (c >= 0x010000 && c <= 0x10FFFF) { bytes.push(((c >> 18) & 0x07) | 0xF0); bytes.push(((c >> 12) & 0x3F) | 0x80); bytes.push(((c >> 6) & 0x3F) | 0x80); bytes.push((c & 0x3F) | 0x80); } else if (c >= 0x000800 && c <= 0x00FFFF) { bytes.push(((c >> 12) & 0x0F) | 0xE0); bytes.push(((c >> 6) & 0x3F) | 0x80); bytes.push((c & 0x3F) | 0x80); } else if (c >= 0x000080 && c <= 0x0007FF) { bytes.push(((c >> 6) & 0x1F) | 0xC0); bytes.push((c & 0x3F) | 0x80); } else { bytes.push(c & 0xFF); } } return bytes; }; vit.bytesToString = function (bytes) { if (!bytes) return null; if (typeof bytes === 'string') { return bytes; } var str = '', _arr = bytes; for (var i = 0; i < _arr.length; i++) { var one = _arr[i].toString(2), v = one.match(/^1+?(?=0)/); if (v && one.length == 8) { var bytesLength = v[0].length; var store = _arr[i].toString(2).slice(7 - bytesLength); for (var st = 1; st < bytesLength; st++) { store += _arr[st + i].toString(2).slice(2); } str += String.fromCharCode(parseInt(store, 2)); i += bytesLength - 1; } else { str += String.fromCharCode(_arr[i]); } } return str; }; vit.bytesToObject = function (bytes) { return eval('(' + vit.bytesToString(bytes) + ')'); }; vit.objectSerializeToString = function (obj) { if (obj == null || typeof (obj) == 'undefined') { return null; } var str = obj; if (typeof (str) != 'string') { str = JSON.stringify(str); } return str; }; vit.objectSerializeToBytes = function (obj) { var str = vit.objectSerializeToString(obj); return vit.stringToBytes(str); }; //合并连个数组 vit.arrayConcat = function (a, b, count) { //a.push.apply(a, b); if (!count) count = b.length; for (var t = 0; t < count; t++) { a.push(b[t]); } return a; }; vit.bytesToArrayBuffer = function (bytes) { return new Uint8Array(bytes).buffer; }; vit.bytesToDataView = function (bytes) { return new DataView(vit.bytesToArrayBuffer(bytes)); }; vit.arrayBufferToBytes = function (arrayBuffer) { return Array.from(new Uint8Array(arrayBuffer)); }; vit.dataViewToBytes = function (dataView) { return vit.arrayBufferToBytes(dataView.buffer); }; vit.bytesGetInt32 = function (bytes, index) { return new DataView(new Uint8Array(bytes).buffer).getInt32(index || 0, true); }; vit.int32ToBytes = function (int32) { var buffer = new ArrayBuffer(4); var view = new DataView(buffer); view.setInt32(0, int32, true); return vit.dataViewToBytes(view); }; vit.bytesInsertInt32 = function (bytes, index, int32) { var bytesInt32 = vit.int32ToBytes(int32); bytes.splice(index, 0, bytesInt32[0], bytesInt32[1], bytesInt32[2], bytesInt32[3]); return bytes; }; // return '112233445566778899aabbccddee' vit.guid = function guid() { function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } return (S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4()); }; })(); //vit.logger (function (logger) { /*** 对Date的扩展,将 Date 转化为指定格式的String * 月(M)、日(d)、12小时(h)、24小时(H)、分(m)、秒(s)、周(E)、季度(q) * 可以用 1-2 个占位符 * 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字) * eg: * (newDate()).pattern("yyyy-MM-dd hh:mm:ss.S")==> 2006-07-02 08:09:04.423 * (new Date()).pattern("yyyy-MM-dd E HH:mm:ss") ==> 2009-03-10 二 20:09:04 * (new Date()).pattern("yyyy-MM-dd EE hh:mm:ss") ==> 2009-03-10 周二 08:09:04 * (new Date()).pattern("yyyy-MM-dd EEE hh:mm:ss") ==> 2009-03-10 星期二 08:09:04 * (new Date()).pattern("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18 */ Date.prototype.pattern = function (fmt) { var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "h+": this.getHours() % 12 == 0 ? 12 : this.getHours() % 12, //小时 "H+": this.getHours(), //小时 "m+": this.getMinutes(), //分 "s+": this.getSeconds(), //秒 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 "S": this.getMilliseconds() //毫秒 }; var week = { "0": "/u65e5", "1": "/u4e00", "2": "/u4e8c", "3": "/u4e09", "4": "/u56db", "5": "/u4e94", "6": "/u516d" }; if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); } if (/(E+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "/u661f/u671f" : "/u5468") : "") + week[this.getDay() + ""]); } for (var k in o) { if (new RegExp("(" + k + ")").test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); } } return fmt; }; //type: info/error //e: pass error when type is error //function(message,type,e){ } logger.onmessage; logger.error = function (e, message) { var msgBody = new Date().pattern("[mm:ss.S]") + '[error]' + (message || e.message || ''); //console.log(e); //console.log(msgBody); try { if (logger.onmessage) logger.onmessage(msgBody, 'error', e); } catch (e) { } }; logger.info = function (message) { var msgBody = new Date().pattern("[mm:ss.S]") + '[info]' + message; //console.log(msgBody); try { if (logger.onmessage) logger.onmessage(msgBody, 'info'); } catch (e) { } }; })(vit.logger = {}); })('undefined' === typeof (vit) ? vit = {} : vit); /* * sers.CL.js 扩展 * PipeFrame CL.DeliveryClient RequestAdaptor CL.OrganizeClient * author : Lith * email : serset@yeah.net */ ; (function (CL) { var logger = vit.logger; function PipeFrame() { this.write = function (arrayBuffer) { queueBuff.push(new Uint8Array(arrayBuffer)); buffLen += arrayBuffer.byteLength; }; //DataView list var queueBuff = []; var buffLen = 0; var QueueBuff_dataLenOfRemoved = 0; //return bytes function read(lenToPop) { if (buffLen < lenToPop) { return; } buffLen -= lenToPop; var dataToPop = []; var copyedIndex = 0; while (copyedIndex < lenToPop) { var leftCount = lenToPop - copyedIndex; var cur = queueBuff[0]; if (QueueBuff_dataLenOfRemoved != 0) { cur = cur.subarray(QueueBuff_dataLenOfRemoved); } if (cur.length <= leftCount) { //dataToPop 数据长 vit.arrayConcat(dataToPop, cur); copyedIndex += cur.length; QueueBuff_dataLenOfRemoved = 0; queueBuff.shift(); } else { //queueBuff 数据长 vit.arrayConcat(dataToPop, cur, leftCount); copyedIndex += leftCount; QueueBuff_dataLenOfRemoved += leftCount; } } return dataToPop; }; var fileLen = -1; //return bytes this.readSersFile = function () { if (fileLen < 0) { var fileLen_bytes = read(4); if (!fileLen_bytes) { return null; } fileLen = vit.bytesGetInt32(fileLen_bytes, 0); } if (buffLen < fileLen) return null; var data = read(fileLen); fileLen = -1; return data; }; }; CL.DeliveryClient = function () { var self = this; self.host = "ws://127.0.0.1:4503"; //function (bytes) { } self.event_onGetFrame; // function () { } self.event_onDisconnected; self.sendFrame = function (bytes) { if (!webSocket) throw new Error('连接尚未建立,无法发送数据,请先建立连接'); vit.bytesInsertInt32(bytes, 0, bytes.length); var dataView = vit.bytesToDataView(bytes); webSocket.send(dataView); }; var pipe = new PipeFrame(); var webSocket = null; //callback: function(success){ } self.connect = function (callback) { if (webSocket) throw new Error('连接尚未断开,不可再次连接'); webSocket = new WebSocket(self.host); webSocket.binaryType = "arraybuffer"; webSocket.onerror = function (event) { self.close(); }; webSocket.onclose = function () { self.close(); }; //成功被调用 或者超时被调用 var isCalled = false; var onCall = function (success) { if (isCalled) return; isCalled = true; callback(success); }; setTimeout(onCall, 10000); webSocket.onopen = function (event) { onCall(true); }; webSocket.onmessage = function (event) { var arrayBuffer = event.data; pipe.write(arrayBuffer); //bytes var frame; while (frame = pipe.readSersFile()) { try { self.event_onGetFrame(frame); } catch (e) { logger.error(e); } } }; }; self.close = function () { if (!webSocket) throw new Error('尚未建立连接,无需断开'); //(x.1) close socket try { webSocket.close(); } catch (e) { logger.error(e); } webSocket = null; logger.info('[sers.CL]DeliveryClient.event_onDisconnected'); //(x.2) event_onDisconnected if (self.event_onDisconnected) { try { self.event_onDisconnected(); } catch (e) { logger.error(e); } } }; }; function RequestAdaptor() { var EFrameType = { request: 1, reply: 2, message: 3 }; var ERequestType = { app: 0, heartBeat: 1 }; var organizeVersion = "Sers.Mq.Socket.v1"; var self = this; // requestKey -> requestCallback var organizeToDelivery_RequestMap = {}; var reqKeyIndex = 100; //事件,向外部delivery发送字节流时被调用 //function (bytes) { } self.event_onSendFrame; //事件,delivery向Organize发送请求时被调用 //function (apiRequestMessage_bytes, callback) { } // callback: function(apiReplyMessage_bytes){ } self.event_onGetRequest; //事件,delivery向Organize发送请求时被调用 //function (bytes) { } self.event_onGetMessage; //请求超时时间(单位ms,默认300000) self.requestTimeoutMs = 300000; //外部调用,当外部从delivery读取到数据时调用 self.deliveryToOrganize_onGetMessageFrame = function (bytes) { //deliveryToOrganize_ProcessFrame var msgType = bytes[0]; var msgData = bytes.slice(2); switch (msgType) { case EFrameType.reply: var t = unpackReqRepFrame(msgData); var reqKey = t.reqKey; var replyData = t.oriData; var reqCallback = organizeToDelivery_RequestMap[reqKey]; if (reqCallback) { delete organizeToDelivery_RequestMap[reqKey]; reqCallback(replyData); } break; case EFrameType.request: var t = unpackReqRepFrame(msgData); var reqKey_bytes = t.reqKey_bytes; var requestData = t.oriData; var requestType = bytes[1]; deliveryToOrganize_onGetRequest(requestType, reqKey_bytes, requestData); break; case EFrameType.message: self.event_onGetMessage(msgData); break; } }; function deliveryToOrganize_onGetRequest(requestType, reqKey_bytes, requestData) { switch (requestType) { case ERequestType.app: self.event_onGetRequest(requestData, function (apiReplyMessage_bytes) { deliveryToOrganize_sendReply(reqKey_bytes, apiReplyMessage_bytes); }); return; case ERequestType.heartBeat: var version = vit.bytesToString(requestData); if (version == organizeVersion) { // send reply deliveryToOrganize_sendReply(reqKey_bytes, requestData); } else { // send reply deliveryToOrganize_sendReply(reqKey_bytes, [0]); } return; } } function deliveryToOrganize_sendReply(reqKey_bytes, replyData) { var repFrame = packageReqRepFrame(reqKey_bytes, replyData); delivery_sendFrame(EFrameType.reply, 0, repFrame); } //callback: ({success,replyData})=>{ } self.sendRequest = function (requestType, requestData, callback) { var reqKey = reqKeyIndex++; //成功被调用 或者超时被调用 var isCalled = false; var onRequestFinish = function (success, replyData) { if (isCalled) return; isCalled = true; //if (!success) delete organizeToDelivery_RequestMap[reqKey]; if (callback) callback({ success: success, replyData: replyData }); }; setTimeout(onRequestFinish, self.requestTimeoutMs); organizeToDelivery_RequestMap[reqKey] = function (replyData) { onRequestFinish(true, replyData); }; var reqKey_bytes = vit.int32ToBytes(reqKey); reqKey_bytes.push(0, 0, 0, 0); var reqRepFrame = packageReqRepFrame(reqKey_bytes, requestData); delivery_sendFrame(EFrameType.request, requestType || ERequestType.app, reqRepFrame); }; self.sendMessage = function (message_bytes) { delivery_sendFrame(EFrameType.message, 0, message_bytes); }; function delivery_sendFrame(msgType, requestType, bytes) { bytes.splice(0, 0, msgType, requestType); self.event_onSendFrame(bytes); } //reqKey_bytes 8字节 //返回 reqRepFrame[bytes] function packageReqRepFrame(reqKey_bytes, oriData) { return vit.arrayConcat(reqKey_bytes, oriData); } // 返回对象 {reqKey:reqKey,reqKey_bytes:reqKey_bytes, oriData:oriData} function unpackReqRepFrame(reqRepFrame) { var reqKey = vit.bytesGetInt32(reqRepFrame, 0); return { reqKey: reqKey, reqKey_bytes: reqRepFrame.slice(0, 8), oriData: reqRepFrame.slice(8) }; } } //websocketHost demo: "ws://127.0.0.1:4503" CL.OrganizeClient = function (websocketHost) { var self = this; var delivery = new CL.DeliveryClient(); //连接秘钥,用以验证连接安全性。服务端和客户端必须一致 self.secretKey = "SersCL"; //设置websocket host 地址 demo: "ws://127.0.0.1:4503" self.setHost = function (websocketHost) { delivery.host = websocketHost; }; self.setHost(websocketHost); var requestAdaptor = new RequestAdaptor(); //初始化requestAdaptor 和 delivery (function () { delivery.event_onGetFrame = function (bytes) { requestAdaptor.deliveryToOrganize_onGetMessageFrame(bytes); }; requestAdaptor.event_onGetRequest = function (apiRequestMessage_bytes, callback) { self.event_onGetRequest(apiRequestMessage_bytes, callback); }; requestAdaptor.event_onGetMessage = function (bytes) { self.event_onGetMessage(bytes); }; requestAdaptor.event_onSendFrame = function (bytes) { delivery.sendFrame(bytes); }; delivery.event_onDisconnected = function () { if (self.event_onDisconnected) self.event_onDisconnected.apply(self, arguments); }; })(); //function (event) { } self.event_onDisconnected = null; //function (apiRequestMessage_bytes,callback) { } // callback function(apiReplyMessage_bytes){} self.event_onGetRequest = null; //function (bytes) { } self.event_onGetMessage = null; //callback: ({success,replyData})=>{ } self.sendRequest = function (requestData, callback) { requestAdaptor.sendRequest(null, requestData, callback); }; self.sendMessage = function (message_bytes) { requestAdaptor.sendMessage(message_bytes); }; //callback: function (success) { } self.connect = function (callback) { delivery.connect(function (success) { //(x.1)连接不成功 if (!success) callback(false); //(x.2)进行权限校验 //setTimeout(function () { self.sendRequest(vit.stringToBytes(self.secretKey), function (args) { let success = args.success, replyData = args.replyData; //(x.x.1)请求不成功 if (!success) { callback(false); return; } //(x.x.2)验证不成功 if (vit.bytesToString(replyData) != 'true') { callback(false); return; } //(x.x.3)验证成功 callback(true); }); //}, 5000); }); }; self.stop = function () { delivery.close(); }; } })(sers.CL || (sers.CL = {})); /* * sers.ServiceStation.js 扩展 * sers.ApiMessage sers.ApiClient sers.MessageClient sers.LocalApiService sers.ServiceStation * author : Lith * email : serset@yeah.net */ ; (function (sers) { var logger = vit.logger; //ApiMessage function ApiMessage() { var self = this; //bytes var rpcContextData_OriData; //bytes var value_OriData; //return object self.getRpcData = function () { var strRpc = vit.bytesToString(rpcContextData_OriData); if (!strRpc) return {}; return eval('(' + strRpc + ')'); }; //return bytes self.getValueBytes = function () { return value_OriData; }; //return string self.getValueString = function () { var strValue = vit.bytesToString(value_OriData); return strValue; }; //return object self.getValueObject = function () { return eval('(' + self.getValueString() + ')'); }; self.initAsApiRequestMessage = function (route, arg, httpMethod) { var rpcData = { "route": route, "caller": { "rid": vit.guid(), "callStack": [], // parentRequestGuid array "source": "Internal" }, "http": { "method": httpMethod || "GET" } }; rpcContextData_OriData = vit.objectSerializeToBytes(rpcData); value_OriData = vit.objectSerializeToBytes(arg); }; self.package = function () { return ApiMessage.package(rpcContextData_OriData, value_OriData); }; self.unpackage = function (oriData) { var files = ApiMessage.unpackage(oriData); rpcContextData_OriData = files[0]; value_OriData = files[1]; }; }; //arg files(bytes[]) //return bytes ApiMessage.package = function () { var files = arguments; var oriData = []; for (var t = 0; t < files.length; t++) { var file = files[t]; vit.arrayConcat(oriData, vit.int32ToBytes(file.length)); vit.arrayConcat(oriData, file); } return oriData; }; //arg oriData(bytes) //return bytes[] file[] ApiMessage.unpackage = function (oriData) { var files = []; var curIndex = 0; while (curIndex < oriData.length) { var fileLength = vit.bytesGetInt32(oriData, curIndex); var fileContent = oriData.slice(curIndex + 4, curIndex + 4 + fileLength); curIndex += 4 + fileLength; files.push(fileContent); } return files; }; sers.ApiMessage = ApiMessage; //ApiClient sers.ApiClient = function (organizeClient) { //(string route, object arg, string httpMethod, function callback) // callback: function({success,replyData_bytes,replyRpcData_object}) this.callApiAsync = function (route, arg, httpMethod, callback) { var apiRequestMessage = new ApiMessage(); apiRequestMessage.initAsApiRequestMessage(route, arg, httpMethod); organizeClient.sendRequest(apiRequestMessage.package(), function (args) { let success = args.success, replyData = args.replyData; if (!callback) return; if (!success) { callback({ success: false }); } else { var apiMessage = new ApiMessage(); apiMessage.unpackage(replyData); var value = apiMessage.getValueBytes(); var replyRpcData = apiMessage.getRpcData(); callback({ success: true, replyData_bytes: value, replyRpcData_object: replyRpcData }); } }); }; }; //MessageClient sers.MessageClient = function (organizeClient) { let EFrameType = { /// /// publish, msgTitle, msgData /// publish : 0, /// /// subscribe, msgTitle /// subscribe : 1, /// /// unSubscribe, msgTitle /// unSubscribe : 2, /// /// message, msgTitle, msgData /// message : 3 }; function sendFrame(frame) { organizeClient.sendMessage(frame); } this.onGetMessage = (messageData) => { let frame = ApiMessage.unpackage(messageData); let msgType = frame[0][0]; switch (msgType) { case EFrameType.message: let msgTitle = vit.bytesToString(frame[1]); let msgData = frame[2]; this.message_Consumer(msgTitle, msgData); break; } }; // (msgTitle,msgData)=>void this.message_Consumer; this.message_Publish = function (msgTitle, msgData) { //EFrameType.publish, msgTitle, msgData let frame = ApiMessage.package( [EFrameType.publish], vit.stringToBytes(msgTitle), msgData); sendFrame(frame); }; this.message_Subscribe = function (msgTitle) { //EFrameType.subscribe, msgTitle let frame = ApiMessage.package( [EFrameType.subscribe], vit.stringToBytes(msgTitle) ); sendFrame(frame); }; this.message_UnSubscribe = function (msgTitle) { //EFrameType.unSubscribe, msgTitle let frame = ApiMessage.package( [EFrameType.unSubscribe], vit.stringToBytes(msgTitle) ); sendFrame(frame); }; }; //SubscriberManage sers.SubscriberManage = function (messageClient) { this.createSubscribe = (msgTitle, onGetMessage) => { return new sers.MessageSubscriber(this, msgTitle, onGetMessage); }; //消息订阅者 msgTitle -> Subscriber[] let subscriberMap = {}; // subscriber:MessageSubscriber this.message_Subscribe = function (subscriber) { let subscriberList = subscriberMap[subscriber.msgTitle]; if (!subscriberList) { subscriberList=subscriberMap[subscriber.msgTitle] = []; messageClient.message_Subscribe(subscriber.msgTitle); } subscriberList.push(subscriber); }; this.message_UnSubscribe = function (subscriber) { let subscriberList = subscriberMap[subscriber.msgTitle]; if (!subscriberList) { return false; } subscriberList = subscriberList.filter(m => m != subscriber); if (subscriberList.length == 0) { delete subscriberMap[subscriber.msgTitle]; messageClient.message_UnSubscribe(subscriber.msgTitle); } }; this.message_Consumer = function (msgTitle, msgData) { let subscriberList = subscriberMap[msgTitle]; if (!subscriberList || !subscriberList.length) return; for (let subscriber of subscriberList) { try { if (!subscriber || !subscriber.onGetMessage) continue; subscriber.onGetMessage(msgData); } catch (ex) { logger.error(ex); } } }; messageClient.message_Consumer = this.message_Consumer; }; //MessageSubscriber sers.MessageSubscriber = function (subscriberManage,msgTitle, onGetMessage) { this.msgTitle = msgTitle; // bytes=>void this.onGetMessage = onGetMessage; this.subscribe = function () { subscriberManage.message_Subscribe(this); return this; }; this.unSubscribe = function () { subscriberManage.message_UnSubscribe(this); return this; }; }; //LocalApiService sers.LocalApiService = function () { var self = this; // route_httpMethod -> ApiNode // ApiNode: { apiDesc,onInvoke,onInvokeAsync } //onInvoke 和 onInvokeAsync 指定其一即可 // onInvoke: (requestData_bytes,rpcData_object,replyRpcData_object)=>{ return replyData_bytes; } //onInvoke 和 onInvokeAsync 指定其一即可 // onInvokeAsync: (requestData_bytes,rpcData_object,replyRpcData_object,onInvokeFinish)=>{ } // onInvokeFinish :(replyData_bytes)=>{ } var apiNodeMap = {}; //return [ ApiNode ]; //ApiNode {apiDesc:apiDesc } self.getApiNodes = function () { var apiNodes = []; for (var key in apiNodeMap) { apiNodes.push({ apiDesc: apiNodeMap[key].apiDesc }); } return apiNodes; }; //清空已加载的apiNode self.clearApiNodes = function () { apiNodeMap = {}; }; // ApiNode: { apiDesc,onInvoke,onInvokeAsync } //onInvoke 和 onInvokeAsync 指定其一即可 // onInvoke: (requestData_bytes,rpcData_object,replyRpcData_object)=>{ return replyData_bytes; } //onInvoke 和 onInvokeAsync 指定其一即可 // onInvokeAsync: (requestData_bytes,rpcData_object,replyRpcData_object,onInvokeFinish)=>{ } // onInvokeFinish :(replyData_bytes)=>{ } self.addApiNode = function (apiNode) { var apiKey = apiNode.apiDesc.route + '_' + apiNode.apiDesc.extendConfig.httpMethod; apiNodeMap[apiKey] = apiNode; }; // apiInvoke {route: '/JsStation/api', httpMethod: 'GET', name: 'call api in js server', description: 'js作为服务站点', onInvoke,onInvokeAsync} // onInvoke: (requestData_bytes,rpcData_object,replyRpcData_object)=>{ return replyData_bytes; } //onInvoke 和 onInvokeAsync 指定其一即可 // onInvokeAsync: (requestData_bytes,rpcData_object,replyRpcData_object,onInvokeFinish)=>{ } // onInvokeFinish :(replyData_bytes)=>{ } self.addApiInvoke = function (apiInvoke) { var apiDesc = { route: apiInvoke.route, name: apiInvoke.name, description: apiInvoke.description, extendConfig: { httpMethod: apiInvoke.httpMethod } }; self.addApiNode({ apiDesc: apiDesc, onInvoke: apiInvoke.onInvoke, onInvokeAsync: apiInvoke.onInvokeAsync }); }; // apiInvoke {route: '/JsStation/api', httpMethod: 'GET', name: 'call api in js server', description: 'js作为服务站点', onInvoke,onInvokeAsync} // onInvoke: (requestData_bytes,rpcData_object,replyRpcData_object)=>{ return replyData_bytes; } //onInvoke 和 onInvokeAsync 指定其一即可 // onInvokeAsync: (requestData_bytes,rpcData_object,replyRpcData_object,onInvokeFinish)=>{ } // onInvokeFinish :(replyData_bytes)=>{ } self.addApiInvokeArray = function (apiInvokeArray) { for (var apiInvoke of apiInvokeArray) { self.addApiInvoke(apiInvoke); } }; //(Error e,requestData_bytes,rpcData_object,replyRpcData_object) //localApiService.onError = (e,requestData_bytes,rpcData_object,replyRpcData_object)=>{ return {success:false}; } self.onError = function (e, requestData_bytes, rpcData_object, replyRpcData_object) { logger.error(e); var reply = { success: false, error: { errorMessage: e.message, errorDetail: { name: e.name, stack: e.stack } } }; return reply; }; //invoke local api //callback: (apiReplyMessage_bytes)=>{ } self.invokeApiAsync = (apiRequestMessage_bytes, callback) => { //(x.1) 解析请求数据 var apiMessage = new ApiMessage(); apiMessage.unpackage(apiRequestMessage_bytes); var rpcData_object = apiMessage.getRpcData(); var requestData_bytes = apiMessage.getValueBytes(); //(x.2)解析路由获得 处理函数 var route = rpcData_object.route; var httpMethod = rpcData_object.http.method; var apiKey = route + '_' + httpMethod; var apiNode = apiNodeMap[apiKey]; //(x.3)进行处理获得结果数据 var replyRpcData_object = {}, replyData_bytes; var onInvokeFinish = (replyData_bytes) => { //返回结果数据 var apiReplyMessage_bytes = ApiMessage.package( vit.objectSerializeToBytes(replyRpcData_object), replyData_bytes ); callback(apiReplyMessage_bytes); }; if (apiNode) { try { if (apiNode.onInvoke) { replyData_bytes = apiNode.onInvoke(requestData_bytes, rpcData_object, replyRpcData_object); } else if (apiNode.onInvokeAsync) { apiNode.onInvokeAsync(requestData_bytes, rpcData_object, replyRpcData_object, onInvokeFinish); return; } } catch (e) { var reply = self.onError(e, requestData_bytes, rpcData_object, replyRpcData_object); replyData_bytes = vit.objectSerializeToBytes(reply); } } else { var reply = { success: false, error: { errorCode: 404, errorMessage: "Api Not Found", errorDetail: { source: 'from JsStation' } } }; replyData_bytes = vit.objectSerializeToBytes(reply); } onInvokeFinish(replyData_bytes); }; }; //ServiceStation // localApiService org apiClient serviceStationInfo sers.ServiceStation = function () { var self = this; //(x.1) localApiService (function () { self.localApiService = new sers.LocalApiService(); })(); //(x.2) OrganizeClient self.org (function () { self.org = new sers.CL.OrganizeClient("ws://127.0.0.1:4503"); //self.org.event_onDisconnected = function () { // logger.info('[sers.CL]org.event_onDisconnected'); //}; self.org.event_onGetRequest = self.localApiService.invokeApiAsync; })(); //(x.3) apiClient (function () { self.apiClient = new sers.ApiClient(self.org); })(); //(x.4) subscriberManage (function () { let messageClient = new sers.MessageClient(self.org); self.subscriberManage = new sers.SubscriberManage(messageClient); self.org.event_onGetMessage = messageClient.onGetMessage; })(); //(x.5) self.stop = function () { logger.info('[sers.ServiceStation] try stop...'); self.org.stop(); logger.info('[sers.ServiceStation] stoped.'); }; //(x.6) self.serviceStationInfo = { serviceStationName: 'JsStation', serviceStationKey: '', stationVersion: '', info: {} }; //(x.7) var deviceInfo = { deviceKey: ('' + Math.random()).substr(2) }; //(x.8) //callback: function(success){} self.start = function (callback) { logger.info('[sers.CL] try connect...'); self.org.connect(function (success) { if (!success) { logger.info('[sers.CL] org cannot connect to server!'); if (callback) callback(false); return; } //向服务中心注册localApiService logger.info('[ServiceStation] regist serviceStation to ServiceCenter...'); var apiNodes = self.localApiService.getApiNodes(); var serviceStationData = { serviceStationInfo: self.serviceStationInfo, deviceInfo: deviceInfo, apiNodes: apiNodes }; //(string route, object arg, string httpMethod, function callback) // callback: function({success,replyData_bytes,replyRpcData_object}) self.apiClient.callApiAsync("/_sys_/serviceStation/regist", serviceStationData, 'POST', function (args) { let success = args.success, replyData_bytes = args.replyData_bytes, replyRpcData_object = args.replyRpcData_object; if (!success) { logger.info("[ServiceStation] regist - failed"); if (callback) callback(false); return; } var apiRet = vit.bytesToObject(replyData_bytes); if (!apiRet.success) { logger.info("[ServiceStation] regist - failed. reply:" + vit.bytesToString(replyData_bytes)); if (callback) callback(false); return; } logger.info("[ServiceStation] regist - succeed"); if (callback) callback(true); }); }); }; } })(sers);