[misc][OpenSocial] OpenSocial RPC Protocol Specification と shindig snapshot 1.1 の実装が不一致な件
やっぱりJavaScript側全部作り直さないとだめかなー。さすがにいらいらしてきた*1。ので、DQ9でもやってから続きの実装をしようかと。
Gadget XMLのコード。shindig の ifr で処理させるもの。
<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="Hello World!"> <Require feature="opensocial-0.9" /> </ModulePrefs> <Content type="html"> <![CDATA[ <div id="#content"></div> <script type="text/javascript"> var req = opensocial.newDataRequest(); req.add(req.newFetchPersonRequest('VIEWER'), 'viewer'); req.send(function(response) { alert(response.get('viewer').getData().getDisplayName()); }); </script> ]]> </Content> </Module>
で、これをfirebugsで接続見ると、
[{"method":"people.get","params":{"userId":["@viewer"],"groupId":"@self","fields":["id","name","thumbnailUrl" ,"id","displayName"]},"id":"viewer"}]
JSON-RPCのバッチリクエストがいくわけさ。まぁそうだよね、ってことで、JSON-RPCの規格に従って、
[ { "id" : "viewer", "result":{ "name":"Jane Doe",// "displayName":"Jone Doe", "gender":"female", "id":"example.org:34KJDCSKJN2HHF0DW20394" } } ]
で返すようにRackのconfig.ruを書くが、全然動かない。
ShindigのJavaScriptを読みあさるの巻。
// features/src/main/javascript/features/opensocial-jsonrpc/jsonrpccontainer.js // line 156 var sendResponse = function(result) {
これが、makeNonProxiedRequest のコールバックハンドラになっている。JSONをパースした結果はresult.data に入っているはず。
// features/src/main/javascript/features/opensocial-jsonrpc/jsonrpccontainer.js // line 162 result = result.data;
OK。こういう書き方大嫌いだけど我慢する。
// features/src/main/javascript/features/opensocial-jsonrpc/jsonrpccontainer.js // line 167 // Map from indices to ids. for (var i = 0; i < result.length; i++) { result[result[i].id] = result[i]; }
配列を勝手にオブジェクトにするなー!これはひどい、が、我慢我慢。
この時点で、result を整理すると
result[0] -> { "id" : "viewer", "result":{ "name":"Jane Doe", "displayName":"Jone Doe", "gender":"female", "id":"example.org:34KJDCSKJN2HHF0DW20394" } } result["viewer"] -> { "id" : "viewer", "result":{ "name":"Jane Doe", "displayName":"Jone Doe", "gender":"female", "id":"example.org:34KJDCSKJN2HHF0DW20394" } }
ってことか。意味がわからん。続いて、JSON-RPCのレスポンスオブジェクトを作る。
// features/src/main/javascript/features/opensocial-jsonrpc/jsonrpccontainer.js // line 172 for (var k = 0; k < requestObjects.length; k++) { var request = requestObjects[k]; var response = result[k]; if (request.key && response.id !== request.key) { throw "Request key(" + request.key + ") and response id(" + response.id + ") do not match"; }
リクエストに対応するresultを取るってことですね。なんでrequest.idではなくてrequest.keyなのかは謎ですがね。
しかし、これは罠が。
var rawData = response.data; var error = response.error;
いや、おい、response.data って。undefined なんですが。
JSON-RPC にも、ShindigのJSON-RPCにもそんなこと書いてなくない?と思ってSPEC確かめる。
POST /rpc HTTP/1.1
http://www.opensocial.org/Technical-Resources/opensocial-spec-v09/RPC-Protocol.html#personEx
Host: api.example.org
Authorization:
Content-Type: application/json
[
{
"method" : "people.get",
"id" : "myself"
},
{
"method" : "people.get",
"id" : "myfriends"
"params: {
"groupId" : "@friends"
}
}
]
HTTP/1.x 207 Multi-Status
Content-Type: application/json
[
{
"id" : "myself",
"result" : {
"id" : "example.org:34KJDCSKJN2HHF0DW20394",
"name" : { "unstructured" : "Jane Doe"},
"gender" : "female"
}
},
{
"id" : "myfriends"
"error" : {
"code" : 401
}
}
]
|
result って書いているじゃん。0.8 のほうも同じ。困ったもんだ。仕方がないので、とりあえず、仕様よりも実装を優先して、
[ { "id" : "viewer", "data":{ "name":"Jane Doe",// "displayName":"Jone Doe", "gender":"female", "id":"example.org:34KJDCSKJN2HHF0DW20394" } } ]
って返すようにしました。そしたら、最初に書いたgadget xml は動きました。
正解の config.ru を書いておくと、
# config.ru require 'rubygems' require 'json' run proc{|env| obj = [ { "id" => "viewer", "data" => { "id" => "example.org:34KJDCSKJN2HHF0DW20394", "name" => "Jane Doe", "displayName" => "Jone Doe", "gender" => "female" } } ] [200, {'Content-Type'=>'text/plain'}, obj.to_json] }
で、あとは、obj = のところを サーバーサイドのJSON-RPCインプリとして実装してあげれば良さそうです。
ってか、Shindig、リファレンスインプリのくせして、ソースが読みにくいように感じるのは自分だけなのかなー。
*1:しかし、snapshotなんだから文句いうなよ!というのはごもっともですねw