Use 'Content-Type: multipart/form-data; boundary=Ym91bmRhcnk' to send multi-part data.

This commit is contained in:
Daniel Nichter
2013-03-21 07:52:21 -06:00
parent cf0342c69e
commit 0e9e897791
5 changed files with 54 additions and 39 deletions

View File

@@ -969,9 +969,9 @@ sub post {
} }
sub put { sub put {
my ($self, %args) = @_; my $self = shift;
$self->_set( $self->_set(
%args, @_,
method => 'PUT', method => 'PUT',
); );
return $self->response->header('Location'); return $self->response->header('Location');
@@ -979,7 +979,6 @@ sub put {
sub delete { sub delete {
my ($self, %args) = @_; my ($self, %args) = @_;
have_required_args(\%args, qw( have_required_args(\%args, qw(
link link
)) or die; )) or die;
@@ -1006,7 +1005,6 @@ sub delete {
sub _set { sub _set {
my ($self, %args) = @_; my ($self, %args) = @_;
have_required_args(\%args, qw( have_required_args(\%args, qw(
method method
resources resources
@@ -1016,6 +1014,8 @@ sub _set {
my $res = $args{resources}; my $res = $args{resources};
my $link = $args{link}; my $link = $args{link};
my $headers = $args{headers};
my $content = ''; my $content = '';
if ( ref($res) eq 'ARRAY' ) { if ( ref($res) eq 'ARRAY' ) {
PTDEBUG && _d('List of resources'); PTDEBUG && _d('List of resources');
@@ -1047,6 +1047,7 @@ sub _set {
method => $method, method => $method,
link => $link, link => $link,
content => $content, content => $content,
headers => $headers,
); );
}; };
if ( my $e = $EVAL_ERROR ) { if ( my $e = $EVAL_ERROR ) {
@@ -1070,27 +1071,22 @@ sub _request {
)) or die; )) or die;
my $method = $args{method}; my $method = $args{method};
my $link = $args{link}; my $link = $args{link};
my @optional_args = ( my $content = $args{content};
'content', my $headers = $args{headers};
'headers',
);
my ($content, $headers) = @args{@optional_args};
my $req = HTTP::Request->new($method => $link); my $req = HTTP::Request->new($method => $link);
$req->content($content) if $content; if ( $content ) {
if ( uc($method) eq 'DELETE' ) { $req->content($content);
$self->ua->default_header('Content-Length' => 0); }
if ( $headers ) {
map { $req->header($_ => $headers->{$_}) } keys %$headers;
} }
PTDEBUG && _d('Request', $method, $link, Dumper($req)); PTDEBUG && _d('Request', $method, $link, Dumper($req));
my $response = $self->ua->request($req); my $response = $self->ua->request($req);
PTDEBUG && _d('Response', Dumper($response)); PTDEBUG && _d('Response', Dumper($response));
if ( uc($method) eq 'DELETE' ) {
$self->ua->default_header('Content-Length' => undef);
}
if ( !($response->code >= 200 && $response->code < 400) ) { if ( !($response->code >= 200 && $response->code < 400) ) {
die Percona::WebAPI::Exception::Request->new( die Percona::WebAPI::Exception::Request->new(
method => $method, method => $method,
@@ -5650,7 +5646,7 @@ sub send_file {
my $agent_json = as_json($agent, json => $json); my $agent_json = as_json($agent, json => $json);
chomp($agent_json); chomp($agent_json);
my $boundary = '--Ym91bmRhcnk='; # "boundary" in base64 my $boundary = 'Ym91bmRhcnk'; # "boundary" in base64, without a trailing =
my $data = slurp($file); my $data = slurp($file);
$data =~ s/^\s+//; $data =~ s/^\s+//;
@@ -5658,14 +5654,23 @@ sub send_file {
# Put it all together: # Put it all together:
my $resource = <<CONTENT; my $resource = <<CONTENT;
--$boundary
Content-Disposition: form-data; name="agent"
$agent_json $agent_json
$boundary --$boundary
Content-Disposition: form-data; name="data"
$data $data
--$boundary
CONTENT CONTENT
$client->post( $client->post(
link => $link, link => $link,
resources => $resource, resources => $resource,
headers => {
'Content-Type' => "multipart/form-data; boundary=$boundary",
}
); );
return; return;

View File

@@ -35,12 +35,14 @@ sub new {
post => [], post => [],
put => [], put => [],
}, },
last_request => undef,
}; };
return bless $self, $class; return bless $self, $class;
} }
sub request { sub request {
my ($self, $req) = @_; my ($self, $req) = @_;
$self->{last_request} = $req;
my $type = lc($req->method); my $type = lc($req->method);
push @{$self->{requests}}, uc($type) . ' ' . $req->uri; push @{$self->{requests}}, uc($type) . ' ' . $req->uri;
if ( $type eq 'post' || $type eq 'put' ) { if ( $type eq 'post' || $type eq 'put' ) {

View File

@@ -168,12 +168,10 @@ sub post {
return $self->response->header('Location'); return $self->response->header('Location');
} }
# For a successful PUT, the server returns nothing because the caller
# already has the resources URI (if not, the caller should POST).
sub put { sub put {
my ($self, %args) = @_; my $self = shift;
$self->_set( $self->_set(
%args, @_,
method => 'PUT', method => 'PUT',
); );
return $self->response->header('Location'); return $self->response->header('Location');
@@ -181,7 +179,6 @@ sub put {
sub delete { sub delete {
my ($self, %args) = @_; my ($self, %args) = @_;
have_required_args(\%args, qw( have_required_args(\%args, qw(
link link
)) or die; )) or die;
@@ -209,7 +206,6 @@ sub delete {
# Low-level POST and PUT handler. # Low-level POST and PUT handler.
sub _set { sub _set {
my ($self, %args) = @_; my ($self, %args) = @_;
have_required_args(\%args, qw( have_required_args(\%args, qw(
method method
resources resources
@@ -219,6 +215,9 @@ sub _set {
my $res = $args{resources}; my $res = $args{resources};
my $link = $args{link}; my $link = $args{link};
# Optional args
my $headers = $args{headers};
my $content = ''; my $content = '';
if ( ref($res) eq 'ARRAY' ) { if ( ref($res) eq 'ARRAY' ) {
PTDEBUG && _d('List of resources'); PTDEBUG && _d('List of resources');
@@ -250,6 +249,7 @@ sub _set {
method => $method, method => $method,
link => $link, link => $link,
content => $content, content => $content,
headers => $headers,
); );
}; };
if ( my $e = $EVAL_ERROR ) { if ( my $e = $EVAL_ERROR ) {
@@ -276,27 +276,23 @@ sub _request {
)) or die; )) or die;
my $method = $args{method}; my $method = $args{method};
my $link = $args{link}; my $link = $args{link};
my @optional_args = ( # Optional args
'content', my $content = $args{content};
'headers', my $headers = $args{headers};
);
my ($content, $headers) = @args{@optional_args};
my $req = HTTP::Request->new($method => $link); my $req = HTTP::Request->new($method => $link);
$req->content($content) if $content; if ( $content ) {
if ( uc($method) eq 'DELETE' ) { $req->content($content);
$self->ua->default_header('Content-Length' => 0); }
if ( $headers ) {
map { $req->header($_ => $headers->{$_}) } keys %$headers;
} }
PTDEBUG && _d('Request', $method, $link, Dumper($req)); PTDEBUG && _d('Request', $method, $link, Dumper($req));
my $response = $self->ua->request($req); my $response = $self->ua->request($req);
PTDEBUG && _d('Response', Dumper($response)); PTDEBUG && _d('Response', Dumper($response));
if ( uc($method) eq 'DELETE' ) {
$self->ua->default_header('Content-Length' => undef);
}
if ( !($response->code >= 200 && $response->code < 400) ) { if ( !($response->code >= 200 && $response->code < 400) ) {
die Percona::WebAPI::Exception::Request->new( die Percona::WebAPI::Exception::Request->new(
method => $method, method => $method,

View File

@@ -1,8 +1,13 @@
--Ym91bmRhcnk
Content-Disposition: form-data; name="agent"
{ {
"hostname" : "prod1", "hostname" : "prod1",
"uuid" : "123" "uuid" : "123"
} }
--Ym91bmRhcnk= --Ym91bmRhcnk
Content-Disposition: form-data; name="data"
[ [
{ {
"attributes" : { "attributes" : {
@@ -74,3 +79,4 @@
} }
} }
] ]
--Ym91bmRhcnk

View File

@@ -138,6 +138,12 @@ ok(
"Removed data file after sending successfully" "Removed data file after sending successfully"
); );
is(
$ua->{last_request}->header('content-type'),
'multipart/form-data; boundary=Ym91bmRhcnk',
'Content-Type=multipart/form-data; boundary=Ym91bmRhcnk'
) or diag(Dumper($ua));
# ############################################################################# # #############################################################################
# Done. # Done.
# ############################################################################# # #############################################################################