Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / HTTP / Request / Common.pm
CommitLineData
3fea05b9 1package HTTP::Request::Common;
2
3use strict;
4use vars qw(@EXPORT @EXPORT_OK $VERSION $DYNAMIC_FILE_UPLOAD);
5
6$DYNAMIC_FILE_UPLOAD ||= 0; # make it defined (don't know why)
7
8require Exporter;
9*import = \&Exporter::import;
10@EXPORT =qw(GET HEAD PUT POST);
11@EXPORT_OK = qw($DYNAMIC_FILE_UPLOAD DELETE);
12
13require HTTP::Request;
14use Carp();
15
16$VERSION = "5.824";
17
18my $CRLF = "\015\012"; # "\r\n" is not portable
19
20sub GET { _simple_req('GET', @_); }
21sub HEAD { _simple_req('HEAD', @_); }
22sub PUT { _simple_req('PUT' , @_); }
23sub DELETE { _simple_req('DELETE', @_); }
24
25sub POST
26{
27 my $url = shift;
28 my $req = HTTP::Request->new(POST => $url);
29 my $content;
30 $content = shift if @_ and ref $_[0];
31 my($k, $v);
32 while (($k,$v) = splice(@_, 0, 2)) {
33 if (lc($k) eq 'content') {
34 $content = $v;
35 }
36 else {
37 $req->push_header($k, $v);
38 }
39 }
40 my $ct = $req->header('Content-Type');
41 unless ($ct) {
42 $ct = 'application/x-www-form-urlencoded';
43 }
44 elsif ($ct eq 'form-data') {
45 $ct = 'multipart/form-data';
46 }
47
48 if (ref $content) {
49 if ($ct =~ m,^multipart/form-data\s*(;|$),i) {
50 require HTTP::Headers::Util;
51 my @v = HTTP::Headers::Util::split_header_words($ct);
52 Carp::carp("Multiple Content-Type headers") if @v > 1;
53 @v = @{$v[0]};
54
55 my $boundary;
56 my $boundary_index;
57 for (my @tmp = @v; @tmp;) {
58 my($k, $v) = splice(@tmp, 0, 2);
59 if ($k eq "boundary") {
60 $boundary = $v;
61 $boundary_index = @v - @tmp - 1;
62 last;
63 }
64 }
65
66 ($content, $boundary) = form_data($content, $boundary, $req);
67
68 if ($boundary_index) {
69 $v[$boundary_index] = $boundary;
70 }
71 else {
72 push(@v, boundary => $boundary);
73 }
74
75 $ct = HTTP::Headers::Util::join_header_words(@v);
76 }
77 else {
78 # We use a temporary URI object to format
79 # the application/x-www-form-urlencoded content.
80 require URI;
81 my $url = URI->new('http:');
82 $url->query_form(ref($content) eq "HASH" ? %$content : @$content);
83 $content = $url->query;
84 }
85 }
86
87 $req->header('Content-Type' => $ct); # might be redundant
88 if (defined($content)) {
89 $req->header('Content-Length' =>
90 length($content)) unless ref($content);
91 $req->content($content);
92 }
93 else {
94 $req->header('Content-Length' => 0);
95 }
96 $req;
97}
98
99
100sub _simple_req
101{
102 my($method, $url) = splice(@_, 0, 2);
103 my $req = HTTP::Request->new($method => $url);
104 my($k, $v);
105 my $content;
106 while (($k,$v) = splice(@_, 0, 2)) {
107 if (lc($k) eq 'content') {
108 $req->add_content($v);
109 $content++;
110 }
111 else {
112 $req->push_header($k, $v);
113 }
114 }
115 if ($content && !defined($req->header("Content-Length"))) {
116 $req->header("Content-Length", length(${$req->content_ref}));
117 }
118 $req;
119}
120
121
122sub form_data # RFC1867
123{
124 my($data, $boundary, $req) = @_;
125 my @data = ref($data) eq "HASH" ? %$data : @$data; # copy
126 my $fhparts;
127 my @parts;
128 my($k,$v);
129 while (($k,$v) = splice(@data, 0, 2)) {
130 if (!ref($v)) {
131 $k =~ s/([\\\"])/\\$1/g; # escape quotes and backslashes
132 push(@parts,
133 qq(Content-Disposition: form-data; name="$k"$CRLF$CRLF$v));
134 }
135 else {
136 my($file, $usename, @headers) = @$v;
137 unless (defined $usename) {
138 $usename = $file;
139 $usename =~ s,.*/,, if defined($usename);
140 }
141 $k =~ s/([\\\"])/\\$1/g;
142 my $disp = qq(form-data; name="$k");
143 if (defined($usename) and length($usename)) {
144 $usename =~ s/([\\\"])/\\$1/g;
145 $disp .= qq(; filename="$usename");
146 }
147 my $content = "";
148 my $h = HTTP::Headers->new(@headers);
149 if ($file) {
150 open(my $fh, "<", $file) or Carp::croak("Can't open file $file: $!");
151 binmode($fh);
152 if ($DYNAMIC_FILE_UPLOAD) {
153 # will read file later, close it now in order to
154 # not accumulate to many open file handles
155 close($fh);
156 $content = \$file;
157 }
158 else {
159 local($/) = undef; # slurp files
160 $content = <$fh>;
161 close($fh);
162 }
163 unless ($h->header("Content-Type")) {
164 require LWP::MediaTypes;
165 LWP::MediaTypes::guess_media_type($file, $h);
166 }
167 }
168 if ($h->header("Content-Disposition")) {
169 # just to get it sorted first
170 $disp = $h->header("Content-Disposition");
171 $h->remove_header("Content-Disposition");
172 }
173 if ($h->header("Content")) {
174 $content = $h->header("Content");
175 $h->remove_header("Content");
176 }
177 my $head = join($CRLF, "Content-Disposition: $disp",
178 $h->as_string($CRLF),
179 "");
180 if (ref $content) {
181 push(@parts, [$head, $$content]);
182 $fhparts++;
183 }
184 else {
185 push(@parts, $head . $content);
186 }
187 }
188 }
189 return ("", "none") unless @parts;
190
191 my $content;
192 if ($fhparts) {
193 $boundary = boundary(10) # hopefully enough randomness
194 unless $boundary;
195
196 # add the boundaries to the @parts array
197 for (1..@parts-1) {
198 splice(@parts, $_*2-1, 0, "$CRLF--$boundary$CRLF");
199 }
200 unshift(@parts, "--$boundary$CRLF");
201 push(@parts, "$CRLF--$boundary--$CRLF");
202
203 # See if we can generate Content-Length header
204 my $length = 0;
205 for (@parts) {
206 if (ref $_) {
207 my ($head, $f) = @$_;
208 my $file_size;
209 unless ( -f $f && ($file_size = -s _) ) {
210 # The file is either a dynamic file like /dev/audio
211 # or perhaps a file in the /proc file system where
212 # stat may return a 0 size even though reading it
213 # will produce data. So we cannot make
214 # a Content-Length header.
215 undef $length;
216 last;
217 }
218 $length += $file_size + length $head;
219 }
220 else {
221 $length += length;
222 }
223 }
224 $length && $req->header('Content-Length' => $length);
225
226 # set up a closure that will return content piecemeal
227 $content = sub {
228 for (;;) {
229 unless (@parts) {
230 defined $length && $length != 0 &&
231 Carp::croak "length of data sent did not match calculated Content-Length header. Probably because uploaded file changed in size during transfer.";
232 return;
233 }
234 my $p = shift @parts;
235 unless (ref $p) {
236 $p .= shift @parts while @parts && !ref($parts[0]);
237 defined $length && ($length -= length $p);
238 return $p;
239 }
240 my($buf, $fh) = @$p;
241 unless (ref($fh)) {
242 my $file = $fh;
243 undef($fh);
244 open($fh, "<", $file) || Carp::croak("Can't open file $file: $!");
245 binmode($fh);
246 }
247 my $buflength = length $buf;
248 my $n = read($fh, $buf, 2048, $buflength);
249 if ($n) {
250 $buflength += $n;
251 unshift(@parts, ["", $fh]);
252 }
253 else {
254 close($fh);
255 }
256 if ($buflength) {
257 defined $length && ($length -= $buflength);
258 return $buf
259 }
260 }
261 };
262
263 }
264 else {
265 $boundary = boundary() unless $boundary;
266
267 my $bno = 0;
268 CHECK_BOUNDARY:
269 {
270 for (@parts) {
271 if (index($_, $boundary) >= 0) {
272 # must have a better boundary
273 $boundary = boundary(++$bno);
274 redo CHECK_BOUNDARY;
275 }
276 }
277 last;
278 }
279 $content = "--$boundary$CRLF" .
280 join("$CRLF--$boundary$CRLF", @parts) .
281 "$CRLF--$boundary--$CRLF";
282 }
283
284 wantarray ? ($content, $boundary) : $content;
285}
286
287
288sub boundary
289{
290 my $size = shift || return "xYzZY";
291 require MIME::Base64;
292 my $b = MIME::Base64::encode(join("", map chr(rand(256)), 1..$size*3), "");
293 $b =~ s/[\W]/X/g; # ensure alnum only
294 $b;
295}
296
2971;
298
299__END__
300
301=head1 NAME
302
303HTTP::Request::Common - Construct common HTTP::Request objects
304
305=head1 SYNOPSIS
306
307 use HTTP::Request::Common;
308 $ua = LWP::UserAgent->new;
309 $ua->request(GET 'http://www.sn.no/');
310 $ua->request(POST 'http://somewhere/foo', [foo => bar, bar => foo]);
311
312=head1 DESCRIPTION
313
314This module provide functions that return newly created C<HTTP::Request>
315objects. These functions are usually more convenient to use than the
316standard C<HTTP::Request> constructor for the most common requests. The
317following functions are provided:
318
319=over 4
320
321=item GET $url
322
323=item GET $url, Header => Value,...
324
325The GET() function returns an C<HTTP::Request> object initialized with
326the "GET" method and the specified URL. It is roughly equivalent to the
327following call
328
329 HTTP::Request->new(
330 GET => $url,
331 HTTP::Headers->new(Header => Value,...),
332 )
333
334but is less cluttered. What is different is that a header named
335C<Content> will initialize the content part of the request instead of
336setting a header field. Note that GET requests should normally not
337have a content, so this hack makes more sense for the PUT() and POST()
338functions described below.
339
340The get(...) method of C<LWP::UserAgent> exists as a shortcut for
341$ua->request(GET ...).
342
343=item HEAD $url
344
345=item HEAD $url, Header => Value,...
346
347Like GET() but the method in the request is "HEAD".
348
349The head(...) method of "LWP::UserAgent" exists as a shortcut for
350$ua->request(HEAD ...).
351
352=item PUT $url
353
354=item PUT $url, Header => Value,...
355
356=item PUT $url, Header => Value,..., Content => $content
357
358Like GET() but the method in the request is "PUT".
359
360The content of the request can be specified using the "Content"
361pseudo-header. This steals a bit of the header field namespace as
362there is no way to directly specify a header that is actually called
363"Content". If you really need this you must update the request
364returned in a separate statement.
365
366=item DELETE $url
367
368=item DELETE $url, Header => Value,...
369
370Like GET() but the method in the request is "DELETE". This function
371is not exported by default.
372
373=item POST $url
374
375=item POST $url, Header => Value,...
376
377=item POST $url, $form_ref, Header => Value,...
378
379=item POST $url, Header => Value,..., Content => $form_ref
380
381=item POST $url, Header => Value,..., Content => $content
382
383This works mostly like PUT() with "POST" as the method, but this
384function also takes a second optional array or hash reference
385parameter $form_ref. As for PUT() the content can also be specified
386directly using the "Content" pseudo-header, and you may also provide
387the $form_ref this way.
388
389The $form_ref argument can be used to pass key/value pairs for the
390form content. By default we will initialize a request using the
391C<application/x-www-form-urlencoded> content type. This means that
392you can emulate a HTML E<lt>form> POSTing like this:
393
394 POST 'http://www.perl.org/survey.cgi',
395 [ name => 'Gisle Aas',
396 email => 'gisle@aas.no',
397 gender => 'M',
398 born => '1964',
399 perc => '3%',
400 ];
401
402This will create a HTTP::Request object that looks like this:
403
404 POST http://www.perl.org/survey.cgi
405 Content-Length: 66
406 Content-Type: application/x-www-form-urlencoded
407
408 name=Gisle%20Aas&email=gisle%40aas.no&gender=M&born=1964&perc=3%25
409
410Multivalued form fields can be specified by either repeating the field
411name or by passing the value as an array reference.
412
413The POST method also supports the C<multipart/form-data> content used
414for I<Form-based File Upload> as specified in RFC 1867. You trigger
415this content format by specifying a content type of C<'form-data'> as
416one of the request headers. If one of the values in the $form_ref is
417an array reference, then it is treated as a file part specification
418with the following interpretation:
419
420 [ $file, $filename, Header => Value... ]
421 [ undef, $filename, Header => Value,..., Content => $content ]
422
423The first value in the array ($file) is the name of a file to open.
424This file will be read and its content placed in the request. The
425routine will croak if the file can't be opened. Use an C<undef> as
426$file value if you want to specify the content directly with a
427C<Content> header. The $filename is the filename to report in the
428request. If this value is undefined, then the basename of the $file
429will be used. You can specify an empty string as $filename if you
430want to suppress sending the filename when you provide a $file value.
431
432If a $file is provided by no C<Content-Type> header, then C<Content-Type>
433and C<Content-Encoding> will be filled in automatically with the values
434returned by LWP::MediaTypes::guess_media_type()
435
436Sending my F<~/.profile> to the survey used as example above can be
437achieved by this:
438
439 POST 'http://www.perl.org/survey.cgi',
440 Content_Type => 'form-data',
441 Content => [ name => 'Gisle Aas',
442 email => 'gisle@aas.no',
443 gender => 'M',
444 born => '1964',
445 init => ["$ENV{HOME}/.profile"],
446 ]
447
448This will create a HTTP::Request object that almost looks this (the
449boundary and the content of your F<~/.profile> is likely to be
450different):
451
452 POST http://www.perl.org/survey.cgi
453 Content-Length: 388
454 Content-Type: multipart/form-data; boundary="6G+f"
455
456 --6G+f
457 Content-Disposition: form-data; name="name"
458
459 Gisle Aas
460 --6G+f
461 Content-Disposition: form-data; name="email"
462
463 gisle@aas.no
464 --6G+f
465 Content-Disposition: form-data; name="gender"
466
467 M
468 --6G+f
469 Content-Disposition: form-data; name="born"
470
471 1964
472 --6G+f
473 Content-Disposition: form-data; name="init"; filename=".profile"
474 Content-Type: text/plain
475
476 PATH=/local/perl/bin:$PATH
477 export PATH
478
479 --6G+f--
480
481If you set the $DYNAMIC_FILE_UPLOAD variable (exportable) to some TRUE
482value, then you get back a request object with a subroutine closure as
483the content attribute. This subroutine will read the content of any
484files on demand and return it in suitable chunks. This allow you to
485upload arbitrary big files without using lots of memory. You can even
486upload infinite files like F</dev/audio> if you wish; however, if
487the file is not a plain file, there will be no Content-Length header
488defined for the request. Not all servers (or server
489applications) like this. Also, if the file(s) change in size between
490the time the Content-Length is calculated and the time that the last
491chunk is delivered, the subroutine will C<Croak>.
492
493The post(...) method of "LWP::UserAgent" exists as a shortcut for
494$ua->request(POST ...).
495
496=back
497
498=head1 SEE ALSO
499
500L<HTTP::Request>, L<LWP::UserAgent>
501
502
503=head1 COPYRIGHT
504
505Copyright 1997-2004, Gisle Aas
506
507This library is free software; you can redistribute it and/or
508modify it under the same terms as Perl itself.
509
510=cut
511