4 rpcSessionID
= L
.env
.sessionid
|| '00000000000000000000000000000000',
5 rpcBaseURL
= L
.url('admin/ubus'),
6 rpcInterceptorFns
= [];
8 return L
.Class
.extend({
9 call: function(req
, cb
) {
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
|| 5) * 1000,
34 parseCallReply: function(req
, res
) {
37 if (res
instanceof Error
)
38 return req
.reject(res
);
42 L
.raise('RPCError', 'RPC call to %s/%s failed with HTTP error %d: %s',
43 req
.object
, req
.method
, res
.status
, res
.statusText
|| '?');
52 * The interceptor args are intentionally swapped.
53 * Response is passed as first arg to align with Request class interceptors
55 Promise
.all(rpcInterceptorFns
.map(function(fn
) { return fn(msg
, req
) }))
56 .then(this.handleCallReply
.bind(this, req
, msg
))
60 handleCallReply: function(req
, msg
) {
61 var type
= Object
.prototype.toString
,
65 /* verify message frame */
66 if (!L
.isObject(msg
) || msg
.jsonrpc
!= '2.0')
67 L
.raise('RPCError', 'RPC call to %s/%s returned invalid message frame',
68 req
.object
, req
.method
);
70 /* check error condition */
71 if (L
.isObject(msg
.error
) && msg
.error
.code
&& msg
.error
.message
)
72 L
.raise('RPCError', 'RPC call to %s/%s failed with error %d: %s',
73 req
.object
, req
.method
, msg
.error
.code
, msg
.error
.message
|| '?');
79 if (!req
.object
&& !req
.method
) {
82 else if (Array
.isArray(msg
.result
)) {
83 ret
= (msg
.result
.length
> 1) ? msg
.result
[1] : msg
.result
[0];
87 for (var key
in req
.expect
) {
88 if (ret
!= null && key
!= '')
91 if (ret
== null || type
.call(ret
) != type
.call(req
.expect
[key
]))
92 ret
= req
.expect
[key
];
99 if (typeof(req
.filter
) == 'function') {
101 req
.priv
[1] = req
.params
;
102 ret
= req
.filter
.apply(this, req
.priv
);
113 params
: arguments
.length
? this.varargs(arguments
) : undefined
116 return new Promise(L
.bind(function(resolveFn
, rejectFn
) {
117 /* store request info */
124 this.call(msg
, this.parseCallReply
.bind(this, req
));
128 declare: function(options
) {
129 return Function
.prototype.bind
.call(function(rpc
, options
) {
130 var args
= this.varargs(arguments
, 2);
131 return new Promise(function(resolveFn
, rejectFn
) {
132 /* build parameter object */
135 if (Array
.isArray(options
.params
))
136 for (p_off
= 0; p_off
< options
.params
.length
; p_off
++)
137 params
[options
.params
[p_off
]] = args
[p_off
];
139 /* all remaining arguments are private args */
140 var priv
= [ undefined, undefined ];
141 for (; p_off
< args
.length
; p_off
++)
142 priv
.push(args
[p_off
]);
144 /* store request info */
146 expect
: options
.expect
,
147 filter
: options
.filter
,
152 object
: options
.object
,
153 method
: options
.method
156 /* build message object */
170 rpc
.call(msg
, rpc
.parseCallReply
.bind(rpc
, req
));
172 }, this, this, options
);
175 getSessionID: function() {
179 setSessionID: function(sid
) {
183 getBaseURL: function() {
187 setBaseURL: function(url
) {
191 getStatusText: function(statusCode
) {
192 switch (statusCode
) {
193 case 0: return _('Command OK');
194 case 1: return _('Invalid command');
195 case 2: return _('Invalid argument');
196 case 3: return _('Method not found');
197 case 4: return _('Resource not found');
198 case 5: return _('No data received');
199 case 6: return _('Permission denied');
200 case 7: return _('Request timeout');
201 case 8: return _('Not supported');
202 case 9: return _('Unspecified error');
203 case 10: return _('Connection lost');
204 default: return _('Unknown error code');
208 addInterceptor: function(interceptorFn
) {
209 if (typeof(interceptorFn
) == 'function')
210 rpcInterceptorFns
.push(interceptorFn
);
211 return interceptorFn
;
214 removeInterceptor: function(interceptorFn
) {
215 var oldlen
= rpcInterceptorFns
.length
, i
= oldlen
;
217 if (rpcInterceptorFns
[i
] === interceptorFn
)
218 rpcInterceptorFns
.splice(i
, 1);
219 return (rpcInterceptorFns
.length
< oldlen
);