JRPC::CGI - JSON-RPC 2.0 Processing for CGI and HTTP::Server::Simple::CGI
This package provides JSON-RPC 2.0 services processor for 2 runtimes based on:
CGI (CGI.pm) Plain old CGI scripting (or mod_perl ModPerl::Registry mode)
HTTP::Server::Simple::CGI - a fast and lightweight runtime with a Perl embedded httpd (web server) module.
HTTP::Server::Simple::CGI is especially interesting for doing distributed computation over the http.
Because of the rudimentary nature of CGI (in both good and bad), the JRPC::CGI::handle_cgi($cgi) is to be called explicitly in code (as CGI is not hosted by sophisticated server).
The service method JRPC::CGI::handle_simple_server_cgi($server, $cgi); for HTTP::Server::Simple::CGI can be aliased to local package's handle_request method, which is the request handling method for HTTP::Server::Simple framework (similar to mod_perl's and Nginx's handler($r) method).
Traditional CGI Handler for JRPC. Example CGI wrapper:
#!/usr/bin/perl use CGI; use CGI::Carp qw/fatalsToBrowser warningsToBrowser/; use JRPC::CGI; use SvcTest; # Load Service package my $cgi = CGI->new(); # Process request. Reports all errors to Client as a JSON-RPC error (fault) response. JRPC::CGI::handle_cgi($cgi); exit(0); # This "Service Package" could (and should) be in a separate file (SvcTest.pm). # It will be called back by JRPC. package SvcTest; use Scalar::Util ('reftype'); # Simpliest possible service: # - reflect/echo 'params' (of request) to 'result' (of response) # - Framework will take care of request parsing and response serialization # - On validation errors, Framework will turn a Perl exception to a JSON-RPC fault. # Call this by: ..., "method": "Test.echo", ... sub echo { my ($p, $jrpc) = @_; # Validate, require $p to be HASH (ref). # Framework will convert exceptions to JSON-RPC Fault if (reftype($p) ne 'HASH') {die("param was not found to be a JSON Object");} return($p); } 1;
Wrapper for intercepting a request to HTTP::Server::Simple::CGI. Alias this as a handle_request() in your package implementing HTTP::Server::Simple::CGI. Example: #!/usr/bin/perl { package MyJRPC; use HTTP::Server::Simple::CGI; use base 'HTTP::Server::Simple::CGI'; # Reuse handle_simple_server_cgi, assign as local alias. *handle_request = \&JRPC::CGI::handle_simple_server_cgi; } my $port = $ENV{'HTTP_SIMPLE_PORT'} || 8080; my $pid = MyWebServer->new($port); #my $pid = MyWebServer->new($port)->background(); print "Use 'kill $pid' to stop server (on port $port).\n";
To be able to run server in thread and to be able to terminate the thread, use the following idiom:
# Server thread as anonymous sub. Pass port to run at. my $runmyserver = sub { my ($port) = @_; # Use signaling to kill thread $SIG{'KILL'} = sub { threads->exit(); }; # Run in the same process, NOT spawning a sub process. MyServer->new($port)->run(); }; my $thr = threads->create($runmyserver, $port); # ... # Much later ... terminate server as no more needed. $thr->kill('KILL')->detach(); # This main thread should continue / survive beyond this point ...
JSON-RPC is not a domain for obsessed print(); debugging folks. Printing to STDOUT messes up the JSON-RPC response output. The returned data structure gets automatically converted to a successful JSON-RPC Response (data goes into 'result' member). Any fatal errors thrown as Perl exceptions get automatically converted to a valid JSON-RPC exception / fault (member 'error', and optionally to logs). Any diagnostic messaging goes to response or logs (or both), NOT STDOUT.
Private package (file) for ServerSimple (with direct default handler handle_request())?
In private package use HTTP::Server::Simple::CGI (and inherit from it)
To install JRPC, copy and paste the appropriate command in to your terminal.
cpanm
cpanm JRPC
CPAN shell
perl -MCPAN -e shell install JRPC
For more information on module installation, please visit the detailed CPAN module installation guide.