package JSONRPC; use strict; use JSON; # インチキJSONRPC & JSONRPC::Transport::HTTP(ほとんど未実装) # JSONRPC::Transport::HTTP::CGIのみをいいかげんに実装 =head1 NAME JSONRPC =head1 SYNOPSIS # In your application class package MyApp; sub own_method { # called by clients ... } # In your main cgi script. use JSONRPC::Transport::HTTP; use MyApp; JSONRPC::Transport::HTTP::CGI->disptch_to('MyApp')->handle(); =head1 SEE ALSO L L =head1 COPYRIGHT Copyright 2005 makamaka [at] donzoko.net This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut sub new { my $class = shift; my $self = {}; bless $self,$class; } # 名前空間のインポートみたいなイメージ # メソッドがcallされると対応するパッケージ名から探す # 今のところモジュール名しか指定できない # JSONRPC::Transport::XXX->disptch_to('MyApp')->handle(); # ↑MyApp.pmからメソッドを探す。 sub dispatch_to { my $class = shift; my $self = $class->new; my @srv = @_; if(@srv){ $self->{_dispatch_to} = [ @srv ] ; $self; } else{ @{ $self->{_dispatch_to} }; } } # リクエストの取得からレスポンスまで(実装はよろしく) sub handle { } # リクエストを取得してください(実装はよろしく) sub requset { } # レスポンス(実装はよろしく) sub response { } # コネクション切断の必要があるエラー(実装はよろしく) sub invalid_request {} # レスポンスしない場合の処理(実装はよろしく) sub no_response {} # JsonRpcデータからメソッドとパラメータを返す sub get_request_data { my $self = shift; my $js = $self->{json_data}; my $method = $js->{method} || ''; my $params = $js->{params} || []; return ($method,$params); } sub find_method { my $self = shift; my $method = shift; no strict 'refs'; for my $srv ( @{$self->{_dispatch_to}} ){ if($srv->can($method)){ my $func = *{"$srv\::$method"}; return $func; } } return; } # メソッドの実行:返り値はJsonRpcデータ sub handle_method { my $self = shift; my ($method,$params) = $self->get_request_data(); if(my $func = $self->find_method($method)){ my $result = $func->($self,@$params); $self->set_response_data($result) } else{ $self->set_err('No such a method.'); } } # notificationの実行 sub notification { my $self = shift; my ($method,$params) = $self->get_request_data(); if(my $func = $self->find_method($method)){ $func->($self,@$params); } return 1; } # Perlデータ構造をJsonRpcに変換 sub set_response_data { my $self = shift; my $value = shift; my $id = $self->request_id; my $error = $self->error; if(!defined $value){ $value = JSON::Null; } if(!defined $error){ $error = JSON::Null; } my $result = { id => $id, result => $value, error => $error, }; return objToJson($result); } # エラーの戻り値としてPerlデータ構造をJsonRpcに変換 sub set_err { my $self = shift; my $error = shift; my $id = $self->request_id; my $result = { id => $id, result => JSON::Null, error => $error, }; return objToJson($result); } # エラーオブジェクトのアクセサ sub error { my $self = shift; $self->{_error} = $_[0] if(@_ > 0); $self->{_error}; } # idのアクセサ sub request_id { my $self = shift; if(@_ > 0){ $self->{_request_id} = $_[0]; if(ref($self->{_request_id}) =~ /JSON/ and !defined $self->{_request_id}->{value}){ $self->{_request_id} = undef; } } $self->{_request_id}; } 1; __END__ # for client sub InvalidServerResponse {} sub MalformedJSONRpc {} sub JSONRPCError {}