Paws XXII (Plana est terra)
The next action I had a crack at was 'PutCORSConfiguration' and I was getting the usual;
<Error> <Code>MalformedXML</Code> <Message>The XML you provided was not well-formed or did not validate against our published schema </Message> </Error>
At this points in my Paws adventure I checked the API doc for URI Request Parameters of the PutCORSConfiguration;
PUT /?cors HTTP/1.1 Host: Bucket.s3.amazonaws.com Content-MD5: ContentMD5
and I see I don't have to deal with the 'id' in the 'URI' bug here as I get what I want in the request URI;
'uri' => '/dev.cargotel.paws?cors'
So I looked a little doc again and it wants;
<CORSConfiguration> <CORSRule> <AllowedOrigin>http://www.example.com</AllowedOrigin>
and I was sending;
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><CORSRules><CORSRule><
hence the Malformed XML error.
I ran into this once some time before when dealing with another bug in Paws and I did a change to boto to fix it. This time out I did not want to make a change to boto as that in the long run is not a solution so I had a deeper look.
In boto I fould this;
"CORSRules":{
"type":"list",
"member":{"shape":"CORSRule"},
"flattened":true
},
"flattened" have not seen that before and I had a look in all the Paws code and could not find it so maybe I can use that to drop the 'CORSRules' tag. That would be the best solution no change to boto;
First I need a new trait in Paws::API;
+package Paws::API::Attribute::Trait::Flatten;
+ use Moose::Role;
+ use Moose::Util;
++ Moose::Util::meta_attribute_alias('Flatten');
just a simple logic one like 'ParamInBody' that is already in use;
Next was a change to the templates so I can get this new trait added into the class.
The correct template was 'default/object.tt' and I just added in;
[%- IF (shape.members.$param_name.streaming == 1); traits.push('ParamInBody'); END %]
+ [%- IF (member.flattened == 1); traits.push('Flatten'); END %]
[%- encoder = c.encoders_struct.$member_shape_name; IF (encoder); traits.push('JSONAttribute') %], decode_as => '[% encoder.encoding %]', method => '[% encoder.alias %]'[% END %]
The real problem was finding the correct template took about 45 minutes to find the correct place.
Next was just a quick change to 'Paws::Net::RestXmlCaller' to account for the above;
++ if ($attribute->does('Flatten')){
++ $xml .= $self->_to_xml($attribute_value);
++ }
++ elsif ($call->can('_namspace_uri')){
-- if ($call->can('_namspace_uri')){
...
$xml .= ( join '', map { sprintf '<%s>%s</%s>', $location, $self->_to_xml($_), $location } @{ $attribute->get_value($value) } );
$xml ="<$att_name>$xml</$att_name>"
-- if( $attribute->does('NameInRequest');
++ if( $attribute->does('NameInRequest') and
++ not $attribute->does('Flatten'));
and this time I got
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedHeaders> <AllowedHeader>*</AllowedHeader> </AllowedHeaders> <AllowedMethods> <AllowedMethod>PUT
I still get an invlaid resuslt but I a close;
The boto for 'AllowedHeaders' is
"AllowedHeaders":{
"type":"list",
"member":{"shape":"AllowedHeader"},
"flattened":true
},
so the 'flattened' is there so a little more change to my 'RestXmlCaller' code;
In 'sub_to_xml' I made this change;
- my $location = $attribute->request_name;
- $xml .= "<${att_name}>" . ( join '', map { sprintf '<%s>%s</%s>', $location, $_, $location } @{ $attribute->get_value($value) } ) . "</${att_name}>";
- } elsif ($attribute->type_constraint =~ m/^ArrayRef\[(.*?\:\:.*)\]/) { #assume it's an array of Paws API objects
- my $location = $attribute->does('NameInRequest') ? $attribute->request_name : $att_name;
+
+ my $location = $attribute->request_name;
+
+ $xml .= ( join '', map { sprintf '<%s>%s</%s>', $location, $_, $location } @{ $attribute->get_value($value) } );
+
+ $xml .= "<${att_name}>".$xml ."</${att_name}>"
+ unless($attribute->does('Flatten'));
+
+ } elsif ($attribute->type_constraint =~ m/^ArrayRef\[(.*?\:\:.*)\]/) { #assume it's an array of Paws API objects
my $location = $attribute->does('NameInRequest') ? $attribute->request_name : $att_name;
and I get the correct XML;
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><CORSRule><AllowedMethod>PUT</AllowedMethod><AllowedMethod>POST</AllowedMethod><AllowedMethod>DELETE</AllowedMethod><AllowedOrigin>http://www.example.com</AllowedOrigin><AllowedHeader>*</AllowedHeader></CORSRule><CORSRule><AllowedOrigin>http://www.aws.com</AllowedOrigin><AllowedHeader>*</AllowedHeader><AllowedMethod>PUT</AllowedMethod><AllowedMethod>POST</AllowedMethod></CORSRule></CORSConfiguration>
but Still a 400?? error
After pulling my hair for a while I relaized I was getting this on the URI;
'uri' => '/dev.cargotel.paws',
which should be
'uri' => '/dev.cargotel.paws?cors',
I had while debugging had takeing the above out of bot so I just reverted boto back and got '200' for my command.
However I was getting this warning all over the place!
Use of uninitialized value $name in concatenation (.) or string at /sdk-perl/lib/Paws/Net/RestXmlCaller.pm line 24.
Not 100% sure what this sub;
sub array_flatten_string {
my $self = shift;
my ($name) = shift;
return ($self->flattened_arrays)?'%s.'.$name.'%d':'%s.member.%d';
}
was doing, but the fix was easy enough;
sub array_flatten_string {
my $self = shift;
my ($name) = shift;
$name=""
unless($name);
return ($self->flattened_arrays)?'%s.'.$name.'%d':'%s.member.%d';
}
and time to check it as all the other test are running 100% correct
Leave a comment