Skip to content

Close #53 - Add PUT multipart support #54

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions author/generate.pl
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@
print " \$options->{$params_key} = \$params if defined \$params;\n";
}

my @code;
@code = split /\n/, $endpoint->{code} if $endpoint->{code};
foreach my $line (@code) {
print " $line\n";
}

print ' ';
print 'return ' if $return;
print "\$self->_call_rest_client( '$verb', '$path', [\@_], \$options );\n";
Expand Down
4 changes: 4 additions & 0 deletions author/sections/projects.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
- create_project: project = POST projects?
- create_project_for_user: POST projects/user/:user_id?
- edit_project: PUT projects/:project_id?
- method: edit_project_multipart
spec: PUT projects/:project_id?
note: The request will have "multipart/form-data" header set for uploading files.
code: $options->{content}->{file} = $params;
- fork_project: POST projects/:project_id/fork?
- project_forks: forks = GET projects/:project_id/forks?
- start_project: project = POST projects/:project_id/star
Expand Down
25 changes: 25 additions & 0 deletions lib/GitLab/API/v4.pm
Original file line number Diff line number Diff line change
Expand Up @@ -7340,6 +7340,31 @@ sub edit_project {
return;
}

=item edit_project_multipart

$api->edit_project_multipart(
$project_id,
\%params,
);

Sends a C<PUT> request to C<projects/:project_id>.

The request will have "multipart/form-data" header set for uploading files.
=cut

sub edit_project_multipart {
my $self = shift;
croak 'edit_project_multipart must be called with 1 to 2 arguments' if @_ < 1 or @_ > 2;
croak 'The #1 argument ($project_id) to edit_project_multipart must be a scalar' if ref($_[0]) or (!defined $_[0]);
croak 'The last argument (\%params) to edit_project_multipart must be a hash ref' if defined($_[1]) and ref($_[1]) ne 'HASH';
my $params = (@_ == 2) ? pop() : undef;
my $options = {};
$options->{decode} = 0;
$options->{content}->{file} = $params if defined $params;
$self->_call_rest_client( 'PUT', 'projects/:project_id', [@_], $options );
return;
}

=item fork_project

$api->fork_project(
Expand Down
48 changes: 36 additions & 12 deletions lib/GitLab/API/v4/RESTClient.pm
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,18 @@ sub request {

my $req_method = 'request';
my $req = [ $verb, $url, $options ];
my $boundary;

if ($verb eq 'POST' and ref($content) eq 'HASH' and $content->{file}) {
if (($verb eq 'POST' or $verb eq 'PUT' ) and ref($content) eq 'HASH' and $content->{file}) {
$content = { %$content };
my $file = path( delete $content->{file} );
my $file = delete $content->{file};

my $key = (keys %$file)[0]
if (ref $file);

$file = (ref $file)
? path( $file->{$key} )
: path( $file );

unless (-f $file and -r $file) {
local $Carp::Internal{ 'GitLab::API::v4' } = 1;
Expand All @@ -183,18 +191,34 @@ sub request {
},
};

$req->[0] = $req->[1]; # Replace method with url.
$req->[1] = $data; # Put data where url was.
# So, req went from [$verb,$url,$options] to [$url,$data,$options],
# per the post_multipart interface.

$req_method = 'post_multipart';
$content = undef if ! %$content;
if ($verb eq 'POST') {
$req->[0] = $req->[1]; # Replace method with url.
$req->[1] = $data; # Put data where url was.
# So, req went from [$verb,$url,$options] to [$url,$data,$options],
# per the post_multipart interface.

$req_method = 'post_multipart';
$content = undef if ! %$content;
} elsif ($verb eq 'PUT') {
$boundary .= sprintf("%x", rand 16) for 1..16;
$content = <<"EOL";
--------------------------$boundary
Content-Disposition: form-data; name="$key"; filename="$data->{file}->{filename}"

$data->{file}->{content}
--------------------------$boundary--
EOL
}
}

if (ref $content) {
$content = $self->json->encode( $content );
$headers->{'content-type'} = 'application/json';
if (defined $boundary or ref $content) {
$content = $self->json->encode( $content )
if (ref $content);

$headers->{'content-type'} = (defined $boundary)
? "multipart/form-data; boundary=------------------------$boundary"
: 'application/json';

$headers->{'content-length'} = length( $content );
}

Expand Down