4 rpcSessionID
= L
.env
.sessionid
|| '00000000000000000000000000000000',
5 rpcBaseURL
= L
.url('admin/ubus'),
6 rpcInterceptorFns
= [];
8 return L
.Class
.extend({
9 call: function(req
, cb
, nobatch
) {
12 if (Array
.isArray(req
)) {
14 return Promise
.resolve([]);
16 for (var i
= 0; i
< req
.length
; i
++)
18 q
+= '%s%s.%s'.format(
24 else if (req
.params
) {
25 q
+= '/%s.%s'.format(req
.params
[1], req
.params
[2]);
28 return L
.Request
.post(rpcBaseURL
+ q
, req
, {
29 timeout
: (L
.env
.rpctimeout
|| 20) * 1000,
35 parseCallReply: function(req
, res
) {
38 if (res
instanceof Error
)
39 return req
.reject(res
);
43 L
.raise('RPCError', 'RPC call to %s/%s failed with HTTP error %d: %s',
44 req
.object
, req
.method
, res
.status
, res
.statusText
|| '?');
53 * The interceptor args are intentionally swapped.
54 * Response is passed as first arg to align with Request class interceptors
56 Promise
.all(rpcInterceptorFns
.map(function(fn
) { return fn(msg
, req
) }))
57 .then(this.handleCallReply
.bind(this, req
, msg
))
61 handleCallReply: function(req
, msg
) {
62 var type
= Object
.prototype.toString
,
66 /* verify message frame */
67 if (!L
.isObject(msg
) || msg
.jsonrpc
!= '2.0')
68 L
.raise('RPCError', 'RPC call to %s/%s returned invalid message frame',
69 req
.object
, req
.method
);
71 /* check error condition */
72 if (L
.isObject(msg
.error
) && msg
.error
.code
&& msg
.error
.message
)
73 L
.raise('RPCError', 'RPC call to %s/%s failed with error %d: %s',
74 req
.object
, req
.method
, msg
.error
.code
, msg
.error
.message
|| '?');
80 if (!req
.object
&& !req
.method
) {
83 else if (Array
.isArray(msg
.result
)) {
84 ret
= (msg
.result
.length
> 1) ? msg
.result
[1] : msg
.result
[0];
88 for (var key
in req
.expect
) {
89 if (ret
!= null && key
!= '')
92 if (ret
== null || type
.call(ret
) != type
.call(req
.expect
[key
]))
93 ret
= req
.expect
[key
];
100 if (typeof(req
.filter
) == 'function') {
102 req
.priv
[1] = req
.params
;
103 ret
= req
.filter
.apply(this, req
.priv
);
114 params
: arguments
.length
? this.varargs(arguments
) : undefined
117 return new Promise(L
.bind(function(resolveFn
, rejectFn
) {
118 /* store request info */
125 this.call(msg
, this.parseCallReply
.bind(this, req
));
129 declare: function(options
) {
130 return Function
.prototype.bind
.call(function(rpc
, options
) {
131 var args
= this.varargs(arguments
, 2);
132 return new Promise(function(resolveFn
, rejectFn
) {
133 /* build parameter object */
136 if (Array
.isArray(options
.params
))
137 for (p_off
= 0; p_off
< options
.params
.length
; p_off
++)
138 params
[options
.params
[p_off
]] = args
[p_off
];
140 /* all remaining arguments are private args */
141 var priv
= [ undefined, undefined ];
142 for (; p_off
< args
.length
; p_off
++)
143 priv
.push(args
[p_off
]);
145 /* store request info */
147 expect
: options
.expect
,
148 filter
: options
.filter
,
153 object
: options
.object
,
154 method
: options
.method
157 /* build message object */
171 rpc
.call(msg
, rpc
.parseCallReply
.bind(rpc
, req
), options
.nobatch
);
173 }, this, this, options
);
176 getSessionID: function() {
180 setSessionID: function(sid
) {
184 getBaseURL: function() {
188 setBaseURL: function(url
) {
192 getStatusText: function(statusCode
) {
193 switch (statusCode
) {
194 case 0: return _('Command OK');
195 case 1: return _('Invalid command');
196 case 2: return _('Invalid argument');
197 case 3: return _('Method not found');
198 case 4: return _('Resource not found');
199 case 5: return _('No data received');
200 case 6: return _('Permission denied');
201 case 7: return _('Request timeout');
202 case 8: return _('Not supported');
203 case 9: return _('Unspecified error');
204 case 10: return _('Connection lost');
205 default: return _('Unknown error code');
209 addInterceptor: function(interceptorFn
) {
210 if (typeof(interceptorFn
) == 'function')
211 rpcInterceptorFns
.push(interceptorFn
);
212 return interceptorFn
;
215 removeInterceptor: function(interceptorFn
) {
216 var oldlen
= rpcInterceptorFns
.length
, i
= oldlen
;
218 if (rpcInterceptorFns
[i
] === interceptorFn
)
219 rpcInterceptorFns
.splice(i
, 1);
220 return (rpcInterceptorFns
.length
< oldlen
);