linkpi_firmware_history/rootfs/link/web/js/jquery.jsonrpc.js

295 lines
10 KiB
JavaScript

(function($, undefined) {
$.extend({
jsonRPC: {
// RPC Version Number
version: '2.0',
// End point URL, sets default in requests if not
// specified with the request call
endPoint: null,
// Default namespace for methods
namespace: null,
/*
* Provides the RPC client with an optional default endpoint and namespace
*
* @param {object} The params object which can contain
* endPoint {string} The default endpoint for RPC requests
* namespace {string} The default namespace for RPC requests
* cache {boolean} If set to false, it will force requested
* pages not to be cached by the browser. Setting cache
* to false also appends a query string parameter,
* "_=[TIMESTAMP]", to the URL. (Default: true)
*/
setup: function(params) {
this._validateConfigParams(params);
this.endPoint = params.endPoint;
this.namespace = params.namespace;
this.cache = params.cache !== undefined ? params.cache : true;
return this;
},
/*
* Convenience wrapper method to allow you to temporarily set a config parameter
* (endPoint or namespace) and ensure it gets set back to what it was before
*
* @param {object} The params object which can contains
* endPoint {string} The default endpoint for RPC requests
* namespace {string} The default namespace for RPC requests
* @param {function} callback The function to call with the new params in place
*/
withOptions: function(params, callback) {
this._validateConfigParams(params);
// No point in running if there isn't a callback received to run
if(callback === undefined) throw("No callback specified");
origParams = {endPoint: this.endPoint, namespace: this.namespace};
this.setup(params);
callback.call(this);
this.setup(origParams);
},
/*
* Performas a single RPC request
*
* @param {string} method The name of the rpc method to be called
* @param {object} options A collection of object which can contains
* params {array} the params array to send along with the request
* success {function} a function that will be executed if the request succeeds
* error {function} a function that will be executed if the request fails
* url {string} the url to send the request to
* id {string} the provenance id for this request (defaults to 1)
* cache {boolean} If set to false, it will force requested
* pages not to be cached by the browser. Setting cache
* to false also appends a query string parameter,
* "_=[TIMESTAMP]", to the URL. (Default: cache value
* set with the setup method)
* @return {undefined}
*/
request: function(method, options) {
if(options === undefined) {
options = { id: 1 };
}
if (options.id === undefined) {
options.id = 1;
}
if (options.cache === undefined) {
options.cache = this.cache;
}
// Validate method arguments
this._validateRequestMethod(method);
this._validateRequestParams(options.params);
this._validateRequestCallbacks(options.success, options.error);
// Perform the actual request
this._doRequest(JSON.stringify(this._requestDataObj(method, options.params, options.id)), options);
return true;
},
/*
* Submits multiple requests
* Takes an array of objects that contain a method and params
*
* @params {array} requests an array of request object which can contain
* method {string} the name of the method
* param {object} the params object to be sent with the request
* id {string} the provenance id for the request (defaults to an incrementer starting at 1)
* @param {object} options A collection of object which can contains
* success {function} a function that will be executed if the request succeeds
* error {function} a function that will be executed if the request fails
* url {string} the url to send the request to
* @return {undefined}
*/
batchRequest: function(requests, options) {
if(options === undefined) {
options = {};
}
// Ensure our requests come in as an array
if(!$.isArray(requests) || requests.length === 0) throw("Invalid requests supplied for jsonRPC batchRequest. Must be an array object that contain at least a method attribute");
// Make sure each of our request objects are valid
var _that = this;
$.each(requests, function(i, req) {
_that._validateRequestMethod(req.method);
_that._validateRequestParams(req.params);
if (req.id === undefined) {
req.id = i + 1;
}
});
this._validateRequestCallbacks(options.success, options.error);
var data = [],
request;
// Prepare our request object
for(var i = 0; i<requests.length; i++) {
request = requests[i];
data.push(this._requestDataObj(request.method, request.params, request.id));
}
this._doRequest(JSON.stringify(data), options);
},
// Validate a params hash
_validateConfigParams: function(params) {
if(params === undefined) {
throw("No params specified");
}
else {
if(params.endPoint && typeof(params.endPoint) !== 'string'){
throw("endPoint must be a string");
}
if(params.namespace && typeof(params.namespace) !== 'string'){
throw("namespace must be a string");
}
}
},
// Request method must be a string
_validateRequestMethod: function(method) {
if(typeof(method) !== 'string') throw("Invalid method supplied for jsonRPC request")
return true;
},
// Validate request params. Must be a) empty, b) an object (e.g. {}), or c) an array
_validateRequestParams: function(params) {
if(!(params === null ||
params === undefined ||
typeof(params) === 'object' ||
$.isArray(params))) {
throw("Invalid params supplied for jsonRPC request. It must be empty, an object or an array.");
}
return true;
},
_validateRequestCallbacks: function(success, error) {
// Make sure callbacks are either empty or a function
if(success !== undefined &&
typeof(success) !== 'function') throw("Invalid success callback supplied for jsonRPC request");
if(error !== undefined &&
typeof(error) !== 'function') throw("Invalid error callback supplied for jsonRPC request");
return true;
},
// Internal method used for generic ajax requests
_doRequest: function(data, options) {
var _that = this;
$.ajax({
type: 'POST',
async: false !== options.async,
dataType: 'json',
contentType: 'application/json',
url: this._requestUrl((options.endPoint || options.url), options.cache),
data: data,
cache: options.cache,
headers: options.headers,
processData: false,
error: function(json) {
_that._requestError.call(_that, json, options.error);
},
success: function(json) {
_that._requestSuccess.call(_that, json, options.success, options.error);
}
})
},
// Determines the appropriate request URL to call for a request
_requestUrl: function(url, cache) {
url = url || this.endPoint;
if (!cache) {
if (url.indexOf("?") < 0) {
url += '?tm=' + new Date().getTime();
}
else {
url += "&tm=" + new Date().getTime();
}
}
return url;
},
// Creates an RPC suitable request object
_requestDataObj: function(method, params, id) {
var dataObj = {
jsonrpc: this.version,
method: this.namespace ? this.namespace +'.'+ method : method,
id: id
}
if(params !== undefined) {
dataObj.params = params;
}
return dataObj;
},
// Handles calling of error callback function
_requestError: function(json, error) {
if (error !== undefined && typeof(error) === 'function') {
if(typeof(json.responseText) === 'string') {
try {
error(JSON.parse(json.responseText));
}
catch(e) {
error(this._response());
}
}
else {
error(this._response());
}
}
},
// Handles calling of RPC success, calls error callback
// if the response contains an error
// TODO: Handle error checking for batch requests
_requestSuccess: function(json, success, error) {
var response = this._response(json);
// If we've encountered an error in the response, trigger the error callback if it exists
if(response.error && typeof(error) === 'function') {
error(response);
return;
}
// Otherwise, successful request, run the success request if it exists
if(typeof(success) === 'function') {
success(response);
}
},
// Returns a generic RPC 2.0 compatible response object
_response: function(json) {
if (json === undefined) {
return {
error: 'Internal server error',
version: '2.0'
};
}
else {
try {
if(typeof(json) === 'string') {
json = JSON.parse(json);
}
if (($.isArray(json) && json.length > 0 && json[0].jsonrpc !== '2.0') ||
(!$.isArray(json) && json.jsonrpc !== '2.0')) {
throw 'Version error';
}
return json;
}
catch (e) {
return {
error: 'Internal server error: ' + e,
version: '2.0'
}
}
}
}
}
});
})(jQuery);