Created
November 16, 2011 19:09
-
-
Save bastman/1371010 to your computer and use it in GitHub Desktop.
jsonrpc client (as3)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.application.rpc | |
{ | |
/** | |
* ... | |
* @author seb | |
*/ | |
public dynamic class CallbackVO extends Object | |
{ | |
public function CallbackVO(data:Object=null) | |
{ | |
if (data is Object) { | |
for (var key in data) { | |
this[key] = data[key]; | |
} | |
} | |
} | |
public function getScope():Object | |
{ | |
return this["scope"]; | |
} | |
public function setScope(value:Object):void | |
{ | |
this["scope"] = value; | |
} | |
public function getOnError():Function | |
{ | |
return this["error"]; | |
} | |
public function setOnError(value:Function):void | |
{ | |
this["error"] = value; | |
} | |
public function getOnResult():Function | |
{ | |
return this["result"]; | |
} | |
public function setOnResult(value:Function):void | |
{ | |
this["result"] = value; | |
} | |
public function getOnInvoke():Function | |
{ | |
return this["invoke"]; | |
} | |
public function setOnInvoke(value:Function):void | |
{ | |
this["invoke"] = value; | |
} | |
public function getOnProgress():Function | |
{ | |
return this["progress"]; | |
} | |
public function setOnProgress(value:Function):void | |
{ | |
this["progress"] = value; | |
} | |
public function getOnResponse():Function | |
{ | |
return this["response"]; | |
} | |
public function setOnResponse(value:Function):void | |
{ | |
this["response"] = value; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.application.rpc | |
{ | |
import flash.events.Event; | |
import flash.events.ProgressEvent; | |
import flash.events.SecurityErrorEvent; | |
import flash.events.IOErrorEvent; | |
import flash.events.HTTPStatusEvent; | |
import flash.net.URLLoaderDataFormat; | |
import flash.net.URLLoader; | |
import flash.net.URLRequest; | |
import flash.net.URLVariables; | |
import flash.net.URLRequestMethod; | |
import com.adobe.serialization.json.JSON; | |
/** | |
* ... | |
* @author seb | |
*/ | |
public class Client | |
{ | |
// where is your gateway / endpoint url? | |
public var url:String = "http://www.example.com/rpc/json.php"; | |
// do a form post? optional, e.g.field="jsonrpc" --> $_POST["jsonrpc"] | |
public var formFieldName:String = null; | |
public var rpcMethodPrefix:String = null; //e.g."HelloworldServer.Api.Fb."; | |
// global callbacks - are you sure you want to use'em? | |
protected var _callback:CallbackVO; | |
public function getCallback():CallbackVO | |
{ | |
if (!(_callback is CallbackVO)) { | |
_callback = newCallbackVO(); | |
} | |
return _callback; | |
} | |
// inject rpc properties on each rpc call | |
protected var _baseParams:Object = {}; | |
public function get baseParams():Object | |
{ | |
if (!(_baseParams is Object)) { | |
_baseParams = { }; | |
} | |
if ((_baseParams==null)) { | |
_baseParams = { }; | |
} | |
return _baseParams; | |
} | |
public function set baseParams(value:Object) { | |
_baseParams = value; | |
} | |
// singleton | |
private static var _instance:Client; | |
public static function getInstance():Client | |
{ | |
if (!_instance) { | |
_instance = new Client(); | |
} | |
return _instance; | |
} | |
// +++++++++++ constructor +++++++++++++ | |
public function Client() { | |
// constructor code | |
super(); | |
_instance = this; | |
} | |
// ++++++++++ methods +++++++++++++++++++ | |
public function newCallbackVO():CallbackVO | |
{ | |
return new CallbackVO(); | |
} | |
public function invoke($method:String, $params:Array, $on:Object):RpcVO | |
{ | |
if (!($method is String)) { | |
$method = ""; | |
} | |
if (!($params is Array)) { | |
$params = []; | |
} | |
var rpc:RpcVO = _newRpc( | |
url, | |
$method, | |
$params, | |
baseParams | |
); | |
rpc.on = new CallbackVO($on); | |
rpc.client = this; | |
rpc.loader.load(rpc.request); | |
return rpc; | |
} | |
protected function _newRpc($url, $method, $params, $baseParams):RpcVO | |
{ | |
var rpc:RpcVO = new RpcVO({ | |
client: null, | |
loader: null, | |
request:null, | |
rpc: null, | |
url: null, | |
bytesLoaded: 0, | |
bytesTotal: 0, | |
onLoaderEvent:null, | |
response: { | |
error:null, | |
result: null | |
}, | |
on: { | |
scope: null, | |
error: null, | |
result: null, | |
response: null, | |
progress: null | |
} | |
}); | |
var loader:URLLoader = new URLLoader(); | |
var request:URLRequest = new URLRequest(); | |
rpc.loader = loader; | |
rpc.request = request; | |
var variables:URLVariables = new URLVariables(); | |
if ((rpcMethodPrefix is String) && (rpcMethodPrefix.length > 0)) { | |
$method = rpcMethodPrefix + "" + $method; | |
} | |
var jsonrpc={ | |
method:$method, | |
params:$params | |
} | |
// apply baseParams if there are any | |
if ($baseParams is Object) | |
{ | |
for (var key in $baseParams) | |
{ | |
jsonrpc[key]=$baseParams[key]; | |
} | |
} | |
rpc.rpc = jsonrpc; | |
var jsonrpcstring=JSON.encode(jsonrpc); | |
variables.jsonrpc=jsonrpcstring; | |
request.url = $url; | |
rpc.url = request.url; | |
if ((formFieldName is String) && (formFieldName.length > 0)) { | |
// a form post | |
request.data=variables; | |
} else { | |
// a raw body post | |
request.data = jsonrpcstring; | |
//request.contentType = URLLoaderDataFormat.BINARY; | |
request.contentType = "application/json"; | |
} | |
request.method=URLRequestMethod.POST; | |
// no!: request.contentType=URLLoaderDataFormat.VARIABLES; | |
// loader event handlers | |
rpc.onLoaderEvent = function(event:Event) { | |
switch(event.type) { | |
case Event.OPEN: { | |
// call request.invoke handler | |
_onInvoke(rpc); | |
break; | |
} | |
case ProgressEvent.PROGRESS: { | |
if (rpc) { | |
// actually does not work for some ajax calls | |
var bytesTotal = 0 + (event as ProgressEvent).bytesTotal; | |
var bytesLoaded = 0 + (event as ProgressEvent).bytesLoaded; | |
rpc.bytesLoaded = bytesLoaded; | |
rpc.bytesTotal = bytesTotal; | |
} | |
// call request.progress handler | |
_onProgress(rpc); | |
break; | |
} | |
case HTTPStatusEvent.HTTP_STATUS: { | |
//ignore | |
break; | |
} | |
case Event.COMPLETE: { | |
try { | |
var response = { | |
error:null, | |
result:null | |
} | |
var responseText = event.currentTarget.data; | |
if (!(responseText is String)) { | |
throw new Error("invalid response"); | |
} | |
var responseData = JSON.decode(responseText); | |
if (!(responseData is Object)) { | |
throw new Error("invalid response"); | |
} | |
if (responseData==null) { | |
throw new Error("invalid response"); | |
} | |
if (!(responseData.hasOwnProperty("result"))) { | |
throw new Error("invalid response"); | |
} | |
if (!(responseData.hasOwnProperty("error"))) { | |
throw new Error("invalid response"); | |
} | |
response = { | |
error:responseData.error, | |
result:responseData.result | |
} | |
// you want all keys in your response? | |
for (var key in responseData) { | |
response[key] = responseData[key]; | |
} | |
} catch (error:Error) { | |
response = { | |
result:null, | |
error: { | |
message: error.message | |
} | |
} | |
} | |
if (rpc) { | |
rpc.response = response; | |
} | |
// call response handler | |
_onResponse(rpc); | |
// call response.error OR response.result handler | |
if (response.error) { | |
// call response.error handler | |
_onError(rpc); | |
return; | |
} else { | |
// call response.result handler | |
_onResult(rpc); | |
} | |
break; | |
} | |
case IOErrorEvent.IO_ERROR: | |
case SecurityErrorEvent.SECURITY_ERROR: { | |
if (rpc) { | |
if (!rpc.response) { | |
rpc.response = { | |
result: null | |
} | |
} | |
rpc.response.error = { | |
message: "CLIENT_ERROR" | |
} | |
if (event.type == IOErrorEvent.IO_ERROR) { | |
rpc.response.error.message = "CLIENT_IOERROR"; | |
} | |
if (event.type == SecurityErrorEvent.SECURITY_ERROR) { | |
rpc.response.error.message = "CLIENT_SECURITYERROR"; | |
} | |
} | |
// call response handler | |
_onResponse(rpc); | |
// call response.error handler | |
_onError(rpc); | |
break; | |
} | |
default: { | |
break; | |
} | |
} | |
} | |
// add loader listeners | |
loader.addEventListener(Event.COMPLETE, rpc.onLoaderEvent); | |
loader.addEventListener(Event.OPEN, rpc.onLoaderEvent); | |
loader.addEventListener(ProgressEvent.PROGRESS, rpc.onLoaderEvent); | |
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, rpc.onLoaderEvent); | |
loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, rpc.onLoaderEvent); | |
loader.addEventListener(IOErrorEvent.IO_ERROR, rpc.onLoaderEvent); | |
// return rpc object | |
return rpc; | |
} | |
protected function _onInvoke(rpc:RpcVO) | |
{ | |
//trace(this + "._onInvoke()"); | |
if (!rpc) { | |
return; | |
} | |
// call client callback | |
if ( | |
(rpc) && (getCallback()) | |
&& (getCallback().getOnInvoke() is Function) | |
) { | |
getCallback().getOnInvoke().call( | |
getCallback().getScope(), rpc | |
); | |
} | |
// call request callback | |
if ( | |
(rpc) && (rpc.getCallback()) | |
&& (rpc.getCallback().getOnInvoke() is Function) | |
) { | |
rpc.getCallback().getOnInvoke().call( | |
rpc.getCallback().getScope(), rpc | |
); | |
} | |
} | |
protected function _onProgress(rpc:RpcVO) | |
{ | |
//trace(this + "._onProgress()"); | |
if (!rpc) { | |
return; | |
} | |
// call client callback | |
if ( | |
(rpc) && (getCallback()) | |
&& (getCallback().getOnProgress() is Function) | |
) { | |
getCallback().getOnProgress().call( | |
getCallback().getScope(), rpc | |
); | |
} | |
// call request callback | |
if ( | |
(rpc) && (rpc.getCallback()) | |
&& (rpc.getCallback().getOnProgress() is Function) | |
) { | |
rpc.getCallback().getOnProgress().call( | |
rpc.getCallback().getScope(), rpc | |
); | |
} | |
} | |
protected function _onResponse(rpc:RpcVO) | |
{ | |
//trace(this + "._onResponse()"); | |
if (!rpc) { | |
return; | |
} | |
// call client callback | |
if ( | |
(rpc) && (getCallback()) | |
&& (getCallback().getOnResponse() is Function) | |
) { | |
getCallback().getOnResponse().call( | |
getCallback().getScope(), rpc | |
); | |
} | |
// call request callback | |
if ( | |
(rpc) && (rpc.getCallback()) | |
&& (rpc.getCallback().getOnResponse() is Function) | |
) { | |
rpc.getCallback().getOnResponse().call( | |
rpc.getCallback().getScope(), rpc | |
); | |
} | |
} | |
protected function _onError(rpc:RpcVO) | |
{ | |
//trace(this + "._onError()"); | |
if (!rpc) { | |
return; | |
} | |
// call client callback | |
if ( | |
(rpc) && (getCallback()) | |
&& (getCallback().getOnError() is Function) | |
) { | |
getCallback().getOnError().call( | |
getCallback().getScope(), rpc | |
); | |
} | |
// call request callback | |
if ( | |
(rpc) && (rpc.getCallback()) | |
&& (rpc.getCallback().getOnError() is Function) | |
) { | |
rpc.getCallback().getOnError().call( | |
rpc.getCallback().getScope(), rpc | |
); | |
} | |
} | |
protected function _onResult(rpc:RpcVO) | |
{ | |
//trace(this + "._onResult()"); | |
if (!rpc) { | |
return; | |
} | |
// call client callback | |
if ( | |
(rpc) && (getCallback()) | |
&& (getCallback().getOnResult() is Function) | |
) { | |
getCallback().getOnResult().call( | |
getCallback().getScope(), rpc | |
); | |
} | |
// call request callback | |
if ( | |
(rpc) && (rpc.getCallback()) | |
&& (rpc.getCallback().getOnResult() is Function) | |
) { | |
rpc.getCallback().getOnResult().call( | |
rpc.getCallback().getScope(), rpc | |
); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.application.rpc | |
{ | |
/** | |
* ... | |
* @author seb | |
*/ | |
import com.application.rpc.RpcVO; | |
import com.application.rpc.ResponseVO; | |
public class Example | |
{ | |
protected var _rpcClient:Client; | |
public function getRpcClient():Client | |
{ | |
return _rpcClient; | |
} | |
public function run() | |
{ | |
// rpc | |
_initRpcClient( | |
"http://cms.omg.com.local.basilicom.de/service/rpc", | |
"de.sony.adventskalendar2011." | |
); | |
// do something | |
_doSomething(); | |
} | |
protected function _doSomething() | |
{ | |
getRpcClient().invoke("Test.say", ["hello wörld"], { | |
"scope":this, | |
"response":function(rpc:RpcVO) { | |
trace(this + ".response() ... "); | |
var responseVO:ResponseVO = (rpc as RpcVO).getResponse(); | |
if (responseVO.hasError()) { | |
throw new Error(responseVO.getErrorMessage()); | |
return; | |
} | |
trace(" ... success! result=" + responseVO.getResult()); | |
} | |
}); | |
} | |
protected function _initRpcClient( | |
$url:String, $rpcMethodPrefix:String | |
) | |
{ | |
var rpcClient:Client = Client.getInstance(); | |
_rpcClient = rpcClient; | |
rpcClient.url = $url; | |
rpcClient.rpcMethodPrefix = $rpcMethodPrefix; | |
_initRpcDefaultCallbacks(); | |
} | |
protected function _initRpcDefaultCallbacks() | |
{ | |
var rpcClient = this.getRpcClient(); | |
// global callbacks for the dirty stuff | |
rpcClient.getCallback().setScope(this); | |
// on invoke | |
rpcClient.getCallback().setOnInvoke( | |
function(rpc:RpcVO) { | |
trace(this + " global on invoke ... "); | |
trace("... rpc = " + (rpc as RpcVO).getRpcAsJson()); | |
trace("... rpc url = "+ (rpc as RpcVO).getUrl()); | |
} | |
); | |
// on progress | |
rpcClient.getCallback().setOnProgress( | |
function(rpc:RpcVO) { | |
// makes n sense in most ajax env's | |
trace(this + " global on progress ... "); | |
trace(" ... progress " | |
+ (rpc as RpcVO).getBytesLoaded() | |
+ " / " +(rpc as RpcVO).getBytesTotal()+" bytes" | |
+ " (" +(rpc as RpcVO).getPercentageLoaded() + " %)" | |
); | |
} | |
); | |
// on response | |
rpcClient.getCallback().setOnResponse( | |
function(rpc:RpcVO) { | |
trace(this + " global on response ... "); | |
trace(" ... response (json) = " | |
+ (rpc as RpcVO).getResponse().toJson() | |
); | |
} | |
); | |
// on result: everything is fine. (success!) | |
rpcClient.getCallback().setOnResult( | |
function(rpc:RpcVO) { | |
trace(this + " global on result ... "); | |
trace("... result (json) = " | |
+ (rpc as RpcVO).getResponse() | |
.getResultAsJson() | |
); | |
} | |
); | |
// on error: wtf? server dude. fix your shit! | |
rpcClient.getCallback().setOnError( | |
function(rpc:RpcVO) { | |
trace(this + " global on error ... "); | |
trace(" ... error (json) = " | |
+ (rpc as RpcVO).getResponse() | |
.getErrorAsJson() | |
); | |
} | |
); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.application.rpc | |
{ | |
/** | |
* ... | |
* @author seb | |
*/ | |
import com.adobe.serialization.json.JSON; | |
public dynamic class ResponseVO extends Object | |
{ | |
public function ResponseVO(data:Object = null) | |
{ | |
if (data is Object) { | |
for (var key in data) { | |
this[key] = data[key]; | |
} | |
} | |
} | |
public function getResult():* | |
{ | |
return this["result"]; | |
} | |
public function getError():* | |
{ | |
return this["error"]; | |
} | |
public function hasError():Boolean | |
{ | |
var error:* = this.getError(); | |
if (error == null) { | |
return false; | |
} | |
if (error == undefined) { | |
return false; | |
} | |
return true; | |
} | |
public function toJson():String | |
{ | |
var o:Object = {}; | |
for (var key in this) { | |
o[key] = this[key]; | |
} | |
return JSON.encode(o); | |
} | |
public function getResultAsJson():String | |
{ | |
var value = this["result"]; | |
return JSON.encode(value); | |
} | |
public function getErrorAsJson():String | |
{ | |
var value = this["error"]; | |
return JSON.encode(value); | |
} | |
public function getErrorMessage():String | |
{ | |
var message:String = ""; | |
var error:Object = this.getError(); | |
if ((error == null)) { | |
return message; | |
} | |
if (error.hasOwnProperty("message")) { | |
message = error.message; | |
} | |
return message; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.application.rpc | |
{ | |
/** | |
* ... | |
* @author seb | |
*/ | |
import com.adobe.serialization.json.JSON; | |
public dynamic class RpcVO extends Object | |
{ | |
public function RpcVO(data:Object=null) | |
{ | |
if (data is Object) { | |
for (var key in data) { | |
this[key] = data[key]; | |
} | |
} | |
} | |
public function getCallback():CallbackVO | |
{ | |
return this["on"]; | |
} | |
public function getResponse():ResponseVO { | |
var value:* = this["response"]; | |
if (!(value is ResponseVO)) { | |
value = new ResponseVO(value); | |
} | |
this["response"] = value; | |
return value; | |
} | |
public function getRpc():Object | |
{ | |
return this["rpc"]; | |
} | |
public function getRpcAsJson():String | |
{ | |
var rpc = this["rpc"]; | |
var rpcText = JSON.encode(rpc); | |
return rpcText; | |
} | |
public function getUrl():String | |
{ | |
return this["url"]; | |
} | |
public function getBytesLoaded():Number | |
{ | |
return this["bytesLoaded"]; | |
} | |
public function getBytesTotal():Number | |
{ | |
return this["bytesTotal"]; | |
} | |
public function getPercentageLoaded():Number | |
{ | |
var bytesLoaded:Number = 0 + getBytesLoaded(); | |
var bytesTotal:Number = 0 + getBytesTotal(); | |
var value = 0; | |
if (bytesTotal > 0) { | |
value = (bytesLoaded / bytesTotal); | |
value = value * 100; | |
value = Math.round(value); | |
} | |
return value; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment