NAME
HTTP::Promise::Body::Form - x-www-form-urlencoded Data Class
SYNOPSIS
use HTTP::Promise::Body::Form;
my $form = HTTP::Promise::Body::Form->new;
my $form = HTTP::Promise::Body::Form->new( $hash_ref );
my $form = HTTP::Promise::Body::Form->new( q{e%3Dmc2} );
die( HTTP::Promise::Body::Form->error, "\n" ) if( !defined( $form ) );
VERSION
v0.2.4
DESCRIPTION
This class represents x-www-form-urlencoded
HTTP body. It inherits from Module::Generic::Hash
This is different from a multipart/form-data
. For this, please check the module HTTP::Promise::Body::Form::Data
CONSTRUCTOR
new
This takes an optional data, and some options and returns a new HTTP::Promise::Body::Form object.
Acceptable data are:
If a string is provided, it will be automatically decoded into an hash of name-value pairs. When a name is found more than once, its values are added as an array reference.
my $form = HTTP::Promise::Body->new( 'name=John+Doe&foo=bar&foo=baz&foo=' );
Would result in a HTTP::Promise::Body::Form
object containing:
name => 'John Doe', foo => ['bar', 'baz', '']
As an historical note, x-www-form-urlencoded
is not an rfc-defined standard, and differs from URI encoding defined by rfc3986 in that it uses +
to represent whitespace. It was defined back then by Mosaic as a non-standard way of encoding form data. This also this historical note and this Stackoverflow discussion.
METHODS
HTTP::Promise::Body::Form inherits all the methods from Module::Generic::Hash, and adds or override the following ones.
as_form_data
This returns a new HTTP::Promise::Body::Form::Data object based on the current data, or upon error, sets an error and returns undef
.
as_string
This returns a properly urlencoded representation of the name-value pairs stored in this hash object.
Each value will be encoded into utf8 before being urlencoded. This is all done fast with URL::Encode::XS
decode
Provided with an x-www-form-urlencoded
string and this will return a decoded string taking under account utf8 characters.
my $params = $form->decode( 'tengu=%E5%A4%A9%E7%8B%97' );
# [ 'tengu', '天狗' ]
If an error occurs, this will set an error object and return undef
decode_string
Provided with an url-encoded string, included utf-8 string, and this returns its corresponding decoded version.
my $deity = $form->decode( '%E5%A4%A9%E7%8B%97' );
results in: 天狗
decode_to_array
Takes an x-www-form-urlencoded
string and returns an array reference of name-value pairs. If a name is seen more than once, its value will be an array reference.
If an error occurs, this will set an error object and return undef
decode_to_hash
Takes an x-www-form-urlencoded
string or an array reference of name-value pairs and returns an hash reference of name-value pairs.
If a name is seen more than once, its value will be an array reference.
If an error occurs, this will set an error object and return undef
encode
Takes an array reference or an hash reference and this returns a properly url-encoded string representation.
If an error occurs, this will set an error object and return undef
encode_string
Takes a string and returns an encoded string. UTF-8 strings are ok too as long as they are in perl's internal representation.
If an error occurs, this will set an error object and return undef
length
Returns the number of keys currently set in this key-value pairs held in the object.
open
This encodes the key-pairs as x-www-form-urlencoded
by calling "as_string", which returns a new scalar object, opens it, passing whatever arguments it received to "open" in Module::Generic::Scalar and return the resulting object upon success, or upon error, sets an error and returns undef
Provided with a valid filehandle, and this print the x-www-form-urlencoded
representation of the key-value pairs contained in this object, to the given filehandle, or upon error, sets an error and returns undef
THREAD-SAFETY
HTTP::Promise::Body::Form::Data is thread-safe for per-object operations, with proper handling of per-object state and external libraries. It supports multi-threaded environments, but since it inherits from Module::Generic::Hash, who is also thread-safe, but still care must be taken when sharing objects across threads or modifying global variables.
Key considerations for thread-safety:
Shared Variables
The global variable
$KEY_OBJECT
controls whether references can be used as hash keys. It is not shared by default, so concurrent modifications in threads may cause race conditions. Uselocal
or the "key_object" method to set it per-object:use threads; my $h = HTTP::Promise::Body::Form::Data->new; $h->key_object(1); # Thread-safe per object my $ref = []; $h->{ $ref } = "array"; # Safe
Hash Data
Hash data is stored in a tied hash (Module::Generic::TieHash), which is per-object and thread-safe for independent operations. Operations like "merge", "json", and "clone" operate on local data. However, concurrent modifications to a shared object are not thread-safe without synchronisation:
use threads; my $h = HTTP::Promise::Body::Form::Data->new( first_name => "John" ); lock( $h ); # Synchronize access my @threads = map { threads->create(sub { lock( $h ); $h->merge({ last_name => "Doe" }); # Thread-safe with lock }); } 1..5; $_->join for( @threads );
For best practices, create per-thread objects to avoid shared state:
use threads; my @threads = map { threads->create(sub { my $h = HTTP::Promise::Body::Form::Data->new( first_name => "John" ); $h->merge({ last_name => "Doe" }); # Thread-safe }); } 1..5; $_->join for @threads;
Serialisation
Serialisation methods ("FREEZE", "THAW") operate on per-object state, making them thread-safe:
use threads; use Storable; my $h = HTTP::Promise::Body::Form::Data->new( age => 30 ); my $frozen = Storable::freeze( $h ); # Thread-safe
For debugging in threaded environments:
ls -l /proc/$$/fd # List open file descriptors
AUTHOR
Jacques Deguest <jack@deguest.jp>
SEE ALSO
rfc7578 on multipart/form-data
HTTP::Promise, HTTP::Promise::Request, HTTP::Promise::Response, HTTP::Promise::Message, HTTP::Promise::Entity, HTTP::Promise::Headers, HTTP::Promise::Body, HTTP::Promise::Body::Form, HTTP::Promise::Body::Form::Data, HTTP::Promise::Body::Form::Field, HTTP::Promise::Status, HTTP::Promise::MIME, HTTP::Promise::Parser, HTTP::Promise::IO, HTTP::Promise::Stream, HTTP::Promise::Exception
COPYRIGHT & LICENSE
Copyright(c) 2022 DEGUEST Pte. Ltd.
All rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.