luci-base: rpc.js: add getStatusText() call
[oweals/luci.git] / modules / luci-base / htdocs / luci-static / resources / rpc.js
1 'use strict';
2
3 var rpcRequestID = 1,
4     rpcSessionID = L.env.sessionid || '00000000000000000000000000000000',
5     rpcBaseURL = L.url('admin/ubus');
6
7 return L.Class.extend({
8         call: function(req, cb) {
9                 var q = '';
10
11                 if (Array.isArray(req)) {
12                         if (req.length == 0)
13                                 return Promise.resolve([]);
14
15                         for (var i = 0; i < req.length; i++)
16                                 q += '%s%s.%s'.format(
17                                         q ? ';' : '/',
18                                         req[i].params[1],
19                                         req[i].params[2]
20                                 );
21                 }
22                 else {
23                         q += '/%s.%s'.format(req.params[1], req.params[2]);
24                 }
25
26                 return L.Request.post(rpcBaseURL + q, req, {
27                         timeout: (L.env.rpctimeout || 5) * 1000,
28                         credentials: true
29                 }).then(cb);
30         },
31
32         handleListReply: function(req, msg) {
33                 var list = msg.result;
34
35                 /* verify message frame */
36                 if (typeof(msg) != 'object' || msg.jsonrpc != '2.0' || !msg.id || !Array.isArray(list))
37                         list = [ ];
38
39                 req.resolve(list);
40         },
41
42         handleCallReply: function(req, res) {
43                 var type = Object.prototype.toString,
44                     msg = null;
45
46                 if (!res.ok)
47                         L.error('RPCError', 'RPC call to %s/%s failed with HTTP error %d: %s',
48                                 req.object, req.method, res.status, res.statusText || '?');
49
50                 msg = res.json();
51
52                 /* fetch response attribute and verify returned type */
53                 var ret = undefined;
54
55                 /* verify message frame */
56                 if (typeof(msg) == 'object' && msg.jsonrpc == '2.0') {
57                         if (typeof(msg.error) == 'object' && msg.error.code && msg.error.message)
58                                 req.reject(new Error('RPC call to %s/%s failed with error %d: %s'
59                                         .format(req.object, req.method, msg.error.code, msg.error.message || '?')));
60                         else if (Array.isArray(msg.result))
61                                 ret = (msg.result.length > 1) ? msg.result[1] : msg.result[0];
62                 }
63                 else {
64                         req.reject(new Error('Invalid message frame received'));
65                 }
66
67                 if (req.expect) {
68                         for (var key in req.expect) {
69                                 if (ret != null && key != '')
70                                         ret = ret[key];
71
72                                 if (ret == null || type.call(ret) != type.call(req.expect[key]))
73                                         ret = req.expect[key];
74
75                                 break;
76                         }
77                 }
78
79                 /* apply filter */
80                 if (typeof(req.filter) == 'function') {
81                         req.priv[0] = ret;
82                         req.priv[1] = req.params;
83                         ret = req.filter.apply(this, req.priv);
84                 }
85
86                 req.resolve(ret);
87         },
88
89         list: function() {
90                 var msg = {
91                         jsonrpc: '2.0',
92                         id:      rpcRequestID++,
93                         method:  'list',
94                         params:  arguments.length ? this.varargs(arguments) : undefined
95                 };
96
97                 return this.call(msg, this.handleListReply);
98         },
99
100         declare: function(options) {
101                 return Function.prototype.bind.call(function(rpc, options) {
102                         var args = this.varargs(arguments, 2);
103                         return new Promise(function(resolveFn, rejectFn) {
104                                 /* build parameter object */
105                                 var p_off = 0;
106                                 var params = { };
107                                 if (Array.isArray(options.params))
108                                         for (p_off = 0; p_off < options.params.length; p_off++)
109                                                 params[options.params[p_off]] = args[p_off];
110
111                                 /* all remaining arguments are private args */
112                                 var priv = [ undefined, undefined ];
113                                 for (; p_off < args.length; p_off++)
114                                         priv.push(args[p_off]);
115
116                                 /* store request info */
117                                 var req = {
118                                         expect:  options.expect,
119                                         filter:  options.filter,
120                                         resolve: resolveFn,
121                                         reject:  rejectFn,
122                                         params:  params,
123                                         priv:    priv,
124                                         object:  options.object,
125                                         method:  options.method
126                                 };
127
128                                 /* build message object */
129                                 var msg = {
130                                         jsonrpc: '2.0',
131                                         id:      rpcRequestID++,
132                                         method:  'call',
133                                         params:  [
134                                                 rpcSessionID,
135                                                 options.object,
136                                                 options.method,
137                                                 params
138                                         ]
139                                 };
140
141                                 /* call rpc */
142                                 rpc.call(msg, rpc.handleCallReply.bind(rpc, req));
143                         });
144                 }, this, this, options);
145         },
146
147         getSessionID: function() {
148                 return rpcSessionID;
149         },
150
151         setSessionID: function(sid) {
152                 rpcSessionID = sid;
153         },
154
155         getBaseURL: function() {
156                 return rpcBaseURL;
157         },
158
159         setBaseURL: function(url) {
160                 rpcBaseURL = url;
161         },
162
163         getStatusText: function(statusCode) {
164                 switch (statusCode) {
165                 case 0: return _('Command OK');
166                 case 1: return _('Invalid command');
167                 case 2: return _('Invalid argument');
168                 case 3: return _('Method not found');
169                 case 4: return _('Resource not found');
170                 case 5: return _('No data received');
171                 case 6: return _('Permission denied');
172                 case 7: return _('Request timeout');
173                 case 8: return _('Not supported');
174                 case 9: return _('Unspecified error');
175                 case 10: return _('Connection lost');
176                 default: return _('Unknown error code');
177                 }
178         }
179 });