Skip Menu |

This queue is for tickets about the libwww-perl CPAN distribution.

Report information
The Basics
Id: 91250
Status: resolved
Priority: 0/
Queue: libwww-perl

People
Owner: Nobody in particular
Requestors: Ian.Goodacre [...] xtra.co.nz
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 6.05
Fixed in: (no value)



Subject: LWP::UserAgent::put does not handle %form or @form as documented
Documentation for LWP::UserAgent says: $ua->put( $url, \%form ) $ua->put( $url, \@form ) $ua->put( $url, \%form, $field_name => $value, ... ) $ua->put( $url, $field_name => $value,... Content => \%form ) $ua->put( $url, $field_name => $value,... Content => \@form ) $ua->put( $url, $field_name => $value,... Content => $content ) This method will dispatch a PUT request on the given $url, with %form or @form providing the key/value pairs for the fill-in form content. Additional headers and content options are the same as for the get() method. This method will use the PUT() function from HTTP::Request::Common to build the request. See HTTP::Request::Common for a details on how to pass form content and other advanced features. But the forms with \%form or \@form do not work: the content isn't generated. This is because they use HTTP::Request::Common PUT to build the request and PUT doesn't accept the content as a reference. Attached is a patch to HTTP::Request::Common to make PUT accept content as POST does. With this patch, LWP::UserAgent::put works as documented. Enhancing HTTP::Request::Common seems a better solution than fixing LWP::UserAgent directly as it would be necessary to duplicate non-trivial function to do the latter.
Subject: http-request-common.patch
From 95cdc27991dc47a8d6de55742deef21b910b45a4 Mon Sep 17 00:00:00 2001 From: Ian Goodacre <Ian.Goodacre@xtra.co.nz> Date: Mon, 9 Dec 2013 07:56:12 +1300 Subject: [PATCH] Change PUT to handle content like POST The documentation for LWP::UserAgent::put says: $ua->put( $url, \%form ) $ua->put( $url, \@form ) $ua->put( $url, \%form, $field_name => $value, ... ) $ua->put( $url, $field_name => $value,... Content => \%form ) $ua->put( $url, $field_name => $value,... Content => \@form ) $ua->put( $url, $field_name => $value,... Content => $content ) This method will dispatch a PUT request on the given $url, with %form or @form providing the key/value pairs for the fill-in form content. Additional headers and content options are the same as for the get() method. But the calls with %form or @form do not set the content because HTTP::Request::Common::PUT does not accept such parameters and LWP::UserAgent uses HTTP::Request::Common::PUT to build the request. This change enhances HTTP::Request::Common so that LWP::UserAgent::put will work as documented. --- lib/HTTP/Request/Common.pm | 106 ++++++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 34 deletions(-) diff --git a/lib/HTTP/Request/Common.pm b/lib/HTTP/Request/Common.pm index 79e9e5e..c1642c7 100644 --- a/lib/HTTP/Request/Common.pm +++ b/lib/HTTP/Request/Common.pm @@ -19,13 +19,25 @@ my $CRLF = "\015\012"; # "\r\n" is not portable sub GET { _simple_req('GET', @_); } sub HEAD { _simple_req('HEAD', @_); } -sub PUT { _simple_req('PUT' , @_); } sub DELETE { _simple_req('DELETE', @_); } +sub PUT +{ + my $url = shift; + my $req = HTTP::Request->new(PUT => $url); + return _process_put_post_args($req, @_); +} + sub POST { my $url = shift; my $req = HTTP::Request->new(POST => $url); + return _process_put_post_args($req, @_); +} + +sub _process_put_post_args +{ + my $req = shift; my $content; $content = shift if @_ and ref $_[0]; my($k, $v); @@ -356,6 +368,10 @@ $ua->request(HEAD ...). =item PUT $url, Header => Value,... +=item PUT $url, $form_ref, Header => Value,... + +=item PUT $url, Header => Value,..., Content => $form_ref + =item PUT $url, Header => Value,..., Content => $content Like GET() but the method in the request is "PUT". @@ -366,35 +382,16 @@ there is no way to directly specify a header that is actually called "Content". If you really need this you must update the request returned in a separate statement. -=item DELETE $url - -=item DELETE $url, Header => Value,... - -Like GET() but the method in the request is "DELETE". This function -is not exported by default. - -=item POST $url - -=item POST $url, Header => Value,... - -=item POST $url, $form_ref, Header => Value,... - -=item POST $url, Header => Value,..., Content => $form_ref - -=item POST $url, Header => Value,..., Content => $content - -This works mostly like PUT() with "POST" as the method, but this -function also takes a second optional array or hash reference -parameter $form_ref. As for PUT() the content can also be specified -directly using the "Content" pseudo-header, and you may also provide -the $form_ref this way. +The content of the request can also be specified by passing $form_ref +(a reference to a hash or array of key/value pairs) as optional +second argument or as value of the "Content" pseudo-header. The $form_ref argument can be used to pass key/value pairs for the form content. By default we will initialize a request using the C<application/x-www-form-urlencoded> content type. This means that -you can emulate an HTML E<lt>form> POSTing like this: +you can generate an HTML PUT request with form content like this: - POST 'http://www.perl.org/survey.cgi', + PUT 'http://www.perl.org/survey.cgi', [ name => 'Gisle Aas', email => 'gisle@aas.no', gender => 'M', @@ -404,7 +401,7 @@ you can emulate an HTML E<lt>form> POSTing like this: This will create an HTTP::Request object that looks like this: - POST http://www.perl.org/survey.cgi + PUT http://www.perl.org/survey.cgi Content-Length: 66 Content-Type: application/x-www-form-urlencoded @@ -413,12 +410,12 @@ This will create an HTTP::Request object that looks like this: Multivalued form fields can be specified by either repeating the field name or by passing the value as an array reference. -The POST method also supports the C<multipart/form-data> content used +The PUT method also supports the C<multipart/form-data> content used for I<Form-based File Upload> as specified in RFC 1867. You trigger -this content format by specifying a content type of C<'form-data'> as -one of the request headers. If one of the values in the $form_ref is -an array reference, then it is treated as a file part specification -with the following interpretation: +this content format by specifying a content type of C<'form-data'> +or C<'multipart/form-data'> as one of the request headers. If one of +the values in the $form_ref is an array reference, then it is treated +as a file part specification with the following interpretation: [ $file, $filename, Header => Value... ] [ undef, $filename, Header => Value,..., Content => $content ] @@ -439,7 +436,7 @@ returned by LWP::MediaTypes::guess_media_type() Sending my F<~/.profile> to the survey used as example above can be achieved by this: - POST 'http://www.perl.org/survey.cgi', + PUT 'http://www.perl.org/survey.cgi', Content_Type => 'form-data', Content => [ name => 'Gisle Aas', email => 'gisle@aas.no', @@ -448,11 +445,11 @@ achieved by this: init => ["$ENV{HOME}/.profile"], ] -This will create an HTTP::Request object that almost looks this (the +This will create an HTTP::Request object that almost looks like this (the boundary and the content of your F<~/.profile> is likely to be different): - POST http://www.perl.org/survey.cgi + PUT http://www.perl.org/survey.cgi Content-Length: 388 Content-Type: multipart/form-data; boundary="6G+f" @@ -493,6 +490,47 @@ applications) like this. Also, if the file(s) change in size between the time the Content-Length is calculated and the time that the last chunk is delivered, the subroutine will C<Croak>. +The put(...) method of "LWP::UserAgent" exists as a shortcut for +$ua->request(PUT ...). + + +=item DELETE $url + +=item DELETE $url, Header => Value,... + +Like GET() but the method in the request is "DELETE". This function +is not exported by default. + +=item POST $url + +=item POST $url, Header => Value,... + +=item POST $url, $form_ref, Header => Value,... + +=item POST $url, Header => Value,..., Content => $form_ref + +=item POST $url, Header => Value,..., Content => $content + +This works like PUT() but with "POST" as the method. + +You can emulate an HTML E<lt>form> POSTing like this: + + POST 'http://www.perl.org/survey.cgi', + [ name => 'Gisle Aas', + email => 'gisle@aas.no', + gender => 'M', + born => '1964', + perc => '3%', + ]; + +This will create an HTTP::Request object that looks like this: + + POST http://www.perl.org/survey.cgi + Content-Length: 66 + Content-Type: application/x-www-form-urlencoded + + name=Gisle%20Aas&email=gisle%40aas.no&gender=M&born=1964&perc=3%25 + The post(...) method of "LWP::UserAgent" exists as a shortcut for $ua->request(POST ...). -- 1.8.5.1