Group
Extension

Template-Plugin-WebService/lib/Template/Plugin/WebService.pm

package Template::Plugin::WebService;

use strict;

use base qw(Template::Plugin);

use vars qw($VERSION);

$VERSION = '0.16';

use CGI::Ex;

use Carp qw(confess);
use CGI::Cookie;
use Storable qw(thaw);
use WWW::Mechanize;

sub new {
    my $class   = shift;
    my $context = shift;
    bless { _CONTEXT => $context, }, $class;
}

sub load {
    my ($class, $context) = @_;
    return $class;
}

sub URLEncode {
    my $arg = shift;
    my ($ref, $return) = ref($arg) ? ($arg, 0) : (\$arg, 1);

    $$ref =~ s/([^\w\.\ -])/sprintf("%%%02X",ord($1))/eg;
    $$ref =~ tr/\ /+/;

    return $return ? $$ref : '';
}

sub get_outserial {
    my $self = shift;
    my $url = shift;
    my $form = shift;

    my $outserial_key = $self->outserial_key;
    
    my $outserial = 'json';

    if($form->{$outserial_key}) {
        $outserial = $form->{$outserial_key};
    } elsif($url =~ /\b$outserial_key=(\w+)/) {
        $outserial = $1;
    }

    return $outserial;
}

sub make_form {
    return '' if !@_;
    my ($hash, $keys);
    if (ref $_[0]) {
        $hash = shift;
        $keys = shift() if @_ && ref $_[0];
    } else {
        $hash = {@_};
    }
    $keys ||= [ sort keys %$hash ];
    my $str = "";
    foreach my $key (@$keys) {
        $hash->{$key} = "" if !exists($hash->{$key});
        my $ref = ref($hash->{$key});
        next if $ref && $ref eq 'HASH';
        my $array = ($ref eq 'ARRAY') ? $hash->{$key} : [ $hash->{$key} ];
        foreach my $val (@$array) {
            my $ref2 = ref($val);
            next if $ref2 && $ref2 eq 'HASH';
            my $array2 = ($ref2 eq 'ARRAY') ? $val : [$val];
            foreach (@$array2) {
                $str .= URLEncode($key) . "=" . URLEncode($_ . '') . "&";
            }
        }
    }
    chop $str;
    return $str;
}

sub content_cleanup {
    my $self = shift;
    my $content_ref = shift;
}

sub default_host {
    return '127.0.0.1';
}

sub outserial_key {
    return 'outserial';
}

sub webservice_call {
    my $self = shift;
    my $url  = shift || confess 'need a url';
    my $form = shift || {};

    confess 'form needs to be a hash ref' unless(UNIVERSAL::isa($form, 'HASH'));

    my $host;

    if($url =~ m@^https?://([^/]+)@) {
        $host = $1;
    } else {
        $host = $self->default_host;
        $url = "http://$host$url";
    }

    if (scalar keys %$form) {
        $url .= ($url =~ /\?/) ? '&' : '?';
        $url .= make_form($form);
    }

    my $mech = WWW::Mechanize->new;

    my %cookies = fetch CGI::Cookie;

    my $content;

    if(%cookies && scalar keys %cookies) {
        require HTTP::Cookies;
        require WWW::Mechanize;

        my $cj = HTTP::Cookies->new();
        foreach my $cookie_key (keys %cookies) {
            $cj->set_cookie(0, $cookie_key, $cookies{$cookie_key}->value, '/', $host);
        }
        $mech = WWW::Mechanize->new(cookie_jar => $cj);
        $content = $mech->get($url)->content;
    } else {
        require LWP::Simple;
        $content = LWP::Simple::get($url);
    }

    $self->content_cleanup(\$content);

    my $obj;

    my $outserial = $self->get_outserial($url, $form);

    if($outserial eq 'storable') {
        require Storable;
        $obj = Storable::thaw($content);
    } elsif($outserial eq 'xml') {
        require XML::Simple;
        $obj = XML::Simple::XMLin($content);
    } elsif($outserial eq 'yaml') {
        require YAML;
        $obj = YAML::Load($content);
    } else {
        require JSON;
        $obj = JSON::from_json($content);
    }

    return $obj;
}

1;

__END__

=head1 NAME

Template::Plugin::WebService - plugin to allow webservice calls
from Template and Template::Alloy

=head1 SYNOPSIS

  [% USE web_service = WebService %]
  [% form = { 'outserial' => 'xml' } %]
  [% stuff = web_service.webservice_call(url, form) %]
  # url is the url to hit

  [% stuff = web_service.webservice_call('/path/to/api', form) %]
  # form is a hash ref that gets appended to the url
  # url can be relative, where the domain defaults to $self->default_host (127.0.0.1)

  [% stuff = web_service.webservice_call('http://domain.com/path/to/api', form) %]

=head1 DESCRIPTION

Template::Plugin::WebService helps handle HTTP from a template.

=head1 FEATURES

 - handles web requests from your template
 - passes along a passed in form
 - passes along any cookies
 - specify serialization via form or just in the url's query_string
 - handles many serializations (JSON, Storable, XML::Simple, YAML)
 - defaults to JSON

=head1 OVERRIDABLE METHODS

content_cleanup - gets sent a Template::Plugin::WebService object and a 
reference to the response content

default_host - gets prepended to your url if your url doesn't start with 
http://.  Defaults to 127.0.0.1

outserial_key - server sends out a key which defines serialization.  
Defaults to outserial.

=head1 AUTHOR

Copyright 2008, Earl J. Cahill. All rights reserved.

This library is free software; you can redistribute it and/or modify 
it under the same terms as Perl itself.

Address bug reports and comments to: cahille@yahoo.com

When sending bug reports, please provide the version of 
Template::Plugin::WebService, the version of Perl, and the name
and version of the operating system you are using.

Earl Cahill, cahille@yahoo.com

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2008 by Earl Cahill

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
at your option, any later version of Perl 5 you may have available.


=cut



Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.