//jsonServer 服务端 import JSON; import string.aasdl; namespace web.rpc; class jsonServer{ ctor(external){}; rpc = { external = external; _rpcResponse = function(reqData,$){ if( ! reqData ){ return { error = { code = -32700; message = "Invalid JSON was received by the server." }; }; }; if( ! (reqData[["method"]] ) ){ return { id = reqData[["id"]]; error = { code = -32600; message = "Invalid Request The JSON sent is not a valid Request object." }; } }; if(!owner.external){ return { id = reqData[["id"]]; error = { code = -32601; message = "The method does not exist / is not available.." }; } } var method = reqData[["method"]]; if(method=="?"){ if(!owner.aasdl){ owner.aasdl = ..string.aasdl(owner.external); } return { result = owner.aasdl; id = reqData.id; } } var success,result,err; var ns,m = ..string.match(method,"(.+)\.([^.]+)$"); if( ns && m ){ var obj = ..table.get(ns,owner.external); if( (type(obj) == type.table ) && obj[m] ){ if( m[1] == '$'# ){ if(reqData.params) success,result,err = call(obj[m],obj,$,..table.unpackArgs(reqData.params) ); else success,result,err= call(obj[m],obj,$); } else { if(reqData.params) success,result,err = call(obj[m],obj,..table.unpackArgs(reqData.params) ); else success,result,err= call(obj[m],obj); } } else { return { id = reqData[["id"]]; error = { code = -32601; message = "The method does not exist / is not available.." }; } } } else { if(owner.external[method] ){ if( method[1] == '$'# ){ if(reqData.params) success,result,err = call(owner.external[method],owner.external,$,..table.unpackArgs(reqData.params) ); else success,result,err = call(owner.external[method],owner.external,$); } else { if(reqData.params) success,result,err = call(owner.external[method],owner.external,..table.unpackArgs(reqData.params) ); else success,result,err = call(owner.external[method],owner.external); } } else { return { id = reqData[["id"]]; error = { code = -32601; message = "The method does not exist / is not available.." }; } } } if(!success){ err = result; } if((result === null) && (err!==null)){ if( type(err) == type.string ){ err = { code =-32603; message = err; } } elseif( type(err) == type.number ){ err = { code = err; } } elseif( err[["code"]] || err[["message"]] ){ } else { err = { code =-32603; } } } else { err = null; } return { @{ _defined = {"result"}; _type="object"}; error = err; result = result; id = reqData.id; } } _beginRpcResponse = function($,request,response){ if( request.method != 'POST' ) return; if(!owner.external) owner.external=this; var reqData = request.postData(); if( reqData && owner.beforeJsonParse ) { reqData = owner.beforeJsonParse(reqData); } if(reqData) reqData = ..JSON.tryParse(reqData); if( ! reqData ){ owner._write({error = { code = -32700; message = ..string.concat("Invalid JSON was received by the server."); }},response) return; }; if(#reqData){ var transaction = {} for(i=1;#reqData;1){ var repData = owner._rpcResponse(reqData[i],$); if( reqData[i].id ) { repData.id = reqData[i].id; repData.jsonrpc = "2.0"; ..table.push(transaction,repData); }; } if(#transaction){ owner._write(transaction,response); }; return; }; var repData = owner._rpcResponse(reqData,$); if(reqData.id!=null) { repData.id = reqData.id; owner._write(repData,response); } }; _write = function(repData,response){ repData.jsonrpc = "2.0"; var jsonData = ..JSON.stringify(repData); if( owner.afterJsonStringify ) { jsonData = owner.afterJsonStringify(jsonData); if(!jsonData) return true; } response.contentType = "text/json"; return response.write(jsonData); }; run = function($){ var this = owner; if(!$) $ = ..request; var request,response = ..request,..response; try{ this._beginRpcResponse($,request,response); } catch(e){ if( this.onError ) { this.onError(e,request.postData()); } this._write({ error = { code = -32603/*_JSONRPC_INTERNAL_ERROR*/; message = ..string.concat( "Internal JSON-RPC Error:",e); }; },response) }; } } } /**intellisense() web.rpc.jsonServer = 基于HTTP协议的JSON-RPC 2.0服务端\n需要在HTTP服务器上运行\n[关于JSON-RPC 2.0](http://www.jsonrpc.org/specification) web.rpc.jsonServer() = 创建JSON-RPC 2.0服务端\n可选在构造参数中指定监听客户端调用的监听器对象\n如果不指定参数,保用对象自身监听客户端调用\n!stdwebrpcjsonServer. !stdwebrpcjsonServer.? = 客户端可以调用的远程对象名或远程方法名字,\n客户端传过来的params参数必须是数组\n服务端会展开此数组作为函数的调用参数\n函数第一个返回值指定为客户端获取的result返回值\n函数的第二个返回值指定为客户端error错误对象\n错误对象可以是数值,字符串、或符合JSON-RPC2.0协议的表对象,\n!web_rpcJsonClient. end intellisense**/ /**intellisense(!stdwebrpcjsonServer) rpc.run() = 运行JSON-RPC服务端响应用户请求\n可选在函数参数中所有名字首字符为$的回调函数的首个回调$参数,\n$参数默认为request rpc.external = 指定包含客户端可以调用的远程函数的表对象,可嵌套子表\n\n如果远程函数名第一个字符是$,则第一个回调参数为$,$对象由run函数指定,\n如果创建服务端对象的构造参数中没有指定表,\n这个对象默认指向对象自身\n可在调用run函数之前更改此对象 rpc.onError = @.onError = function(err,requestData){ __/*服务器内部错误时触发此事件\nerr为抛出的异常对象,一般为错误信息\nrequestData为客户端发送的请求数据*/ } rpc.aasdl = 指定自定义的aasdl\n如果不指定,服务端会根据external自动生成aasdl\n如果客户端请求的方法名为"?"时,返回此属性,\n[关于aasdl](https://github.com/aardio/aardio-js/blob/master/AASDL.md) rpc.beforeJsonParse = @.beforeJsonParse = function(jsonData){ __/*可以在这里解密客户端数据,返回null中止本次调用*/ return jsonData; } rpc.afterJsonStringify = @.afterJsonStringify = function(jsonData){ __/*可以在这里加密服务端JSON,返回null中止本次调用*/ return jsonData; } end intellisense**/ /**intellisense() _JSONRPC_PARSE_ERROR=@-32700/*_JSONRPC_PARSE_ERROR*/ _JSONRPC_INVALID_REQUEST=@-32600/*_JSONRPC_INVALID_REQUEST*/ _JSONRPC_METHOD_NOTFOUND=@-32601/*_JSONRPC_METHOD_NOTFOUND*/ _JSONRPC_INVALID_PARAMS=@-32602/*_JSONRPC_INVALID_PARAMS*/ _JSONRPC_INTERNAL_ERROR=@-32603/*_JSONRPC_INTERNAL_ERROR*/ end intellisense**/