CallBackery
view release on metacpan or search on metacpan
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/Server.js view on Meta::CPAN
/* ************************************************************************
Copyright: 2009 OETIKER+PARTNER AG
License: GPLv3 or later
Authors: Tobi Oetiker <tobi@oetiker.ch>
Utf8Check: äöü
************************************************************************ */
/**
* JSON-RPC 2.0 client for the CallBackery backend. Wraps
* {@link qx.io.jsonrpc.Client} while preserving the historic callback-style
* API (callAsync/callAsyncSmart/callAsyncSmartBusy with a (ret, exc, id)
* handler) so existing call sites keep working unchanged.
*
* @use(qx.io.transport.Xhr)
*/
qx.Class.define("callbackery.data.Server", {
extend: qx.core.Object,
type: "singleton",
properties: {
sessionCookie: {
init: null,
nullable: true
},
url: {
init: 'QX-JSON-RPC/',
check: 'String'
},
timeout: {
init: 180000,
check: 'Integer'
}
},
members: {
__client: null,
/**
* Lazily create the JSON-RPC client and wire the session-cookie header.
* @return {qx.io.jsonrpc.Client}
*/
_getClient: function() {
if (!this.__client) {
var self = this;
var transport = new qx.io.transport.Xhr(this.getUrl());
var client = new qx.io.jsonrpc.Client(transport);
client.addListener('outgoingRequest', function() {
// getTransportImpl() creates a fresh impl that the
// immediately-following Xhr.send() will pick up and reuse.
var impl = transport.getTransportImpl();
impl.setTimeout(self.getTimeout());
var cookie = self.getSessionCookie();
if (cookie) {
impl.setRequestHeader('X-Session-Cookie', cookie);
}
});
this.__client = client;
}
return this.__client;
},
/**
* Recursively replace non-finite numbers (NaN, Infinity) with null in
* plain data so the outgoing JSON is valid. qx.io.jsonrpc serialises
* via qx.util.Serializer.toJson, which emits a literal "NaN"/"Infinity"
* (invalid JSON the server rejects), whereas the legacy transport used
* JSON.stringify, which already mapped these to null. An empty numeric
* form field is the common source of NaN. Dates and qooxdoo objects are
* passed through untouched so the serialiser can handle them.
*
* @param v {var} value to sanitise
* @return {var} json-safe value
*/
_jsonSafe: function(v) {
if (typeof v === 'number') {
return isFinite(v) ? v : null;
}
if (v === null || typeof v !== 'object' || v instanceof Date) {
return v;
}
if (qx.lang.Type.isArray(v)) {
var arr = [];
for (var i = 0; i < v.length; i++) {
arr[i] = this._jsonSafe(v[i]);
}
return arr;
}
// only descend into plain data objects; leave qooxdoo objects intact
if (v.constructor === Object) {
var out = {};
for (var k in v) {
if (Object.prototype.hasOwnProperty.call(v, k)) {
out[k] = this._jsonSafe(v[k]);
}
}
return out;
}
return v;
},
/**
* Perform the actual JSON-RPC call and adapt the promise to the
* historic (ret, exc, id) callback contract.
*
* @param handler {Function} callback(ret, exc, id)
* @param methodName {String} remote method
* @param params {Array} positional parameters
*/
_send: function(handler, methodName, params) {
params = this._jsonSafe(params);
var invoke = function(ret, exc, id) {
( run in 1.221 second using v1.01-cache-2.11-cpan-9581c071862 )