summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/rpc.js76
1 files changed, 56 insertions, 20 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/rpc.js b/modules/luci-base/htdocs/luci-static/resources/rpc.js
index e6a1bb24dc..9a0f0164ae 100644
--- a/modules/luci-base/htdocs/luci-static/resources/rpc.js
+++ b/modules/luci-base/htdocs/luci-static/resources/rpc.js
@@ -2,7 +2,8 @@
var rpcRequestID = 1,
rpcSessionID = L.env.sessionid || '00000000000000000000000000000000',
- rpcBaseURL = L.url('admin/ubus');
+ rpcBaseURL = L.url('admin/ubus'),
+ rpcInterceptorFns = [];
return L.Class.extend({
call: function(req, cb) {
@@ -39,29 +40,50 @@ return L.Class.extend({
req.resolve(list);
},
- handleCallReply: function(req, res) {
- var type = Object.prototype.toString,
- msg = null;
+ parseCallReply: function(req, res) {
+ var msg = null;
- if (!res.ok)
- L.error('RPCError', 'RPC call to %s/%s failed with HTTP error %d: %s',
- req.object, req.method, res.status, res.statusText || '?');
+ try {
+ if (!res.ok)
+ L.raise('RPCError', 'RPC call to %s/%s failed with HTTP error %d: %s',
+ req.object, req.method, res.status, res.statusText || '?');
- msg = res.json();
+ msg = res.json();
+ }
+ catch (e) {
+ return req.reject(e);
+ }
- /* fetch response attribute and verify returned type */
- var ret = undefined;
+ /*
+ * The interceptor args are intentionally swapped.
+ * Response is passed as first arg to align with Request class interceptors
+ */
+ Promise.all(rpcInterceptorFns.map(function(fn) { return fn(msg, req) }))
+ .then(this.handleCallReply.bind(this, req, msg))
+ .catch(req.reject);
+ },
- /* verify message frame */
- if (typeof(msg) == 'object' && msg.jsonrpc == '2.0') {
- if (typeof(msg.error) == 'object' && msg.error.code && msg.error.message)
- req.reject(new Error('RPC call to %s/%s failed with error %d: %s'
- .format(req.object, req.method, msg.error.code, msg.error.message || '?')));
- else if (Array.isArray(msg.result))
- ret = (msg.result.length > 1) ? msg.result[1] : msg.result[0];
+ handleCallReply: function(req, msg) {
+ var type = Object.prototype.toString,
+ ret = null;
+
+ try {
+ /* verify message frame */
+ if (!L.isObject(msg) || msg.jsonrpc != '2.0')
+ L.raise('RPCError', 'RPC call to %s/%s returned invalid message frame',
+ req.object, req.method);
+
+ /* check error condition */
+ if (L.isObject(msg.error) && msg.error.code && msg.error.message)
+ L.raise('RPCError', 'RPC call to %s/%s failed with error %d: %s',
+ req.object, req.method, msg.error.code, msg.error.message || '?');
}
- else {
- req.reject(new Error('Invalid message frame received'));
+ catch (e) {
+ return req.reject(e);
+ }
+
+ if (Array.isArray(msg.result)) {
+ ret = (msg.result.length > 1) ? msg.result[1] : msg.result[0];
}
if (req.expect) {
@@ -139,7 +161,7 @@ return L.Class.extend({
};
/* call rpc */
- rpc.call(msg, rpc.handleCallReply.bind(rpc, req));
+ rpc.call(msg, rpc.parseCallReply.bind(rpc, req));
});
}, this, this, options);
},
@@ -175,5 +197,19 @@ return L.Class.extend({
case 10: return _('Connection lost');
default: return _('Unknown error code');
}
+ },
+
+ addInterceptor: function(interceptorFn) {
+ if (typeof(interceptorFn) == 'function')
+ rpcInterceptorFns.push(interceptorFn);
+ return interceptorFn;
+ },
+
+ removeInterceptor: function(interceptorFn) {
+ var oldlen = rpcInterceptorFns.length, i = oldlen;
+ while (i--)
+ if (rpcInterceptorFns[i] === interceptorFn)
+ rpcInterceptorFns.splice(i, 1);
+ return (rpcInterceptorFns.length < oldlen);
}
});