Verified Commit db40a106 authored by Roman Lacko's avatar Roman Lacko
Browse files

API: Fix incorrect parameter handling

Array or hash parameters require '[]' suffix when passed to API. This
commit fixes problems when the suffix was not added for other than GET
requests (notably POST and PUT).
parent f19ff947
Loading
Loading
Loading
Loading
+63 −5
Original line number Original line Diff line number Diff line
@@ -202,10 +202,22 @@ sub create_uri {


    # add query parameters
    # add query parameters
    foreach my $param (@{$tmpl->{query} // []}) {
    foreach my $param (@{$tmpl->{query} // []}) {
        my $type = '';
        if ($param =~ s/\[\]$//) {
            $type = 'ARRAY';
        } elsif ($param =~ s/\{\}//) {
            $type = 'HASH';
        }

        if (exists $args->{$param}) {
        if (exists $args->{$param}) {
            if (ref $args->{$param} ne $type) {
                croak "Argument '$param' is expected to be of type '$type',
                        but '" . ref($args->{$param}) . "' is provided";
            }

            if (ref $args->{$param} eq "ARRAY") {
            if (ref $args->{$param} eq "ARRAY") {
                foreach my $val (@{ $args->{$param} }) {
                foreach my $val (@{ $args->{$param} }) {
                    $uri->query_param_append($param, $val);
                    $uri->query_param_append("$param\[\]", $val);
                }
                }
            } elsif (ref $args->{$param} eq "HASH") {
            } elsif (ref $args->{$param} eq "HASH") {
                while (my ($key, $val) = each %{$args->{$param}}) {
                while (my ($key, $val) = each %{$args->{$param}}) {
@@ -214,6 +226,7 @@ sub create_uri {
            } else {
            } else {
                $uri->query_param_append($param => $args->{$param});
                $uri->query_param_append($param => $args->{$param});
            }
            }

            delete $args->{$param};
            delete $args->{$param};
        }
        }
    }
    }
@@ -221,6 +234,47 @@ sub create_uri {
    return $uri;
    return $uri;
}
}


sub _param_exists {
    my ($self, $tmpl, $param) = @_;

    return grep { $_ eq $param }
        @{ $tmpl->{optional} // [] },
        @{ $tmpl->{required} // [] };
}

sub process_post_args {
    my ($self, $tmpl, $args) = @_;

    my @result;
    foreach my $param (keys %$args) {
        if (ref $args->{$param} eq 'ARRAY') {
            if (!$self->_param_exists($tmpl, $param . '[]')) {
                croak "$param: Is an array but $param\[\] is not allowed for this request";
            }

            foreach my $value (@{ $args->{$param} }) {
                push @result, "$param\[\]", $value;
            }
        } elsif (ref $args->{$param} eq 'HASH') {
            if (!$self->_param_exists($tmpl, $param . '{}')) {
                croak "$param: Is a hash but $param\{\} is not allowed for this request";
            }

            foreach my $key (sort keys %{ $args->{$param} }) {
                push @result, "$param\[$key\]", $args->{$param}->{$key};
            }
        } else {
            if (!$self->_param_exists($tmpl, $param)) {
                croak "$param: Is a scalar but $param is not allowed for this request";
            }

            push @result, $param, $args->{$param};
        }
    }

    return @result;
}

sub clean_data {
sub clean_data {
    my ($self, $response) = @_;
    my ($self, $response) = @_;


@@ -277,13 +331,17 @@ sub exec_request {
    croak "Missing arguments [" . join(", ", @missing) . "] for '$tmpl->{name}'" if scalar @missing;
    croak "Missing arguments [" . join(", ", @missing) . "] for '$tmpl->{name}'" if scalar @missing;


    # validate optional arguments
    # validate optional arguments
    my %allargs = map { $_ => 1 } (@{$tmpl->{required}}, @{$tmpl->{optional}});
    my %allargs = map { ($_ =~ s/(\[\]|\{\})$//gr) => 1 }
    my @extra   = grep { !defined $allargs{$_} } keys %$args;
            (@{$tmpl->{required}}, @{$tmpl->{optional}});

    my @extra   = grep { !defined $allargs{$_} }
            keys %$args;

    carp "Extra arguments [" . join(", ", @extra) . "] for '$tmpl->{name}'" if scalar @extra;
    carp "Extra arguments [" . join(", ", @extra) . "] for '$tmpl->{name}'" if scalar @extra;


    my @postdata    = %$args;
    my @postdata = $self->process_post_args($tmpl, $args);
    my $response;
    my $data = [];
    my $data = [];
    my $response;


    croak "Cannot request -iterator if -page is specified as well"
    croak "Cannot request -iterator if -page is specified as well"
        if $rtargs->{-iterator} && defined $rtargs->{-page};
        if $rtargs->{-iterator} && defined $rtargs->{-page};