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!
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'};
Leave a comment