HTTP-Promise

 view release on metacpan or  search on metacpan

lib/HTTP/Promise/Body/Form/Data.pm  view on Meta::CPAN

=head1 DESCRIPTION

This class represents a C<form-data> content as key-value pairs and is designed to make construction and manipulation of C<multipart/form-data> easier. It inherits from L<HTTP::Promise::Body::Form>

For C<x-www-form-urlencoded>, use L<HTTP::Promise::Body::Form> instead.

Each key represents a C<form-data> field and its value can either be a simple string or a C<HTTP::Promise::Body::Form::Field> object.

C<multipart/form-data> is the only valid Content-Type for sending multiple data. L<rfc7578 in section 4.3|https://tools.ietf.org/html/rfc7578#section-4.3> states: "[RFC2388] suggested that multiple files for a single form field be transmitted using a...

See also this L<Stackoverflow discussion|https://stackoverflow.com/questions/36674161/http-multipart-form-data-multiple-files-in-one-input/41204533#41204533> and L<this one too|https://stackoverflow.com/questions/51575746/http-header-content-type-mul...

=head1 CONSTRUCTOR

=head2 new

This takes an optional data, and some options and returns a new L<HTTP::Promise::Body::Form> object.

Acceptable data are:

=over 4

lib/HTTP/Promise/Entity.pm  view on Meta::CPAN

=head2 make_boundary

Returns a uniquely generated multipart boundary created using L<Data::UUID>

=head2 make_multipart

This transforms the current entity into the first part of a <multipart/form-data> HTTP message.

For HTTP request, C<multipart/form-data> is the only valid C<Content-Type> for sending multiple data. L<rfc7578 in section 4.3|https://tools.ietf.org/html/rfc7578#section-4.3> states: "[RFC2388] suggested that multiple files for a single form field b...

See also this L<Stackoverflow discussion|https://stackoverflow.com/questions/36674161/http-multipart-form-data-multiple-files-in-one-input/41204533#41204533> and L<this one too|https://stackoverflow.com/questions/51575746/http-header-content-type-mul...

Of course, technically, nothing prevents an HTTP message (request or response) from being a C<multipart/mixed> or something else.

This method takes a multipart subtype, such as C<form-data>, or C<mixed>, etc and creates a multipart entity of which this current entity will become the first part. If no multipart subtype is specified, this defaults to C<form-data>.

It takes also an optional hash or hash reference of parameters.

Valid parameters are:

=over 4

lib/HTTP/Promise/Headers.pm  view on Meta::CPAN

# NOTE: proxy_authorization_basic() is inherited

# NOTE: push_header() is inherited

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range>
sub range { return( shift->_set_get_multi( 'Range', @_ ) ); }

sub recommended_filename
{
    my $self = shift( @_ );
    foreach my $attr_name ( qw( content-disposition.filename* content-disposition.filename content-type.name ) )
    {
        my $value = $self->mime_attr( $attr_name );
        if( defined( $value ) && 
            $value ne '' &&
            $value =~ /\S/ )
        {
            return( $self->decode_filename( $value ) );
        }
    }
    return;

lib/HTTP/Promise/Headers/Generic.pm  view on Meta::CPAN

                {
                    # We'll return the caller's original value, not the lowercase one we use for comparison
                    $ok->push( $this->[$i] );
                }
            }
        }
    }
    return( $ok->unique );
}

