NAME
HTTP::Promise::Message - HTTP Message Class
SYNOPSIS
use HTTP::Promise::Message;
my $this = HTTP::Promise::Message->new(
[ 'Content-Type' => 'text/plain' ],
'Hello world'
) || die( HTTP::Promise::Message->error, "\n" );
VERSION
v0.3.0
DESCRIPTION
This class represents an HTTP message, and implements methods that are common to either a request or a response. This class is inherited by HTTP::Promise::Request and HTTP::Promise::Response. It difffers from HTTP::Promise::Entity in that HTTP::Promise::Entity represents en HTTP entity which is composed of headers and a body, and this can be embedded within another entity.
Here is how it fits in overall relation with other classes.
+-------------------------+ +--------------------------+
| | | |
| HTTP::Promise::Request | | HTTP::Promise::Response |
| | | |
+------------|------------+ +-------------|------------+
| |
| |
| |
| +------------------------+ |
| | | |
+--- HTTP::Promise::Message |---+
| |
+------------|-----------+
|
|
+------------|-----------+
| |
| HTTP::Promise::Entity |
| |
+------------|-----------+
|
|
+------------|-----------+
| |
| HTTP::Promise::Body |
| |
+------------------------+
CONSTRUCTOR
new
This takes some parameters and instantiates a new HTTP::Promise::Message.
Accepted parameters can be one of the followings:
- 1. an headers object and some content as a string or scalar reference.
-
my $msg = HTTP::Promise::Message->new( HTTP::Promise::Headers->new( Content_Type => 'text/plain', Content_Encoding => 'gzip', Host: 'www.example.org', ), "Some content", ); my $str = "Some content"; my $hdr = HTTP::Promise::Headers->new( Content_Type => 'text/plain', Content_Encoding => 'gzip', Host: 'www.example.org', ); my $msg = HTTP::Promise::Message->new( $hdr, \$str );
- 2. an headers object and and HTTP::Promise::Body or HTTP::Promise::Body::Form object
-
my $body = HTTP::Promise::Body::Scalar->new( "Some content" ); my $hdr = HTTP::Promise::Headers->new( Content_Type => 'text/plain', Content_Encoding => 'gzip', Host: 'www.example.org', ); my $msg = HTTP::Promise::Message->new( $hdr, $body );
Using the x-www-form-urlencoded class:
my $body = HTTP::Promise::Body::Form->new({ name => '嘉納 治五郎', age => 22, city => 'Tokyo' }); my $hdr = HTTP::Promise::Headers->new( Content_Type => 'text/plain', Content_Encoding => 'gzip', Host: 'www.example.org', ); my $msg = HTTP::Promise::Message->new( $hdr, $body );
- 3. an array reference of headers field-value pairs and some content as a string or scalar reference.
-
my $msg = HTTP::Promise::Message->new([ Content_Type => 'text/plain', Content_Encoding => 'gzip', Host: 'www.example.org', ], "Some content", );
- 4. an hash reference of parameters
-
my $hdr = HTTP::Promise::Headers->new( Content_Type => 'text/plain', Content_Encoding => 'gzip', Host: 'www.example.org', ); my $msg = HTTP::Promise::Message->new({ headers => $hdr, content => \$str, # HTP::Promise::Entity entity => $entity_object, debug => 4, });
In any case, you can provide additional object options by providing an hash reference as the last argument, such as:
my $msg = HTTP::Promise::Message->new([
Content_Type => 'text/plain',
Content_Encoding => 'gzip',
Host: 'www.example.org',
],
"Some content",
{
debug => 4,
entity => $entity_object
},
);
If some content is provided, a new entity in-memory body object will be initiated
It returns the new http message object, or upon error, sets an error and returns undef
.
METHODS
add_content
This takes a string or a scalar reference and append it to the current body if the body object is an HTTP::Promise::Body::File or HTTP::Promise::Body::Scalar object. This does not work for HTTP::Promise::Body::Form. You would have to call yourself the class methods to add your key-value pairs.
The content thus provided is downgraded, which means it is flagged as being in perl's internal utf-8 representation. So you cannot use this method to add binary data. If you want to do so, you would need to use directly the body object methods. For example:
my $io = $msg->entity->body->open( '>', { binmode => 'utf-8', autoflush => 1 }) ||
die( $msg->entity->body->error );
$io->print( $some_data ) || die( $io->error );
$io->close;
This code works for either HTTP::Promise::Body::File or HTTP::Promise::Body::Scalar
If no entity, or body is set yet, it will create one automatically, and defaults to HTTP::Promise::Body::Scalar for the body class.
It returns the entity body object, or upon error, sets an error and returns undef
.
add_content_utf8
This is the same thing as "add_content", except it will encode in utf-8 the data provided, i.e. not perl's internal representation.
add_part
By default, this will check if the HTTP message Content-Type
is a multipart one, and if not, it will automatically set it to multipart/form-data
and transform the current HTTP message into the first part of a multipart/form-data
, and add after all the parts provided.
If the 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, multipart/form-data
is the only valid Content-Type for sending multiple data. rfc7578 in section 4.3 states: "[RFC2388] suggested that multiple files for a single form field be transmitted using a nested "multipart/mixed" part. This usage is deprecated."
See also this Stackoverflow discussion and this one too
When used for an HTTP response, one can return either a multipart/form-data
or a 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 HTTP::Promise::Entity or a HTTP::Promise::Message object with an HTTP::Promise::Entity set with "entity") OR a list of parts whose name attribute is set.
If you want to make an HTTP response, you can either return a multipart/form-data
by providing pairs of form-name-and part object as mentioned above, or a multipart/mixed
by providing a list of part object (either a HTTP::Promise::Entity or a HTTP::Promise::Message object with an HTTP::Promise::Entity set with "entity").
For example:
$m->add_part(
file1 => $ent1,
file2 => $ent2,
first_name => $ent3,
last_name => $ent4,
# etc...
);
or, using the name attribute:
$ent1->name( 'file1' );
$ent2->name( 'file2' );
$ent3->name( 'first_name' );
$ent4->name( 'last_name' );
$m->add_part( $ent1, $ent2, $ent3, $ent4 );
Note that you can always set an entity name, and it will only be used if the HTTP message Content-Type is of type multipart/form-data
, unless you set yourself the Content-Disposition
header value.
It returns the current object, or upon error, sets an error and returns undef
.
as_form_data
This will read the body of the HTTP entity and return it as an object of key-value pairs with the module HTTP::Promise::Body::Form
This supports HTTP Content-Type
multipart/form-data
, application/json
, application/x-www-form-urlencoded
, or in the case of HTTP method GET
, HEAD
, or DELETE
, it will use any query string parameters, and return a new HTTP::Promise::Body::Form object.
It defaults to application/x-www-form-urlencoded
. Upon error, it will set an HTTP::Promise::Exception and return undef
in scalar context, or an empty list in list context.
The way this works is it checks first for multipart/form-data
, then application/json
, and for query strings only if there is no HTTP body content, and else it fallbacks to application/x-www-form-urlencoded
.
This means you must be careful if you send or receive JSON
data to properly set the Content-Type
to application/json
as_string
This takes an optional end-of-line terminator and returns a scalar object representing the entire HTTP message.
The end-of-line terminator defaults to $CRLF
, which is a global variable of HTTP::Promise::Message
boundary
This is a shortcut.
It returns the result returned by "boundary" in HTTP::Promise::Headers
can
This behaves like "can" in UNIVERSAL, with a twist.
Provided with a method name and this check if this is supported by HTTP::Promise::Message, or in last resort by HTTP::Promise::Headers and if the latter is true, it will alias the headers method to this namespace.
It returns the code reference of the requested method, or undef
if none could be found.
clear
Clears out the headers object by calling "clear" in HTTP::Promise::Headers, empty the entity body, if any, and remove any part if any.
It does not return anything. This should be called in void context.
clone
This clones the current HTTP message and returns a new object.
content
Get or set the HTTP message body.
If one or more values are provided, they will be added to the newly created HTTP::Promise::Body object.
You can provide as values one or more instance of either a string or a scalar reference.
For example:
$m->content( \$string, 'Hello world', \$another_string );
It returns the newly set HTTP::Promise::Body object upon success or, upon error, sets an error and returns undef
.
When no argument is provided, this returns the HTTP::Promise::Body object as a scalar object.
Beware that the content returned might not be decoded if compression has been applied previously, or if compressed content was provided upon instantiation of the HTTP::Promise::Message
object, such as:
my $m = HTTP::Promise::Message->new([
'Content-Type' => 'text/plain',
'Content-Encoding' => 'deflate, base64',
],
'80jNyclXCM8vyklRBAA='
);
my $content = $m->content; # 80jNyclXCM8vyklRBAA=
But even with utf-8 content, such as:
my $m = HTTP::Promise::Message->new([
'Content-Type' => 'text/plain; charset=utf-8',
],
"\x{E3}\x{81}\x{8A}\x{E6}\x{97}\x{A9}\x{E3}\x{81}\x{86}\x{EF}\x{BC}\x{81}\x{A}",
);
my $content = $m->content;
$content
would contain undecoded utf-8 bytes, i.e. not in perl's internal representation. Indeed, charset is never decoded. If you want the charset decoded content, use "decoded_content", which will guess the content charset to decode it into perl's internal representation. If you are sure this is utf-8, you can either call:
my $decoded_content = $m->decoded_content( binmode => 'utf-8' );
or
my $decoded_content = $m->decoded_content_utf8;
See "decoded_content" for more information.
content_charset
This is a convenient method that calls "content_charset" in HTTP::Promise::Entity and returns the result.
This method attempts at guessing the content charset of the entity body.
It returns a string representing the content charset, possibly empty if nothing was found, or upon error, sets an error and returns undef
.
content_ref
This sets or gets the content as a scalar reference.
In assignment mode, this takes a scalar reference and pass it to "content" and returns the body object
Otherwise, this returns the content as scalar object.
If an error occurs, this sets an error and returns undef
.
decodable
This gets an array object of all supported and installed decodings on the system, by calling "decodable" in HTTP::Promise::Stream
decode
This decodes the HTTP message body and return true.
If there is no Content-Encoding
set, or the entity body is empty, or the entity body already has been decoded, this does nothing obviously. Otherwise, this calls "decode_body" in HTTP::Promise::Entity passing it the encodings as an array reference.
If an error occurs, this sets an error and returns undef
.
decode_content
This is similar to </decode>, except that it takes an hash or hash reference of options passed to "decode_body" in HTTP::Promise::Entity, notably replace
, which if true will replace the body by its decoded version and if false will return a new body version representing the decoded body.
This returns the entity body object upon success, or upon error, sets an error and returns undef
.
decoded_content
This takes an hash or hash reference of options and returns the decoded representation of the body, including charset.
This calls "decode_content", passing it the options provided, to decompress the entity body if necessary. Then, unless the binmode
option was provided, this calls "io_encoding" in HTTP::Promise::Entity to guess the charset encoding, and set the binmode
option to it, if anything was found.
If the entity body is an xml file, any BOM
(Byte Order Mark) will be removed.
This returns the content as a scalar object, or upon error, sets an error and returns undef
.
Supported options are:
binmode
The PerlIO encoding to apply to decode the data.
If not provided, this will be guessed by calling "io_encoding" in HTTP::Promise::Entity
charset_strict
If true, this will returns an error if there is some issues with the content charset. By default, this is false, making it lenient, especially with malformed utf-8.
raise_error
When set to true, this will cause this method to die upon error. Default is false.
decoded_content_utf8
This calls "decoded_content", but this sets the binmode
option to utf-8
.
It returns whatever "decode_content" returns.
decoded_json
If the content type of the response is application/json
, this will call "decoded_content_utf8" and decode the JSON payload and return the hash reference. If an error occurred, it will set an error and return undef
in scalar context, or an empty list in list context.
dump
This takes an hash or hash reference of options and either print the resulting dump on the STDOUT
in void content, or returns a string representation of the HTTP message, or upon error, sets an error and returns undef
.
Supported options are:
maxlength
The maximum amount of body data in bytes to display.
no_content
The string to use when there is no entity body data.
prefix
A string to be added at the beginning of each line of the data returned.
preheader
An arbitrary string to add before the HTTP headers, typically the HTTP
start line
# Returns a string
my $dump = $msg->dump;
# Prints on the STDOUT the result
$msg->dump;
encode
This takes an optional list of encoding and an optional hash or hash reference of options and encode the entity body and returns true, or upon error, sets an error and returns undef
.
This will return an error if it is used on a multipart message or an message/*
such as message/http
.
Obviously this is a no-op if no encoding was found, or if the body is empty, or if the body is already marked as encoded
Supported options are:
update_header
When true, this will set the
Content-Encoding
with the encoding used to encode the entity body and remove the headersContent-Length
andContent-MD5
. Defaults to true.
entity
Sets or gets the HTTP entity object
header
This is a shortcut by calling "header" in HTTP::Promise::Headers
headers
Sets or gets the HTTP::Promise::Headers object.
headers_as_string
This is a shortcut to call "as_string" in HTTP::Promise::Headers
is_encoding_supported
Provided with an encoding and this returns true if the encoding is supported by HTTP::Promise::Stream
make_boundary
Returns a newly generated boundary, which is basically a uuid generated by the XS module Data::UUID
parse
Provided with a string and this will try to parse this HTTP message and returns the current message object if it was called with an HTTP message, or a new HTTP message if it was called as a class function, or upon error, sets an error and returns undef
.
my $msg = HTTP::Promise::Message->parse( $some_http_message ) ||
die( HTTP::Promise::Message->error );
$msg->parse( $some_http_message ) ||
die( HTTP::Promise::Message->error );
parts
This returns the HTTP message entity parts as an array object and returns it, or upon error, sets an error and returns undef
.
If the HTTP message has a body with content and there is no part and the mime-type top type is multipart
or message
, this will first parse the body into parts. Thus you could do:
my $msg = HTTP::Promise::Message->new([
Content_Type => 'multipart/form-data; boundary="abcd"',
Content_Encoding => 'gzip',
Host => 'example.org',
], <<EOT );
--abcd
Content-Disposition: form-data; name="name"
Jigoro Kano
--abcd
Content-Disposition: form-data; name="birthdate"
1860-12-10
--abcd--
EOT
my $parts = $msg->parts;
protocol
Sets or gets the HTTP protocol. This is typically something like HTTP/1.0
, HTTP/1.1
, HTTP/2
Returns the HTTP protocol, if any was set, as a scalar object, or upon error, sets an error and returns undef
.
Note that it may return undef
if no protocol was set. Errors are likely to occur when assigning an improper value.
start_line
This is a no-op since it is superseded by its inheriting classes HTTP::Promise::Request and HTTP::Promise::Response
version
Sets or gets the HTTP protocol version, something like 1.0
, or 1.1
, or maybe 2
This returns a number object
AUTHOR
Jacques Deguest <jack@deguest.jp>
SEE ALSO
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.