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


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


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 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;


the URI param part would be;


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


Looking back at what I have in boto


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


and my $vars hash-ref is


and when this code runs

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

the end product is


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'};


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