# Works for language and content-type and content-encoding
sub _qv_match_wildcard
{
    my $self = shift( @_ );
    # $proposals contain the value offered in lower case, whereas $original contains
    # the original value and we return our value from there. Both $proposals and $original
    # are of the same size.
    my( $acceptable, $proposals, $original, $seen ) = @_;
    return( $self->error( "Bad arguments. Usage: \$h->_qv_match_wildcard( \$acceptable, \$proposals, \$original )" ) ) unless( @_ == 3 );
    return( $self->error( "This is not a wildcard acceptable value." ) ) if( $acceptable->index( '*' ) == -1 );
    return( $self->error( "Proposed values must be an array reference." ) ) unless( $self->_is_array( $proposals ) );

lib/HTTP/Promise/Message.pm  view on Meta::CPAN

This is the same thing as L</add_content>, except it will encode in utf-8 the data provided, i.e. not perl's internal representation.

=head2 add_part

By default, this will check if the HTTP message C<Content-Type> is a multipart one, and if not, it will automatically set it to C<multipart/form-data> and transform the current HTTP message into the first part of a C<multipart/form-data>, and add aft...

If the C<Content-Type> is already a multipart one, but has no part yet and has a body content, it will parse that content to build one or more parts from it.

When used for an HTTP request, C<multipart/form-data> is the only valid Content-Type for sending multiple data. L<rfc7578 in section 4.3|https://tools.ietf.org/html/rfc7578#section-4.3> states: "[RFC2388] suggested that multiple files for a single fo...

See also this L<Stackoverflow discussion|https://stackoverflow.com/questions/36674161/http-multipart-form-data-multiple-files-in-one-input/41204533#41204533> and L<this one too|https://stackoverflow.com/questions/51575746/http-header-content-type-mul...

When used for an HTTP response, one can return either a C<multipart/form-data> or a C<multipart-mixed> HTTP message.

If you want to make an HTTP request, then you need to provide pairs of form-name-and part object (either a L<HTTP::Promise::Entity> or a L<HTTP::Promise::Message> object with an L<HTTP::Promise::Entity> set with L</entity>) OR a list of parts whose L...

If you want to make an HTTP response, you can either return a C<multipart/form-data> by providing pairs of form-name-and part object as mentioned above, or a C<multipart/mixed> by providing a list of part object (either a L<HTTP::Promise::Entity> or ...

For example:

    $m->add_part(

lib/HTTP/Promise/Parser.pm  view on Meta::CPAN

        return( $self->error({ code => 425, message => 'Incomplete request, call again when there is more data.', class => $EXCEPTION_CLASS }) );
    }
    # response headers:
    # {
    #   "_content_length" => 15,
    #   "_keepalive"      => 0,
    #   "_message"        => "OK",
    #   "_protocol"       => "HTTP/1.0",
    #   "_status"         => 200,
    #   "content-length"  => [15],
    #   "content-type"    => ["text/plain"],
    #   "host"            => ["example.com"],
    #   "user-agent"      => ["hoge"],
    # }
    # request headers:
    # {
    #   "_content_length" => 27,
    #   "_keepalive"      => 1,
    #   "_method"         => "POST",
    #   "_protocol"       => "HTTP/1.1",
    #   "_query_string"   => "",
    #   "_request_uri"    => "/test",
    #   "_uri"            => "/test",
    #   "content-length"  => [27],
    #   "content-type"    => ["application/x-www-form-urlencoded"],
    #   "host"            => ["foo.example"],
    # }
    $r->{_protocol} = "HTTP/${bkp_version}" if( defined( $bkp_version ) );
    # warn( "HTTP::Parser2::XS->parse_headers_xs: bytes read ($len) differs from _content_length (", ( $r->{_content_length} // '' ), ")\n" ) if( defined( $r->{_content_length} ) && length( $r->{_content_length} ) && $len != $r->{_content_length} && ...
    my $def = { length => $len };
    # Sadly enough, HTTP::Parser2::XS does not provide the order of the header and
    # although we could find out ourself, it would defeat the purpose of using an XS module
    # so we default to alphabetical order
    # If this is really important, you can use parse_request method instead
    my $headers = $self->new_array;

lib/HTTP/Promise/Request.pm  view on Meta::CPAN

Obviously you should not use both and if you do, C<file> will take priority.

If this provided, the L<body object|HTTP::Promise::Body> will be a L<HTTP::Promise::Body::Scalar>

=back

=back

C<multipart/form-data> is the only valid Content-Type for sending multiple data. L<rfc7578 in section 4.3|https://tools.ietf.org/html/rfc7578#section-4.3> states: "[RFC2388] suggested that multiple files for a single form field be transmitted using a...

See also this L<Stackoverflow discussion|https://stackoverflow.com/questions/36674161/http-multipart-form-data-multiple-files-in-one-input/41204533#41204533> and L<this one too|https://stackoverflow.com/questions/51575746/http-header-content-type-mul...

See also L<HTTP::Promise::Body::Form::Data> for an alternate easy way to create and manipulate C<form-data>, and see also L<HTTP::Promise::Entity/as_form_data>, which will create and return a L<HTTP::Promise::Body::Form::Data> object.

=head2 method

Sets or gets the HTTP C<method>, such as C<CONNECT>, C<DELETE>, C<GET>, C<HEAD>, C<OPTIONS>, C<PATCH>, C<POST>, C<PUT>, C<TRACE> which are the standard ones as defined by L<rfc7231, section 4.1|https://tools.ietf.org/html/rfc7231#section-4.1>

Note that casing must be uppercase for standard methods, but non-standard ones can be whatever you want as long as it complies with the rfc7231.

This returns the current method set, if any, as an L<scalar object|Module::Generic::Scalar>

t/02.parser.t  view on Meta::CPAN

        'to'                            => 'sip:john.doe@somewhere.example.com ; tag = 1234567890n',
        'from'                          => '"Bob \\\\\"" <sip:bob@example.com> ; tag = 12abcd3',
        'max-forwards'                  => '0010',
        'call-id'                       => 'john.doe@192.0.1.2',
        'content-length'                => '150',
        'cseq'                          => '0009 INVITE',
        'via'                           => 'SIP / 2.0 /UDP 192.0.1.3;branch=123abcdef',
        's'                             => '',
        'newfangledheader'              => 'newfangled value continued newfangled value',
        'unknownheaderwithunusualvalue' => ';;,,;;,;',
        'content-type'                  => 'application/sdp',
        'route'                         => '<sip:services.example.com;lr;unknownwith=value;unknown-no-value>',
        'v'                             => 'SIP / 2.0 / TCP maybe.example.com ; branch = a1bC2dE3fgh4 , SIP / 2.0 / UDP 192.168.255.123 ; branch= a1bC2dE3fgh4',
        'm'                             => '"Quoted string \"\"" <sip:bob@example.com> ; newparam = newvalue ; secondparam ; q = 0.33',
    ), length => 764 };

    my $p = HTTP::Promise::Parser->new( debug => $DEBUG );
    my $headers = $p->parse_headers( \$message );
    is_deeply( $headers, $expected, "Parsed headers" );
};

