mono/packages/vfs/ref/rpc/JSON-RPC-2.ts

71 lines
2.1 KiB
TypeScript

import { InvalidRequest, JSON_RPC_ERROR, MethodNotFound, ParserError } from './JSON-RPC-2-Errors';
import { Response } from './JSON-RPC-2-Response';
import * as _ from 'lodash';
const parse = require('co-body');
const debug = require('debug');
export type JSONRPC = any;
export function JSON_RPC_2(): JSONRPC {
let registry = Object.create(null);
return {
registry: registry,
use: function (name: string, func: Function, owner: any = null) {
if (registry[name]) {
debug('Overwrite already registered function \'%s\'', name);
}
else {
debug('Register function \'%s\'', name);
}
if (owner) {
registry[name] = {
owner: owner,
handler: func
};
} else {
registry[name] = func;
}
},
app: function () {
return function* rpcApp(next: Function) {
let body: any = {};
try {
body = yield parse.json(this);
}
catch (err) {
this.body = new Response(null, new ParserError(err.message));
return;
}
if (body.jsonrpc !== '2.0'
|| !body.hasOwnProperty('method')
|| !body.hasOwnProperty('id')) {
debug('JSON is not correct JSON-RPC2 request: %O', body);
this.body = new Response(body.id || null, new InvalidRequest());
return;
}
if (!registry[body.method]) {
debug('Method not found \'%s\' in registry', body.method);
this.body = new Response(body.id, new MethodNotFound(body.method));
return;
}
debug('Request: %o', body);
if (_.isObject(registry[body.method])) {
const _method = body.method;
const service = registry[_method];
const args = _.values(body.params).concat([this.request, this]);
try {
const result = yield service.handler.apply(service.owner, args) || {};
this.body = new Response(body.id, null, result);
return;
} catch (err) {
console.error('JSON-RPC Error : ', err);
this.body = new Response(body.id || null, new JSON_RPC_ERROR(err, 1));
return;
}
}
let result = yield registry[body.method](body.params) || {};
this.body = new Response(body.id, null, result);
return;
};
}
};
}