summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/htdocs/luci-static/resources/rpc.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-base/htdocs/luci-static/resources/rpc.js')
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/rpc.js257
1 files changed, 256 insertions, 1 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/rpc.js b/modules/luci-base/htdocs/luci-static/resources/rpc.js
index 9c74bfdaf0..9b642444fa 100644
--- a/modules/luci-base/htdocs/luci-static/resources/rpc.js
+++ b/modules/luci-base/htdocs/luci-static/resources/rpc.js
@@ -5,7 +5,17 @@ var rpcRequestID = 1,
rpcBaseURL = L.url('admin/ubus'),
rpcInterceptorFns = [];
-return L.Class.extend({
+/**
+ * @class rpc
+ * @memberof LuCI
+ * @hideconstructor
+ * @classdesc
+ *
+ * The `LuCI.rpc` class provides high level ubus JSON-RPC abstractions
+ * and means for listing and invoking remove RPC methods.
+ */
+return L.Class.extend(/** @lends LuCI.rpc.prototype */ {
+ /* privates */
call: function(req, cb, nobatch) {
var q = '';
@@ -106,6 +116,27 @@ return L.Class.extend({
req.resolve(ret);
},
+ /**
+ * Lists available remote ubus objects or the method signatures of
+ * specific objects.
+ *
+ * This function has two signatures and is sensitive to the number of
+ * arguments passed to it:
+ * - `list()` -
+ * Returns an array containing the names of all remote `ubus` objects
+ * - `list("objname", ...)`
+ * Returns method signatures for each given `ubus` object name.
+ *
+ * @param {...string} [objectNames]
+ * If any object names are given, this function will return the method
+ * signatures of each given object.
+ *
+ * @returns {Promise<Array<string>|Object<string, Object<string, Object<string, string>>>>}
+ * When invoked without arguments, this function will return a promise
+ * resolving to an array of `ubus` object names. When invoked with one or
+ * more arguments, a promise resolving to an object describing the method
+ * signatures of each requested `ubus` object name will be returned.
+ */
list: function() {
var msg = {
jsonrpc: '2.0',
@@ -126,6 +157,138 @@ return L.Class.extend({
}, this));
},
+ /**
+ * @typedef {Object} DeclareOptions
+ * @memberof LuCI.rpc
+ *
+ * @property {string} object
+ * The name of the remote `ubus` object to invoke.
+ *
+ * @property {string} method
+ * The name of the remote `ubus` method to invoke.
+ *
+ * @property {string[]} [params]
+ * Lists the named parameters expected by the remote `ubus` RPC method.
+ * The arguments passed to the resulting generated method call function
+ * will be mapped to named parameters in the order they appear in this
+ * array.
+ *
+ * Extraneous parameters passed to the generated function will not be
+ * sent to the remote procedure but are passed to the
+ * {@link LuCI.rpc~filterFn filter function} if one is specified.
+ *
+ * Examples:
+ * - `params: [ "foo", "bar" ]` -
+ * When the resulting call function is invoked with `fn(true, false)`,
+ * the corresponding args object sent to the remote procedure will be
+ * `{ foo: true, bar: false }`.
+ * - `params: [ "test" ], filter: function(reply, args, extra) { ... }` -
+ * When the resultung generated function is invoked with
+ * `fn("foo", "bar", "baz")` then `{ "test": "foo" }` will be sent as
+ * argument to the remote procedure and the filter function will be
+ * invoked with `filterFn(reply, [ "foo" ], "bar", "baz")`
+ *
+ * @property {Object<string,*>} [expect]
+ * Describes the expected return data structure. The given object is
+ * supposed to contain a single key selecting the value to use from
+ * the returned `ubus` reply object. The value of the sole key within
+ * the `expect` object is used to infer the expected type of the received
+ * `ubus` reply data.
+ *
+ * If the received data does not contain `expect`'s key, or if the
+ * type of the data differs from the type of the value in the expect
+ * object, the expect object's value is returned as default instead.
+ *
+ * The key in the `expect` object may be an empty string (`''`) in which
+ * case the entire reply object is selected instead of one of its subkeys.
+ *
+ * If the `expect` option is omitted, the received reply will be returned
+ * as-is, regardless of its format or type.
+ *
+ * Examples:
+ * - `expect: { '': { error: 'Invalid response' } }` -
+ * This requires the entire `ubus` reply to be a plain JavaScript
+ * object. If the reply isn't an object but e.g. an array or a numeric
+ * error code instead, it will get replaced with
+ * `{ error: 'Invalid response' }` instead.
+ * - `expect: { results: [] }` -
+ * This requires the received `ubus` reply to be an object containing
+ * a key `results` with an array as value. If the received reply does
+ * not contain such a key, or if `reply.results` points to a non-array
+ * value, the empty array (`[]`) will be used instead.
+ * - `expect: { success: false }` -
+ * This requires the received `ubus` reply to be an object containing
+ * a key `success` with a boolean value. If the reply does not contain
+ * `success` or if `reply.success` is not a boolean value, `false` will
+ * be returned as default instead.
+ *
+ * @property {LuCI.rpc~filterFn} [filter]
+ * Specfies an optional filter function which is invoked to transform the
+ * received reply data before it is returned to the caller.
+ *
+ */
+
+ /**
+ * The filter function is invoked to transform a received `ubus` RPC call
+ * reply before returning it to the caller.
+ *
+ * @callback LuCI.rpc~filterFn
+ *
+ * @param {*} data
+ * The received `ubus` reply data or a subset of it as described in the
+ * `expect` option of the RPC call declaration. In case of remote call
+ * errors, `data` is numeric `ubus` error code instead.
+ *
+ * @param {Array<*>} args
+ * The arguments the RPC method has been invoked with.
+ *
+ * @param {...*} extraArgs
+ * All extraneous arguments passed to the RPC method exceeding the number
+ * of arguments describes in the RPC call declaration.
+ *
+ * @return {*}
+ * The return value of the filter function will be returned to the caller
+ * of the RPC method as-is.
+ */
+
+ /**
+ * The generated invocation function is returned by
+ * {@link LuCI.rpc#declare rpc.declare()} and encapsulates a single
+ * RPC method call.
+ *
+ * Calling this function will execute a remote `ubus` HTTP call request
+ * using the arguments passed to it as arguments and return a promise
+ * resolving to the received reply values.
+ *
+ * @callback LuCI.rpc~invokeFn
+ *
+ * @param {...*} params
+ * The parameters to pass to the remote procedure call. The given
+ * positional arguments will be named to named RPC parameters according
+ * to the names specified in the `params` array of the method declaration.
+ *
+ * Any additional parameters exceeding the amount of arguments in the
+ * `params` declaration are passed as private extra arguments to the
+ * declared filter function.
+ *
+ * @return {Promise<*>}
+ * Returns a promise resolving to the result data of the remote `ubus`
+ * RPC method invocation, optionally substituted and filtered according
+ * to the `expect` and `filter` declarations.
+ */
+
+ /**
+ * Describes a remote RPC call procedure and returns a function
+ * implementing it.
+ *
+ * @param {LuCI.rpc.DeclareOptions} options
+ * If any object names are given, this function will return the method
+ * signatures of each given object.
+ *
+ * @returns {LuCI.rpc~invokeFn}
+ * Returns a new function implementing the method call described in
+ * `options`.
+ */
declare: function(options) {
return Function.prototype.bind.call(function(rpc, options) {
var args = this.varargs(arguments, 2);
@@ -173,22 +336,58 @@ return L.Class.extend({
}, this, this, options);
},
+ /**
+ * Returns the current RPC session id.
+ *
+ * @returns {string}
+ * Returns the 32 byte session ID string used for authenticating remote
+ * requests.
+ */
getSessionID: function() {
return rpcSessionID;
},
+ /**
+ * Set the RPC session id to use.
+ *
+ * @param {string} sid
+ * Sets the 32 byte session ID string used for authenticating remote
+ * requests.
+ */
setSessionID: function(sid) {
rpcSessionID = sid;
},
+ /**
+ * Returns the current RPC base URL.
+ *
+ * @returns {string}
+ * Returns the RPC URL endpoint to issue requests against.
+ */
getBaseURL: function() {
return rpcBaseURL;
},
+ /**
+ * Set the RPC base URL to use.
+ *
+ * @param {string} sid
+ * Sets the RPC URL endpoint to issue requests against.
+ */
setBaseURL: function(url) {
rpcBaseURL = url;
},
+ /**
+ * Translates a numeric `ubus` error code into a human readable
+ * description.
+ *
+ * @param {number} statusCode
+ * The numeric status code.
+ *
+ * @returns {string}
+ * Returns the textual description of the code.
+ */
getStatusText: function(statusCode) {
switch (statusCode) {
case 0: return _('Command OK');
@@ -206,12 +405,68 @@ return L.Class.extend({
}
},
+ /**
+ * Registered interceptor functions are invoked before the standard reply
+ * parsing and handling logic.
+ *
+ * By returning rejected promises, interceptor functions can cause the
+ * invocation function to fail, regardless of the received reply.
+ *
+ * Interceptors may also modify their message argument in-place to
+ * rewrite received replies before they're processed by the standard
+ * response handling code.
+ *
+ * A common use case for such functions is to detect failing RPC replies
+ * due to expired authentication in order to trigger a new login.
+ *
+ * @callback LuCI.rpc~interceptorFn
+ *
+ * @param {*} msg
+ * The unprocessed, JSON decoded remote RPC method call reply.
+ *
+ * Since interceptors run before the standard parsing logic, the reply
+ * data is not verified for correctness or filtered according to
+ * `expect` and `filter` specifications in the declarations.
+ *
+ * @param {Object} req
+ * The related request object which is an extended variant of the
+ * declaration object, allowing access to internals of the invocation
+ * function such as `filter`, `expect` or `params` values.
+ *
+ * @return {Promise<*>|*}
+ * Interceptor functions may return a promise to defer response
+ * processing until some delayed work completed. Any values the returned
+ * promise resolves to are ignored.
+ *
+ * When the returned promise rejects with an error, the invocation
+ * function will fail too, forwarding the error to the caller.
+ */
+
+ /**
+ * Registers a new interceptor function.
+ *
+ * @param {LuCI.rpc~interceptorFn} interceptorFn
+ * The inteceptor function to register.
+ *
+ * @returns {LuCI.rpc~interceptorFn}
+ * Returns the given function value.
+ */
addInterceptor: function(interceptorFn) {
if (typeof(interceptorFn) == 'function')
rpcInterceptorFns.push(interceptorFn);
return interceptorFn;
},
+ /**
+ * Removes a registered interceptor function.
+ *
+ * @param {LuCI.rpc~interceptorFn} interceptorFn
+ * The inteceptor function to remove.
+ *
+ * @returns {boolean}
+ * Returns `true` if the given function has been removed or `false`
+ * if it has not been found.
+ */
removeInterceptor: function(interceptorFn) {
var oldlen = rpcInterceptorFns.length, i = oldlen;
while (i--)