t/10.entity_body.t  view on Meta::CPAN

subtest "build entity" => sub
{
    {
        local $SIG{__WARN__} = sub{ die( "caught warning: ", @_ ) };
        {   
             my $e = HTTP::Promise::Entity->build( path => "${testin_dir}/short.txt", debug => $DEBUG );
             diag( "Error instantiating HTTP::Promise::Entity object: ", HTTP::Promise::Entity->error ) if( $DEBUG && !defined( $e ) );
             my $name = 'short.txt';
             my $got;

             $got = $e->headers->mime_attr( 'content-type.name' );
             # diag( "Content-Type is '", $e->header( 'Content-Type' ), "' and content-type.name yielded '$got', double checking '", $e->headers->mime_attr( 'content-type.name' ), "'" ) if( $DEBUG );
             is( $got, $name, 'Path: with no Filename, got default content-type.name' );

             $got = $e->headers->mime_attr( 'content-disposition.filename' );
             is( $got, $name, 'Path: with no Filename, got default content-disposition.filename' );

             $got = $e->headers->recommended_filename;
             is( $got, $name, 'Path: with no Filename, got default recommended filename' );
        }
        { 
            my $e = HTTP::Promise::Entity->build(
                path => "${testin_dir}/short.txt",
                filename => undef,
                debug => $DEBUG
            );
            my $got = $e->headers->mime_attr( 'content-type.name' );
            ok( !$got, 'Path: with explicitly undef Filename, got no filename' );
            my $x = $e->as_string;
            my $desired = "Content-Type: text/plain${CRLF}${CRLF}" . <<EOT;
Dear «François Müller»,

As you requested, I have written the HTTP::Promise modules to support
the creation of HTTP multipart messages.

Jacques
EOT
            is( $x, $desired, 'Tested stringify' );
        }

        {
            my $e = HTTP::Promise::Entity->build(
                path => "${testin_dir}/short.txt",
                filename => 'foo.txt',
                debug => $DEBUG
            );
            my $got = $e->headers->mime_attr( 'content-type.name' );
            is( $got, "foo.txt", "Path: verified explicit 'Filename'" );
        }
        {
            my $e = HTTP::Promise::Entity->build( path => "${testin_dir}/mignonne-ronsard.txt" );
            my $got = $e->headers->mime_attr( 'content-type' );
            is( $got, 'text/plain', 'Type: default ok' );
        }
        {
            my $e = HTTP::Promise::Entity->build(
                path => "${testin_dir}/mignonne-ronsard.txt",
                type => 'text/foo'
            );
            my $got = $e->headers->mime_attr( 'content-type' );
            is( $got, 'text/foo', 'Type: explicit ok' );
        }
        {
            my $e = HTTP::Promise::Entity->build(
                path => "${testin_dir}/science-sans-conscience-rabelais.txt",
                encoding => 'suggest'
            );
            my $got = $e->headers->content_encoding;
            is( $got, undef, 'No encoding for small body' );
        }

t/10.entity_body.t  view on Meta::CPAN

                path => "${testin_dir}/tengu.png",
                encoding => 'suggest'
            );
            my $got = $e->headers->content_encoding;
            is( $got, undef, 'No encoding suggested for images' );
        }
        {
            my $e = HTTP::Promise::Entity->build(
                path => "${testin_dir}/short.txt"
            );
            my $got = $e->headers->mime_attr( 'content-type.charset' );
            ok( !$got, 'Charset: default ok' );
        }
        {
            my $e = HTTP::Promise::Entity->build(
                path => "${testin_dir}/short.txt",
                charset => 'utf-8'
            );
            my $got = $e->headers->mime_attr( 'content-type.charset' );
            is( $got, 'utf-8', 'Charset: explicit' );
        }

        {
            my $e = HTTP::Promise::Entity->build(
                type => 'message/http',
                encoding => 'base64',
                data => "GET / HTTP/1.0${CRLF}Host: wwww.example.org${CRLF}${CRLF}Foo\n"
            );
            my $encoding = $e->headers->content_encoding;

t/13.header_fields.t  view on Meta::CPAN

    is( $h->style_src, 'https://example.com/' );
    is( $h->style_src_attr, 'https://example.com/' );
    is( $h->style_src_elem, 'https://example.com/' );
    is( $h->trusted_types, 1 );
    is( $h->upgrade_insecure_requests, 1 );
    is( $h->worker_src, 'https://example.com/' );
    $h->block_all_mixed_content(0);
    is( $h->block_all_mixed_content, 0 );
};

subtest 'content-type' => sub
{
    use ok( 'HTTP::Promise::Headers::ContentType' );
    my $str = q{text/html; charset=UTF-8};
    my $h = HTTP::Promise::Headers::ContentType->new( $str );
    is( "$h", $str );
    is( $h->type, 'text/html' );
    is( $h->charset, 'UTF-8' );

    $str = q{application/octet-stream};
    $h = HTTP::Promise::Headers::ContentType->new( $str );



( run in 2.747 seconds using v1.01-cache-2.11-cpan-524268b4103 )