Paws XXVII (Templated Paws)


Well today on paws I figured I would take a look and see what was outstanding in terms of code to fix. All that I could find was only really one thing and this boto fix well really a Kludge


/{Bucket}?action
/{Bucket}?action&id={Id}

where I add the id to the URI to get around a bug/problems when running this code on RestXmlCaller.pm;


$uri->query_form(%$qparams); 

would scramble the URI so the call would fail.

What I would like to do is roll back the changes I have made for Boto and see if I can find a pure Perl solution to my problem.

Looking at my notes from before and rereading all the pod for I think six or seven of the various CPAN modules that used when creating a request with Paws I was still empty handed.

The level of my desperation went so far as me changed the installed CPAN module URL.pm to see if had to fix that.

Well no luck!

I eventually asked a simple question!

What is the difference between a Query Param and a URI param??


Well it turns our this is largely a semantic API difference. In an API the URI is usually used to describe the endpoint part of the path.

Given this example URL;

https::/pickmydog.com/api/1.1/dogs/big

the URI param part would be;

'dogs/big'

While the Query Prams are used to modify the URI like this;

dogs/big?colour=red&coat=thick

Looking back at what I have in boto


 /{Bucket}?action

the stuff after the '?' Is really part of the query sting not the endpoint, bad API design on AWS's part I guess but then again they return JSON on an XML API so it should be expected.

So I had a bit of a brain storm, why not just treat the attributes that have either the 'ParamInQuery' or 'ParamInURI' the same and run them though URI::Template?

So first I commented out all the code to do with Query Params


    my $qparams = { $uri->query_form };
--  foreach my $attribute ($call->meta->get_all_attributes) {
--    my $att_name = $attribute->name;
--    if ($attribute->does('Paws::API::Attribute::Trait::ParamInQuery')) {
--      $qparams->{ $attribute->query_name } = $call->$att_name if (defined $call->$att_name);
--    }
-- }

my $qparams = { $uri->query_form };
++ #foreach my $attribute ($call->meta->get_all_attributes) {
++ # my $att_name = $attribute->name;
++ # if ($attribute->does('Paws::API::Attribute::Trait::ParamInQuery')) {
++ # $qparams->{ $attribute->query_name } = $call->$att_name if (defined $call->$att_name);
++ # }
++ #}

then I modified the '_call_uri' sub to handle 'Query Params' as well


  my $joiner ='?';
  $joiner ='&'
    if (index($uri_template,'?') != -1);
   
    foreach my $attribute ($call->meta->get_all_attributes) {
       if ($attribute->does('Paws::API::Attribute::Trait::ParamInQuery')) {
           my $att_name = $attribute->name;
           $uri_template .= $joiner.$attribute->query_name."={".$att_name."}";
           $vars->{ $att_name } = $call->$att_name;
           $joiner ='&';
       }
    }
    foreach my $attribute ($call->meta->get_all_attributes)
    {

if ($attribute->does('Paws::API::Attribute::Trait::ParamInURI')) {
my $att_name = $attribute->name;

What the above does is set a joiner to '?' and then back to '&' if that '?' is already in the template.

Next I iterate over the attributes checking for those with the 'ParamInQuery' trait. For each of these I add them to the template sting $uri_template and the value into the $vars hash-ref.

Finally I set $joiner to '&' just in case there are no URI params in the call.

After all of that I just carry on as before and now my URI template is


/{Bucket}?action&id={Id}

and my $vars hash-ref is


{
Bucket=>'some.bucket.on.aws'
id=>'Some_required_id'
}

and when this code runs


my $t = URI::Templae->new( $uri_template );
my $uri = $t->process($vars);

the end product is


/some.bucket.on.aws?action=&id=some_required_id

Just what I needed.

I checked over boto and rolled back some twenty plus changes I had added in over the past few weeks.

Now I have NO!!! boto changes for any of my 'S3' fixes.

I think I am getting close to doing this patch;


package Paws::S3;
--  warn "Paws::S3 is not stable / supported / entirely developed" unless $ENV{'PAWS_SILENCE_UNSTABLE_WARNINGS'};



3e7f15ab1c562a7b131e803fee68c52b.jpg

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations