Sledge::Plugin::JSONRPC

API作る必要が出てきたので作ってみた。


package Sledge::Plugin::JSONRPC;
use strict;
use warnings;
use JSON::Syck;

sub import {
my $self = shift;
my $pkg = caller;

$pkg->register_hook(BEFORE_INIT => sub {
my $self = shift;
$self->{_body} = do { local $/; };
});

no strict 'refs';
*{"$pkg\::jsonrpc"} = \&_jsonrpc;
}

sub _jsonrpc {
my $self = shift;

my $req;
# Deserialize request
eval { $req = _deserialize_jsonrpc($self) };
if ($@ || !$req) {
warn qq{Invalid JSONRPC request "$@"};
_serialize_jsonrpc($self,{
result => undef,
eror => 'Invalid request'
});
return 0;
}

my $res = 0;
my $method = $req->{method};
if ($method) {
if (my $code = $self->can("jsonrpc_$method")) {
$res = $self->$code($req);
} else {
warn qq{Couldn't find jsonrpc method "$method"};
}
}

# Serialize response
_serialize_jsonrpc($self,{
result => $res,
error => undef,
id => $req->{id},
});
return $res;
}

sub _deserialize_jsonrpc {
my $self = shift;

my $req = JSON::Syck::Load($self->{_body});
return $req;
}

sub _serialize_jsonrpc {
my ($self, $status) = @_;

my $res = JSON::Syck::Dump($status);

$self->r->content_type('text/javascript+json');
$self->set_content_length(length $res);
$self->send_http_header;
$self->r->print($res);
$self->invoke_hook('AFTER_OUTPUT');
$self->finished(1);
}

1;