気づいたら自分の投稿が合計100回もストックされていました。みなさんありがとうございます、あらっきぃです。
method_missing を利用して動的にAPIのエンドポイントにアクセスする を読んで、ES.nextのProxyを使ってJSON-RPCを呼んだら面白そうな気がしたので実装しました。
ちゃちゃっと作ったものだし、そもそも似たようなライブラリがすでにありそう。
ちなみにJSON-RPCというのは、リモート環境にある関数をネットワークからJSONにデータを載せてでリクエストして、実行するプロトコルです。
Ideone APIとかで使えます。(というかそれでしか使ったことない)
var
request = require('request');
function JsonRpcClient(url) {
return Proxy.create({
get: function(_, method) {
var
requester = function() {
var
args = Array.prototype.slice.call(arguments, 0);
return call.bind(this, method, args);
};
requester.call = function(params, callback) {
call(method, params, callback);
};
return requester;
}
});
function call(method, params, callback) {
var
body = JSON.stringify({
jsonrpc: '2.0',
id: +(new Date),
method: method,
params: params,
});
request(url, {
method: 'POST',
body: body,
header: {
'Content-Length': Buffer.byteLength(body, encoding='utf8'),
},
json: true,
}, function(err, res, body) {
if(body && body.error) {
err = new Error(body.error.msg);
err.data = body.error;
}
callback(err, body && body.result);
});
}
}
module.exports = {
createClient : JsonRpcClient,
};
例として ideone のAPIを呼んでみます。
user
とpass
は自分のものを使ってください。
また、このコードを実行するためには上記のjsonrpc.js
と同じディレクトリに置いて,
nodeに--harmony-proxies
オプションを付けてください。
var
async = require('async'),
ideone = require('./jsonrpc').createClient('http://ideone.com/api/1/service.json');
var
user = 'your user',
pass = 'your pass',
lang = {'python': 4, 'ruby': 17}['ruby'],
src = 'puts "Hello, World!"',
input = '';
/*
ideone.testFunction(user, pass)(function(err, res) {
console.log(res);
});
*/
async.waterfall([
function(next) {
console.log('createSubmission');
ideone.createSubmission(user, pass, src, lang, input, true, false)(next);
},
function loop(data, next) {
var
link = data.link;
console.log('getSubmissionStatus: %s', link);
ideone.getSubmissionStatus(user, pass, link)(function(err, res) {
console.log(res);
if(err){
next(err);
return;
}
if(res.status == 0){
next(null, link);
return;
}
setTimeout(function(){
loop(data, next);
}, 100);
});
},
function(link, next) {
console.log('getSubmissionDetails');
ideone.getSubmissionDetails(user, pass, link, false, false, true, true, true)(next);
},
], function(err, result) {
if(err) {
console.log(err);
return;
}
console.log(result);
});
ideone.createSubmission
のように、APIをメソッドのように呼び出していることに注目!
ところでgetSubmissionStatus
を呼び出して実行の終了を確かめている辺り、async.jsを使ってもっとスムーズに実装できたりしないんでしょうか?
参考
- Old Proxy API Es.nextのProxyの詳細。残念なことにNode.jsでサポートされているのはOld Proxy APIなんです…。
-
jabsorbのJSON-RPCインターフェイスにRubyで接続してみる - うなの日記 Rubyで
method_missing
を使って似たようなことをした例。参考にさせてもらいました。 - [意外と便利なJSON RPC](TechTalkManiacs - http://d.hatena.ne.jp/kagigotonet/20121204/1354630831) JSON-RPCについてはここを見てください。