Blame lib/HTTP/Request/Common.pm

Packit a09cf7
package HTTP::Request::Common;
Packit a09cf7
Packit a09cf7
use strict;
Packit a09cf7
use warnings;
Packit a09cf7
Packit a09cf7
our $VERSION = '6.18';
Packit a09cf7
Packit a09cf7
our $DYNAMIC_FILE_UPLOAD ||= 0;  # make it defined (don't know why)
Packit a09cf7
Packit a09cf7
use Exporter 5.57 'import';
Packit a09cf7
Packit a09cf7
our @EXPORT =qw(GET HEAD PUT PATCH POST);
Packit a09cf7
our @EXPORT_OK = qw($DYNAMIC_FILE_UPLOAD DELETE);
Packit a09cf7
Packit a09cf7
require HTTP::Request;
Packit a09cf7
use Carp();
Packit a09cf7
Packit a09cf7
my $CRLF = "\015\012";   # "\r\n" is not portable
Packit a09cf7
Packit a09cf7
sub GET  { _simple_req('GET',  @_); }
Packit a09cf7
sub HEAD { _simple_req('HEAD', @_); }
Packit a09cf7
sub DELETE { _simple_req('DELETE', @_); }
Packit a09cf7
sub PATCH { request_type_with_data('PATCH', @_); }
Packit a09cf7
sub POST { request_type_with_data('POST', @_); }
Packit a09cf7
sub PUT { request_type_with_data('PUT', @_); }
Packit a09cf7
Packit a09cf7
sub request_type_with_data
Packit a09cf7
{
Packit a09cf7
    my $type = shift;
Packit a09cf7
    my $url  = shift;
Packit a09cf7
    my $req = HTTP::Request->new($type => $url);
Packit a09cf7
    my $content;
Packit a09cf7
    $content = shift if @_ and ref $_[0];
Packit a09cf7
    my($k, $v);
Packit a09cf7
    while (($k,$v) = splice(@_, 0, 2)) {
Packit a09cf7
	if (lc($k) eq 'content') {
Packit a09cf7
	    $content = $v;
Packit a09cf7
	}
Packit a09cf7
	else {
Packit a09cf7
	    $req->push_header($k, $v);
Packit a09cf7
	}
Packit a09cf7
    }
Packit a09cf7
    my $ct = $req->header('Content-Type');
Packit a09cf7
    unless ($ct) {
Packit a09cf7
	$ct = 'application/x-www-form-urlencoded';
Packit a09cf7
    }
Packit a09cf7
    elsif ($ct eq 'form-data') {
Packit a09cf7
	$ct = 'multipart/form-data';
Packit a09cf7
    }
Packit a09cf7
Packit a09cf7
    if (ref $content) {
Packit a09cf7
	if ($ct =~ m,^multipart/form-data\s*(;|$),i) {
Packit a09cf7
	    require HTTP::Headers::Util;
Packit a09cf7
	    my @v = HTTP::Headers::Util::split_header_words($ct);
Packit a09cf7
	    Carp::carp("Multiple Content-Type headers") if @v > 1;
Packit a09cf7
	    @v = @{$v[0]};
Packit a09cf7
Packit a09cf7
	    my $boundary;
Packit a09cf7
	    my $boundary_index;
Packit a09cf7
	    for (my @tmp = @v; @tmp;) {
Packit a09cf7
		my($k, $v) = splice(@tmp, 0, 2);
Packit a09cf7
		if ($k eq "boundary") {
Packit a09cf7
		    $boundary = $v;
Packit a09cf7
		    $boundary_index = @v - @tmp - 1;
Packit a09cf7
		    last;
Packit a09cf7
		}
Packit a09cf7
	    }
Packit a09cf7
Packit a09cf7
	    ($content, $boundary) = form_data($content, $boundary, $req);
Packit a09cf7
Packit a09cf7
	    if ($boundary_index) {
Packit a09cf7
		$v[$boundary_index] = $boundary;
Packit a09cf7
	    }
Packit a09cf7
	    else {
Packit a09cf7
		push(@v, boundary => $boundary);
Packit a09cf7
	    }
Packit a09cf7
Packit a09cf7
	    $ct = HTTP::Headers::Util::join_header_words(@v);
Packit a09cf7
	}
Packit a09cf7
	else {
Packit a09cf7
	    # We use a temporary URI object to format
Packit a09cf7
	    # the application/x-www-form-urlencoded content.
Packit a09cf7
	    require URI;
Packit a09cf7
	    my $url = URI->new('http:');
Packit a09cf7
	    $url->query_form(ref($content) eq "HASH" ? %$content : @$content);
Packit a09cf7
	    $content = $url->query;
Packit a09cf7
Packit a09cf7
	    # HTML/4.01 says that line breaks are represented as "CR LF" pairs (i.e., `%0D%0A')
Packit a09cf7
	    $content =~ s/(?
Packit a09cf7
	}
Packit a09cf7
    }
Packit a09cf7
Packit a09cf7
    $req->header('Content-Type' => $ct);  # might be redundant
Packit a09cf7
    if (defined($content)) {
Packit a09cf7
	$req->header('Content-Length' =>
Packit a09cf7
		     length($content)) unless ref($content);
Packit a09cf7
	$req->content($content);
Packit a09cf7
    }
Packit a09cf7
    else {
Packit a09cf7
        $req->header('Content-Length' => 0);
Packit a09cf7
    }
Packit a09cf7
    $req;
Packit a09cf7
}
Packit a09cf7
Packit a09cf7
Packit a09cf7
sub _simple_req
Packit a09cf7
{
Packit a09cf7
    my($method, $url) = splice(@_, 0, 2);
Packit a09cf7
    my $req = HTTP::Request->new($method => $url);
Packit a09cf7
    my($k, $v);
Packit a09cf7
    my $content;
Packit a09cf7
    while (($k,$v) = splice(@_, 0, 2)) {
Packit a09cf7
	if (lc($k) eq 'content') {
Packit a09cf7
	    $req->add_content($v);
Packit a09cf7
            $content++;
Packit a09cf7
	}
Packit a09cf7
	else {
Packit a09cf7
	    $req->push_header($k, $v);
Packit a09cf7
	}
Packit a09cf7
    }
Packit a09cf7
    if ($content && !defined($req->header("Content-Length"))) {
Packit a09cf7
        $req->header("Content-Length", length(${$req->content_ref}));
Packit a09cf7
    }
Packit a09cf7
    $req;
Packit a09cf7
}
Packit a09cf7
Packit a09cf7
Packit a09cf7
sub form_data   # RFC1867
Packit a09cf7
{
Packit a09cf7
    my($data, $boundary, $req) = @_;
Packit a09cf7
    my @data = ref($data) eq "HASH" ? %$data : @$data;  # copy
Packit a09cf7
    my $fhparts;
Packit a09cf7
    my @parts;
Packit a09cf7
    while (my ($k,$v) = splice(@data, 0, 2)) {
Packit a09cf7
	if (!ref($v)) {
Packit a09cf7
	    $k =~ s/([\\\"])/\\$1/g;  # escape quotes and backslashes
Packit a09cf7
            no warnings 'uninitialized';
Packit a09cf7
	    push(@parts,
Packit a09cf7
		 qq(Content-Disposition: form-data; name="$k"$CRLF$CRLF$v));
Packit a09cf7
	}
Packit a09cf7
	else {
Packit a09cf7
	    my($file, $usename, @headers) = @$v;
Packit a09cf7
	    unless (defined $usename) {
Packit a09cf7
		$usename = $file;
Packit a09cf7
		$usename =~ s,.*/,, if defined($usename);
Packit a09cf7
	    }
Packit a09cf7
            $k =~ s/([\\\"])/\\$1/g;
Packit a09cf7
	    my $disp = qq(form-data; name="$k");
Packit a09cf7
            if (defined($usename) and length($usename)) {
Packit a09cf7
                $usename =~ s/([\\\"])/\\$1/g;
Packit a09cf7
                $disp .= qq(; filename="$usename");
Packit a09cf7
            }
Packit a09cf7
	    my $content = "";
Packit a09cf7
	    my $h = HTTP::Headers->new(@headers);
Packit a09cf7
	    if ($file) {
Packit a09cf7
		open(my $fh, "<", $file) or Carp::croak("Can't open file $file: $!");
Packit a09cf7
		binmode($fh);
Packit a09cf7
		if ($DYNAMIC_FILE_UPLOAD) {
Packit a09cf7
		    # will read file later, close it now in order to
Packit a09cf7
                    # not accumulate to many open file handles
Packit a09cf7
                    close($fh);
Packit a09cf7
		    $content = \$file;
Packit a09cf7
		}
Packit a09cf7
		else {
Packit a09cf7
		    local($/) = undef; # slurp files
Packit a09cf7
		    $content = <$fh>;
Packit a09cf7
		    close($fh);
Packit a09cf7
		}
Packit a09cf7
		unless ($h->header("Content-Type")) {
Packit a09cf7
		    require LWP::MediaTypes;
Packit a09cf7
		    LWP::MediaTypes::guess_media_type($file, $h);
Packit a09cf7
		}
Packit a09cf7
	    }
Packit a09cf7
	    if ($h->header("Content-Disposition")) {
Packit a09cf7
		# just to get it sorted first
Packit a09cf7
		$disp = $h->header("Content-Disposition");
Packit a09cf7
		$h->remove_header("Content-Disposition");
Packit a09cf7
	    }
Packit a09cf7
	    if ($h->header("Content")) {
Packit a09cf7
		$content = $h->header("Content");
Packit a09cf7
		$h->remove_header("Content");
Packit a09cf7
	    }
Packit a09cf7
	    my $head = join($CRLF, "Content-Disposition: $disp",
Packit a09cf7
			           $h->as_string($CRLF),
Packit a09cf7
			           "");
Packit a09cf7
	    if (ref $content) {
Packit a09cf7
		push(@parts, [$head, $$content]);
Packit a09cf7
		$fhparts++;
Packit a09cf7
	    }
Packit a09cf7
	    else {
Packit a09cf7
		push(@parts, $head . $content);
Packit a09cf7
	    }
Packit a09cf7
	}
Packit a09cf7
    }
Packit a09cf7
    return ("", "none") unless @parts;
Packit a09cf7
Packit a09cf7
    my $content;
Packit a09cf7
    if ($fhparts) {
Packit a09cf7
	$boundary = boundary(10) # hopefully enough randomness
Packit a09cf7
	    unless $boundary;
Packit a09cf7
Packit a09cf7
	# add the boundaries to the @parts array
Packit a09cf7
	for (1..@parts-1) {
Packit a09cf7
	    splice(@parts, $_*2-1, 0, "$CRLF--$boundary$CRLF");
Packit a09cf7
	}
Packit a09cf7
	unshift(@parts, "--$boundary$CRLF");
Packit a09cf7
	push(@parts, "$CRLF--$boundary--$CRLF");
Packit a09cf7
Packit a09cf7
	# See if we can generate Content-Length header
Packit a09cf7
	my $length = 0;
Packit a09cf7
	for (@parts) {
Packit a09cf7
	    if (ref $_) {
Packit a09cf7
	 	my ($head, $f) = @$_;
Packit a09cf7
		my $file_size;
Packit a09cf7
		unless ( -f $f && ($file_size = -s _) ) {
Packit a09cf7
		    # The file is either a dynamic file like /dev/audio
Packit a09cf7
		    # or perhaps a file in the /proc file system where
Packit a09cf7
		    # stat may return a 0 size even though reading it
Packit a09cf7
		    # will produce data.  So we cannot make
Packit a09cf7
		    # a Content-Length header.
Packit a09cf7
		    undef $length;
Packit a09cf7
		    last;
Packit a09cf7
		}
Packit a09cf7
	    	$length += $file_size + length $head;
Packit a09cf7
	    }
Packit a09cf7
	    else {
Packit a09cf7
		$length += length;
Packit a09cf7
	    }
Packit a09cf7
        }
Packit a09cf7
        $length && $req->header('Content-Length' => $length);
Packit a09cf7
Packit a09cf7
	# set up a closure that will return content piecemeal
Packit a09cf7
	$content = sub {
Packit a09cf7
	    for (;;) {
Packit a09cf7
		unless (@parts) {
Packit a09cf7
		    defined $length && $length != 0 &&
Packit a09cf7
		    	Carp::croak "length of data sent did not match calculated Content-Length header.  Probably because uploaded file changed in size during transfer.";
Packit a09cf7
		    return;
Packit a09cf7
		}
Packit a09cf7
		my $p = shift @parts;
Packit a09cf7
		unless (ref $p) {
Packit a09cf7
		    $p .= shift @parts while @parts && !ref($parts[0]);
Packit a09cf7
		    defined $length && ($length -= length $p);
Packit a09cf7
		    return $p;
Packit a09cf7
		}
Packit a09cf7
		my($buf, $fh) = @$p;
Packit a09cf7
                unless (ref($fh)) {
Packit a09cf7
                    my $file = $fh;
Packit a09cf7
                    undef($fh);
Packit a09cf7
                    open($fh, "<", $file) || Carp::croak("Can't open file $file: $!");
Packit a09cf7
                    binmode($fh);
Packit a09cf7
                }
Packit a09cf7
		my $buflength = length $buf;
Packit a09cf7
		my $n = read($fh, $buf, 2048, $buflength);
Packit a09cf7
		if ($n) {
Packit a09cf7
		    $buflength += $n;
Packit a09cf7
		    unshift(@parts, ["", $fh]);
Packit a09cf7
		}
Packit a09cf7
		else {
Packit a09cf7
		    close($fh);
Packit a09cf7
		}
Packit a09cf7
		if ($buflength) {
Packit a09cf7
		    defined $length && ($length -= $buflength);
Packit a09cf7
		    return $buf
Packit a09cf7
	    	}
Packit a09cf7
	    }
Packit a09cf7
	};
Packit a09cf7
Packit a09cf7
    }
Packit a09cf7
    else {
Packit a09cf7
	$boundary = boundary() unless $boundary;
Packit a09cf7
Packit a09cf7
	my $bno = 0;
Packit a09cf7
      CHECK_BOUNDARY:
Packit a09cf7
	{
Packit a09cf7
	    for (@parts) {
Packit a09cf7
		if (index($_, $boundary) >= 0) {
Packit a09cf7
		    # must have a better boundary
Packit a09cf7
		    $boundary = boundary(++$bno);
Packit a09cf7
		    redo CHECK_BOUNDARY;
Packit a09cf7
		}
Packit a09cf7
	    }
Packit a09cf7
	    last;
Packit a09cf7
	}
Packit a09cf7
	$content = "--$boundary$CRLF" .
Packit a09cf7
	           join("$CRLF--$boundary$CRLF", @parts) .
Packit a09cf7
		   "$CRLF--$boundary--$CRLF";
Packit a09cf7
    }
Packit a09cf7
Packit a09cf7
    wantarray ? ($content, $boundary) : $content;
Packit a09cf7
}
Packit a09cf7
Packit a09cf7
Packit a09cf7
sub boundary
Packit a09cf7
{
Packit a09cf7
    my $size = shift || return "xYzZY";
Packit a09cf7
    require MIME::Base64;
Packit a09cf7
    my $b = MIME::Base64::encode(join("", map chr(rand(256)), 1..$size*3), "");
Packit a09cf7
    $b =~ s/[\W]/X/g;  # ensure alnum only
Packit a09cf7
    $b;
Packit a09cf7
}
Packit a09cf7
Packit a09cf7
1;
Packit a09cf7
Packit a09cf7
=pod
Packit a09cf7
Packit a09cf7
=encoding UTF-8
Packit a09cf7
Packit a09cf7
=head1 NAME
Packit a09cf7
Packit a09cf7
HTTP::Request::Common - Construct common HTTP::Request objects
Packit a09cf7
Packit a09cf7
=head1 VERSION
Packit a09cf7
Packit a09cf7
version 6.18
Packit a09cf7
Packit a09cf7
=head1 SYNOPSIS
Packit a09cf7
Packit a09cf7
  use HTTP::Request::Common;
Packit a09cf7
  $ua = LWP::UserAgent->new;
Packit a09cf7
  $ua->request(GET 'http://www.sn.no/');
Packit a09cf7
  $ua->request(POST 'http://somewhere/foo', [foo => bar, bar => foo]);
Packit a09cf7
  $ua->request(PATCH 'http://somewhere/foo', [foo => bar, bar => foo]);
Packit a09cf7
  $ua->request(PUT 'http://somewhere/foo', [foo => bar, bar => foo]);
Packit a09cf7
Packit a09cf7
=head1 DESCRIPTION
Packit a09cf7
Packit a09cf7
This module provides functions that return newly created C<HTTP::Request>
Packit a09cf7
objects.  These functions are usually more convenient to use than the
Packit a09cf7
standard C<HTTP::Request> constructor for the most common requests.
Packit a09cf7
Packit a09cf7
Note that L<LWP::UserAgent> has several convenience methods, including
Packit a09cf7
C<get>, C<head>, C<delete>, C<post> and C<put>.
Packit a09cf7
Packit a09cf7
The following functions are provided:
Packit a09cf7
Packit a09cf7
=over 4
Packit a09cf7
Packit a09cf7
=item GET $url
Packit a09cf7
Packit a09cf7
=item GET $url, Header => Value,...
Packit a09cf7
Packit a09cf7
The C<GET> function returns an L<HTTP::Request> object initialized with
Packit a09cf7
the "GET" method and the specified URL.  It is roughly equivalent to the
Packit a09cf7
following call
Packit a09cf7
Packit a09cf7
  HTTP::Request->new(
Packit a09cf7
     GET => $url,
Packit a09cf7
     HTTP::Headers->new(Header => Value,...),
Packit a09cf7
  )
Packit a09cf7
Packit a09cf7
but is less cluttered.  What is different is that a header named
Packit a09cf7
C<Content> will initialize the content part of the request instead of
Packit a09cf7
setting a header field.  Note that GET requests should normally not
Packit a09cf7
have a content, so this hack makes more sense for the C<PUT>, C<PATCH>
Packit a09cf7
 and C<POST> functions described below.
Packit a09cf7
Packit a09cf7
The C<get(...)> method of L<LWP::UserAgent> exists as a shortcut for
Packit a09cf7
C<< $ua->request(GET ...) >>.
Packit a09cf7
Packit a09cf7
=item HEAD $url
Packit a09cf7
Packit a09cf7
=item HEAD $url, Header => Value,...
Packit a09cf7
Packit a09cf7
Like GET() but the method in the request is "HEAD".
Packit a09cf7
Packit a09cf7
The C<head(...)>  method of L<LWP::UserAgent> exists as a shortcut for
Packit a09cf7
C<< $ua->request(HEAD ...) >>.
Packit a09cf7
Packit a09cf7
=item DELETE $url
Packit a09cf7
Packit a09cf7
=item DELETE $url, Header => Value,...
Packit a09cf7
Packit a09cf7
Like C<GET> but the method in the request is C<DELETE>.  This function
Packit a09cf7
is not exported by default.
Packit a09cf7
Packit a09cf7
=item PATCH $url
Packit a09cf7
Packit a09cf7
=item PATCH $url, Header => Value,...
Packit a09cf7
Packit a09cf7
=item PATCH $url, $form_ref, Header => Value,...
Packit a09cf7
Packit a09cf7
=item PATCH $url, Header => Value,..., Content => $form_ref
Packit a09cf7
Packit a09cf7
=item PATCH $url, Header => Value,..., Content => $content
Packit a09cf7
Packit a09cf7
The same as C<POST> below, but the method in the request is C<PATCH>.
Packit a09cf7
Packit a09cf7
=item PUT $url
Packit a09cf7
Packit a09cf7
=item PUT $url, Header => Value,...
Packit a09cf7
Packit a09cf7
=item PUT $url, $form_ref, Header => Value,...
Packit a09cf7
Packit a09cf7
=item PUT $url, Header => Value,..., Content => $form_ref
Packit a09cf7
Packit a09cf7
=item PUT $url, Header => Value,..., Content => $content
Packit a09cf7
Packit a09cf7
The same as C<POST> below, but the method in the request is C<PUT>
Packit a09cf7
Packit a09cf7
=item POST $url
Packit a09cf7
Packit a09cf7
=item POST $url, Header => Value,...
Packit a09cf7
Packit a09cf7
=item POST $url, $form_ref, Header => Value,...
Packit a09cf7
Packit a09cf7
=item POST $url, Header => Value,..., Content => $form_ref
Packit a09cf7
Packit a09cf7
=item POST $url, Header => Value,..., Content => $content
Packit a09cf7
Packit a09cf7
C<POST>, C<PATCH> and C<PUT> all work with the same parameters.
Packit a09cf7
Packit a09cf7
  %data = ( title => 'something', body => something else' );
Packit a09cf7
  $ua = LWP::UserAgent->new();
Packit a09cf7
  $request = HTTP::Request::Common::POST( $url, [ %data ] );
Packit a09cf7
  $response = $ua->request($request);
Packit a09cf7
Packit a09cf7
They take a second optional array or hash reference
Packit a09cf7
parameter C<$form_ref>.  The content can also be specified
Packit a09cf7
directly using the C<Content> pseudo-header, and you may also provide
Packit a09cf7
the C<$form_ref> this way.
Packit a09cf7
Packit a09cf7
The C<Content> pseudo-header steals a bit of the header field namespace as
Packit a09cf7
there is no way to directly specify a header that is actually called
Packit a09cf7
"Content".  If you really need this you must update the request
Packit a09cf7
returned in a separate statement.
Packit a09cf7
Packit a09cf7
The C<$form_ref> argument can be used to pass key/value pairs for the
Packit a09cf7
form content.  By default we will initialize a request using the
Packit a09cf7
C<application/x-www-form-urlencoded> content type.  This means that
Packit a09cf7
you can emulate an HTML E<lt>form> POSTing like this:
Packit a09cf7
Packit a09cf7
  POST 'http://www.perl.org/survey.cgi',
Packit a09cf7
       [ name   => 'Gisle Aas',
Packit a09cf7
         email  => 'gisle@aas.no',
Packit a09cf7
         gender => 'M',
Packit a09cf7
         born   => '1964',
Packit a09cf7
         perc   => '3%',
Packit a09cf7
       ];
Packit a09cf7
Packit a09cf7
This will create an L<HTTP::Request> object that looks like this:
Packit a09cf7
Packit a09cf7
  POST http://www.perl.org/survey.cgi
Packit a09cf7
  Content-Length: 66
Packit a09cf7
  Content-Type: application/x-www-form-urlencoded
Packit a09cf7
Packit a09cf7
  name=Gisle%20Aas&email=gisle%40aas.no&gender=M&born=1964&perc=3%25
Packit a09cf7
Packit a09cf7
Multivalued form fields can be specified by either repeating the field
Packit a09cf7
name or by passing the value as an array reference.
Packit a09cf7
Packit a09cf7
The POST method also supports the C<multipart/form-data> content used
Packit a09cf7
for I<Form-based File Upload> as specified in RFC 1867.  You trigger
Packit a09cf7
this content format by specifying a content type of C<'form-data'> as
Packit a09cf7
one of the request headers.  If one of the values in the C<$form_ref> is
Packit a09cf7
an array reference, then it is treated as a file part specification
Packit a09cf7
with the following interpretation:
Packit a09cf7
Packit a09cf7
  [ $file, $filename, Header => Value... ]
Packit a09cf7
  [ undef, $filename, Header => Value,..., Content => $content ]
Packit a09cf7
Packit a09cf7
The first value in the array ($file) is the name of a file to open.
Packit a09cf7
This file will be read and its content placed in the request.  The
Packit a09cf7
routine will croak if the file can't be opened.  Use an C<undef> as
Packit a09cf7
$file value if you want to specify the content directly with a
Packit a09cf7
C<Content> header.  The $filename is the filename to report in the
Packit a09cf7
request.  If this value is undefined, then the basename of the $file
Packit a09cf7
will be used.  You can specify an empty string as $filename if you
Packit a09cf7
want to suppress sending the filename when you provide a $file value.
Packit a09cf7
Packit a09cf7
If a $file is provided by no C<Content-Type> header, then C<Content-Type>
Packit a09cf7
and C<Content-Encoding> will be filled in automatically with the values
Packit a09cf7
returned by C<LWP::MediaTypes::guess_media_type()>
Packit a09cf7
Packit a09cf7
Sending my F<~/.profile> to the survey used as example above can be
Packit a09cf7
achieved by this:
Packit a09cf7
Packit a09cf7
  POST 'http://www.perl.org/survey.cgi',
Packit a09cf7
       Content_Type => 'form-data',
Packit a09cf7
       Content      => [ name  => 'Gisle Aas',
Packit a09cf7
                         email => 'gisle@aas.no',
Packit a09cf7
                         gender => 'M',
Packit a09cf7
                         born   => '1964',
Packit a09cf7
                         init   => ["$ENV{HOME}/.profile"],
Packit a09cf7
                       ]
Packit a09cf7
Packit a09cf7
This will create an L<HTTP::Request> object that almost looks this (the
Packit a09cf7
boundary and the content of your F<~/.profile> is likely to be
Packit a09cf7
different):
Packit a09cf7
Packit a09cf7
  POST http://www.perl.org/survey.cgi
Packit a09cf7
  Content-Length: 388
Packit a09cf7
  Content-Type: multipart/form-data; boundary="6G+f"
Packit a09cf7
Packit a09cf7
  --6G+f
Packit a09cf7
  Content-Disposition: form-data; name="name"
Packit a09cf7
Packit a09cf7
  Gisle Aas
Packit a09cf7
  --6G+f
Packit a09cf7
  Content-Disposition: form-data; name="email"
Packit a09cf7
Packit a09cf7
  gisle@aas.no
Packit a09cf7
  --6G+f
Packit a09cf7
  Content-Disposition: form-data; name="gender"
Packit a09cf7
Packit a09cf7
  M
Packit a09cf7
  --6G+f
Packit a09cf7
  Content-Disposition: form-data; name="born"
Packit a09cf7
Packit a09cf7
  1964
Packit a09cf7
  --6G+f
Packit a09cf7
  Content-Disposition: form-data; name="init"; filename=".profile"
Packit a09cf7
  Content-Type: text/plain
Packit a09cf7
Packit a09cf7
  PATH=/local/perl/bin:$PATH
Packit a09cf7
  export PATH
Packit a09cf7
Packit a09cf7
  --6G+f--
Packit a09cf7
Packit a09cf7
If you set the C<$DYNAMIC_FILE_UPLOAD> variable (exportable) to some TRUE
Packit a09cf7
value, then you get back a request object with a subroutine closure as
Packit a09cf7
the content attribute.  This subroutine will read the content of any
Packit a09cf7
files on demand and return it in suitable chunks.  This allow you to
Packit a09cf7
upload arbitrary big files without using lots of memory.  You can even
Packit a09cf7
upload infinite files like F</dev/audio> if you wish; however, if
Packit a09cf7
the file is not a plain file, there will be no C<Content-Length> header
Packit a09cf7
defined for the request.  Not all servers (or server
Packit a09cf7
applications) like this.  Also, if the file(s) change in size between
Packit a09cf7
the time the C<Content-Length> is calculated and the time that the last
Packit a09cf7
chunk is delivered, the subroutine will C<Croak>.
Packit a09cf7
Packit a09cf7
The C<post(...)>  method of L<LWP::UserAgent> exists as a shortcut for
Packit a09cf7
C<< $ua->request(POST ...) >>.
Packit a09cf7
Packit a09cf7
=back
Packit a09cf7
Packit a09cf7
=head1 SEE ALSO
Packit a09cf7
Packit a09cf7
L<HTTP::Request>, L<LWP::UserAgent>
Packit a09cf7
Packit a09cf7
Also, there are some examples in L<HTTP::Request/"EXAMPLES"> that you might
Packit a09cf7
find useful. For example, batch requests are explained there.
Packit a09cf7
Packit a09cf7
=head1 AUTHOR
Packit a09cf7
Packit a09cf7
Gisle Aas <gisle@activestate.com>
Packit a09cf7
Packit a09cf7
=head1 COPYRIGHT AND LICENSE
Packit a09cf7
Packit a09cf7
This software is copyright (c) 1994-2017 by Gisle Aas.
Packit a09cf7
Packit a09cf7
This is free software; you can redistribute it and/or modify it under
Packit a09cf7
the same terms as the Perl 5 programming language system itself.
Packit a09cf7
Packit a09cf7
=cut
Packit a09cf7
Packit a09cf7
__END__
Packit a09cf7
Packit a09cf7
Packit a09cf7
#ABSTRACT: Construct common HTTP::Request objects