package Perinci::Access; use 5.010; use strict; use warnings; use Log::Any '$log'; use Scalar::Util qw(blessed); use URI; our $VERSION = '0.10'; # VERSION sub new { my ($class, %opts) = @_; $opts{handlers} //= {}; $opts{handlers}{pm} //= 'Perinci::Access::InProcess'; $opts{handlers}{http} //= 'Perinci::Access::HTTP::Client'; $opts{handlers}{https} //= 'Perinci::Access::HTTP::Client'; $opts{handlers}{'riap+tcp'} //= 'Perinci::Access::TCP::Client'; $opts{_handler_objs} //= {}; bless \%opts, $class; } # convert URI string into URI object sub _normalize_uri { my ($self, $uri) = @_; return $uri if blessed($uri); if ($uri =~ /^\w+(::\w+)+$/) { # assume X::Y is a module name my $orig = $uri; $uri =~ s!::!/!g; $uri = "/$uri/"; #return URI->new("pm:$uri"); # to avoid mistakes, die instead die "You specified module name '$orig' as Riap URI, ". "please use '$uri' instead"; } else { return URI->new(($uri =~ /\A[A-Za-z+-]+:/ ? "" : "pm:") . $uri); } } sub request { my ($self, $action, $uri, $extra) = @_; $uri = $self->_normalize_uri($uri); my $sch = $uri->scheme; die "Unrecognized scheme '$sch' in URL" unless $self->{handlers}{$sch}; unless ($self->{_handler_objs}{$sch}) { if (blessed($self->{handlers}{$sch})) { $self->{_handler_objs}{$sch} = $self->{handlers}{$sch}; } else { my $mod_pm = $self->{handlers}{$sch}; $mod_pm =~ s!::!/!g; require "$mod_pm.pm"; $self->{_handler_objs}{$sch} = $self->{handlers}{$sch}->new; } } $self->{_handler_objs}{$sch}->request($action, $uri, $extra); } 1; # ABSTRACT: Wrapper for Perinci Riap clients __END__ =pod =head1 NAME Perinci::Access - Wrapper for Perinci Riap clients =head1 VERSION version 0.10 =head1 SYNOPSIS use Perinci::Access; my $pa = Perinci::Access->new; my $res; # use Perinci::Access::InProcess $res = $pa->request(call => "pm:/Mod/SubMod/func"); # ditto $res = $pa->request(call => "/Mod/SubMod/func"); $res = $pa->request(call => "Mod::SubMod::func"); # use Perinci::Access::HTTP::Client $res = $pa->request(info => "http://example.com/Sub/ModSub/func"); # use Perinci::Access::TCP::Client $res = $pa->request(meta => "riap+tcp://localhost:7001/Sub/ModSub/"); # dies, unknown scheme $res = $pa->request(call => "baz://example.com/Sub/ModSub/"); =head1 DESCRIPTION This module provides a convenient wrapper to select appropriate Riap client (Perinci::Access::*) objects based on URI scheme (or lack thereof). /Foo/Bar/ -> InProcess pm:/Foo/Bar -> InProcess http://... -> HTTP::Client https://... -> HTTP::Client riap+tcp:// -> TCP::Client You can customize or add supported schemes by providing the . =head1 METHODS =head2 new(%opts) -> OBJ Create new instance. Known options: =over 4 =item * handlers (HASH) A mapping of scheme names and class names or objects. If values are class names, they will be require'd and instantiated. The default is: { pm => 'Perinci::Access::InProcess', http => 'Perinci::Access::HTTP::Client', https => 'Perinci::Access::HTTP::Client', 'riap+tcp' => 'Perinci::Access::TCP::Client', } Objects can be given instead of class names. This is used if you need to pass special options when instantiating the class. =back =head2 $pa->request($action, $uri, \%extra) -> RESP Pass the request to the appropriate Riap client objects (as configured in C<handlers> constructor options). RESP is the enveloped result. =head1 SEE ALSO L<Perinci>, L<Riap> =head1 AUTHOR Steven Haryanto <stevenharyanto@gmail.com> =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Steven Haryanto. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut