view release on metacpan or search on metacpan
auto_switch_https
Boolean. If set to a true value, or if left to "undef" (default value),
this will set the "Upgrade-Insecure-Requests" header field to 1
buffer_size
The size of the buffer to use when reading data from the filehandle or
socket.
connection_header
Sets or gets the value for the header "Connection". It can be "close" or
"keep-alive"
If it is let "undef", this module will try to guess the proper value
based on the "protocol" in HTTP::Promise::Request and "version" in
HTTP::Promise::Request used.
For protocol "HTTP/1.0", "Connection" value would be "close", but above
"HTTP/1.1" the connection can be set to "keep-alive" and thus be
re-used.
cookie_jar
Sets or gets the Cookie jar class object to use. This is typically
Cookie::Jar or maybe HTTP::Cookies
This defaults to Cookie::Jar
use Cookie::Jar;
my $jar = Cookie::Jar->new;
## auto\_switch\_https
Boolean. If set to a true value, or if left to `undef` (default value), this will set the `Upgrade-Insecure-Requests` header field to `1`
## buffer\_size
The size of the buffer to use when reading data from the filehandle or socket.
## connection\_header
Sets or gets the value for the header `Connection`. It can be `close` or `keep-alive`
If it is let `undef`, this module will try to guess the proper value based on the ["protocol" in HTTP::Promise::Request](https://metacpan.org/pod/HTTP%3A%3APromise%3A%3ARequest#protocol) and ["version" in HTTP::Promise::Request](https://metacpan.org/...
For protocol `HTTP/1.0`, `Connection` value would be `close`, but above `HTTP/1.1` the connection can be set to `keep-alive` and thus be re-used.
## cookie\_jar
Sets or gets the Cookie jar class object to use. This is typically [Cookie::Jar](https://metacpan.org/pod/Cookie%3A%3AJar) or maybe [HTTP::Cookies](https://metacpan.org/pod/HTTP%3A%3ACookies)
This defaults to [Cookie::Jar](https://metacpan.org/pod/Cookie%3A%3AJar)
use Cookie::Jar;
my $jar = Cookie::Jar->new;
my $p = HTTP::Promise->new( cookie_jar => $jar );
lib/HTTP/Promise.pm view on Meta::CPAN
$self->{use_content_file} = 0;
$self->{use_promise} = 1;
$self->{_init_strict_use_sub} = 1;
$self->{_exception_class} = $EXCEPTION_CLASS;
$self->SUPER::init( @_ ) || return( $self->pass_error );
my $headers = $self->default_headers;
if( $headers )
{
unless( $self->connection_header )
{
my $connection_header = 'keep-alive';
if( $headers->exists( 'connection' ) )
{
$connection_header = $headers->get( 'connection' );
}
$self->{connection_header} = $connection_header;
}
}
else
{
$self->default_headers( HTTP::Promise::Headers->new ) ||
lib/HTTP/Promise.pm view on Meta::CPAN
{
$io = HTTP::Promise::IO->new( $sock, stop_if => $self->stop_if ) ||
return( $self->pass_error( HTTP::Promise::IO->error ) );
if( !$io->make_select( write => 0, timeout => 0 ) )
{
close( $sock );
undef( $sock );
}
else
{
$p->{in_keepalive} = 1;
}
}
if( !$p->{in_keepalive} )
{
if( $proxy )
{
# my( undef, $proxy_user, $proxy_pass, $proxy_host, $proxy_port, undef) = $self->_parse_url($proxy);
return( $self->error( "Proxy set '$proxy' (", overload::StrVal( $proxy ), ") is not URI object." ) ) if( !$self->_is_a( $proxy => 'URI' ) );
my $proxy_auth = $proxy->userinfo;
my( $proxy_user, $proxy_pass ) = split( /:/, $proxy_auth, 2 );
my $proxy_authorization;
if( defined( $proxy_user ) && length( $proxy_user ) )
{
lib/HTTP/Promise.pm view on Meta::CPAN
my $connection_header = $self->connection_header;
# If no connection_header value was provided, let's guess it based on the protocol used
unless( $connection_header )
{
if( uc( $method ) eq 'HEAD' )
{
$connection_header = 'close';
}
elsif( $req->version && $req->version > 1.0 )
{
$connection_header = 'keep-alive';
}
else
{
$connection_header = 'close';
}
}
my $cookie_jar = $self->cookie_jar;
{
my $headers = $req->headers;
lib/HTTP/Promise.pm view on Meta::CPAN
# <https://security.stackexchange.com/questions/110565/large-over-sizesd-http-header-lengths-and-security-implications>
my $max = $self->max_headers_size;
my( $n, $def, $headers );
$n = -1;
LOOP: while(1)
{
$n = $io->read( $buff, 2048, length( $buff ) );
if( !defined( $n ) || $n == 0 )
{
my $code = defined( $n ) ? '' : $io->error->code;
if( $p->{in_keepalive} &&
( length( $buff ) // 0 ) == 0 &&
!$opts->{total_attempts} &&
( defined( $n ) || $code == ECONNRESET || ( $IS_WIN32 && $code == ECONNABORTED ) ) )
{
# the server closed the connection (maybe because of keep-alive timeout)
$opts->{total_attempts}++;
return( $self->send( $req, %$opts ) );
}
elsif( !length( $buff ) )
{
return( $self->error({ code => HTTP_BAD_REQUEST, message => "Unexpected EOF while reading response from socket '", $io->filehandle, "'." }) );
}
elsif( !defined( $n ) )
{
return( $self->pass_error( $io->error ) );
lib/HTTP/Promise.pm view on Meta::CPAN
reader => $io,
headers => $headers,
entity => $ent,
) || return( $self->pass_error );
}
return( $self->pass_error ) if( !defined( $body ) );
$total_bytes_read += $body->length;
$ent->body( $body );
}
# manage connection cache (i.e. keep-alive)
if( defined( $connection_header ) &&
lc( $connection_header ) eq 'keep-alive' )
{
my $connection = $headers->connection->lc // '';
if( ( $def->{version} > 1.0
? $connection ne 'close' # HTTP/1.1 can keep alive by default
: $connection eq 'keep-alive' # HTTP/1.0 needs explicit keep-alive
) && ( defined( $content_length ) or $chunked ) )
{
my $sock = $io->filehandle;
$self->_pool->push( $uri->host, $uri->port, $sock ) ||
return( $self->pass_error );
}
}
# explicitly close here, just after returning the socket to the pool,
# since it might be reused in the upcoming recursive call
# undef( $sock );
lib/HTTP/Promise.pm view on Meta::CPAN
=head2 auto_switch_https
Boolean. If set to a true value, or if left to C<undef> (default value), this will set the C<Upgrade-Insecure-Requests> header field to C<1>
=head2 buffer_size
The size of the buffer to use when reading data from the filehandle or socket.
=head2 connection_header
Sets or gets the value for the header C<Connection>. It can be C<close> or C<keep-alive>
If it is let C<undef>, this module will try to guess the proper value based on the L<HTTP::Promise::Request/protocol> and L<HTTP::Promise::Request/version> used.
For protocol C<HTTP/1.0>, C<Connection> value would be C<close>, but above C<HTTP/1.1> the connection can be set to C<keep-alive> and thus be re-used.
=head2 cookie_jar
Sets or gets the Cookie jar class object to use. This is typically L<Cookie::Jar> or maybe L<HTTP::Cookies>
This defaults to L<Cookie::Jar>
use Cookie::Jar;
my $jar = Cookie::Jar->new;
my $p = HTTP::Promise->new( cookie_jar => $jar );
lib/HTTP/Promise/Headers.pm view on Meta::CPAN
clearsitedata => 'HTTP::Promise::Headers::ClearSiteData',
contentdisposition => 'HTTP::Promise::Headers::ContentDisposition',
contentrange => 'HTTP::Promise::Headers::ContentRange',
contentsecuritypolicy => 'HTTP::Promise::Headers::ContentSecurityPolicy',
contentsecuritypolicyreportonly => 'HTTP::Promise::Headers::ContentSecurityPolicyReportOnly',
contenttype => 'HTTP::Promise::Headers::ContentType',
cookie => 'HTTP::Promise::Headers::Cookie',
expectct => 'HTTP::Promise::Headers::ExpectCT',
forwarded => 'HTTP::Promise::Headers::Forwarded',
generic => 'HTTP::Promise::Headers::Generic',
keepalive => 'HTTP::Promise::Headers::KeepAlive',
link => 'HTTP::Promise::Headers::Link',
range => 'HTTP::Promise::Headers::Range',
servertiming => 'HTTP::Promise::Headers::ServerTiming',
stricttransportsecurity => 'HTTP::Promise::Headers::StrictTransportSecurity',
te => 'HTTP::Promise::Headers::TE',
wantdigest => 'HTTP::Promise::Headers::WantDigest',
};
sub new
{
lib/HTTP/Promise/Headers.pm view on Meta::CPAN
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Range>
sub if_range { return( shift->_set_get_one( 'If-Range', @_ ) ); }
# NOTE: if_unmodified_since() is inherited
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Unmodified-Since>
sub if_unmodified_since { return( shift->_date_header( 'If-Unmodified-Since', @_ ) ); }
# NOTE: init_header() is inherited
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive>
sub keep_alive { return( shift->_set_get_one( 'Keep-Alive', @_ ) ); }
# NOTE: last_modified() is inherited
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified>
sub last_modified { return( shift->_date_header( 'Last-Modified', @_ ) ); }
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link>
sub link { return( shift->_set_get_multi( 'Link', @_ ) ); }
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location>
sub location { return( shift->_set_get_one( 'Location', @_ ) ); }
lib/HTTP/Promise/Headers.pm view on Meta::CPAN
$h->clear_site_data( [qw( cache cookies storage executionContexts )] );
The Clear-Site-Data header accepts one or more directives. If all types of data should be cleared, the wildcard directive ("*") can be used.
See also L<HTTP::Promise::Headers::ClearSiteData> to have a more granular control.
See L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data>
=head2 connection
# Connection: keep-alive
# Connection: close
Sets or gets the C<Connection> header field value. It takes a string value.
See L<rfc7230, section 6.1|https://tools.ietf.org/html/rfc7230#section-6.1> and L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection>
=head2 content_disposition
# Content-Disposition: inline
# Content-Disposition: attachment
lib/HTTP/Promise/Headers.pm view on Meta::CPAN
This sets or gets the C<If-Unmodified-Since> header value. It takes a date string value, a unix timestamp or a L<DateTime::Lite>, or a L<DateTime> value.
If no value is provided, it returns the current value of the C<Date> header field as a L<DateTime::Lite> object.
For example:
If-Unmodified-Since: Wed, 21 Oct 2015 07:28:00 GMT
See also L<rfc7232, section 3.4|https://tools.ietf.org/html/rfc7232#section-3.4> and L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Unmodified-Since>
=head2 keep_alive
This sets or gets the C<Keep-Alive> header value. It takes either a string or an array or array reference of properly formatted values.
See also L<HTTP::Promise::Headers::KeepAlive> to have a more granular control.
Example response containing a Keep-Alive header:
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
lib/HTTP/Promise/Parser.pm view on Meta::CPAN
# 417 Expectation failed
# 422 Unprocessable entity
# 425 Too early
elsif( $len == -2 )
{
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 ) );
lib/HTTP/Promise/Status.pm view on Meta::CPAN
See L<rfc7231, section 6.3.1|https://datatracker.ietf.org/doc/html/rfc7231#section-6.3.1>
This is returned to inform the request has succeeded. It can also alternatively be C<204 No Content> when there is no response body.
For example:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 184
Connection: keep-alive
Cache-Control: s-maxage=300, public, max-age=0
Content-Language: en-US
Date: Mon, 18 Apr 2022 17:37:18 GMT
ETag: "2e77ad1dc6ab0b53a2996dfd4653c1c3"
Server: Apache/2.4
Strict-Transport-Security: max-age=63072000
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Vary: Accept-Encoding,Cookie
t/03.headers.t view on Meta::CPAN
can_ok( $h => 'expires' );
can_ok( $h => 'expose_headers' );
can_ok( $h => 'forwarded' );
can_ok( $h => 'from' );
can_ok( $h => 'host' );
can_ok( $h => 'if_match' );
can_ok( $h => 'if_modified_since' );
can_ok( $h => 'if_none_match' );
can_ok( $h => 'if_range' );
can_ok( $h => 'if_unmodified_since' );
can_ok( $h => 'keep_alive' );
can_ok( $h => 'last_modified' );
can_ok( $h => 'link' );
can_ok( $h => 'location' );
can_ok( $h => 'max_age' );
can_ok( $h => 'nel' );
can_ok( $h => 'origin' );
can_ok( $h => 'proxy' );
can_ok( $h => 'proxy_authenticate' );
can_ok( $h => 'proxy_authorization' );
can_ok( $h => 'range' );
t/13.header_fields.t view on Meta::CPAN
{
use ok( 'HTTP::Promise::Headers::Forwarded' );
my $str = q{for=192.0.2.60; proto=http; by=203.0.113.43};
my $h = HTTP::Promise::Headers::Forwarded->new( $str );
is( "$h", $str );
is( $h->for, '192.0.2.60' );
is( $h->proto, 'http' );
is( $h->by, '203.0.113.43' );
};
subtest 'keep-alive' => sub
{
use ok( 'HTTP::Promise::Headers::KeepAlive' );
my $str = q{timeout=5, max=1000};
my $h = HTTP::Promise::Headers::KeepAlive->new( $str );
is( "$h", $str );
is( $h->timeout, 5 );
is( $h->max, 1000 );
};
subtest 'link' => sub
t/13.header_fields.t view on Meta::CPAN
clear_site_data => 'HTTP::Promise::Headers::ClearSiteData',
content_disposition => 'HTTP::Promise::Headers::ContentDisposition',
content_range => 'HTTP::Promise::Headers::ContentRange',
content_securit_ypolicy => 'HTTP::Promise::Headers::ContentSecurityPolicy',
content_security_policy_report_only => 'HTTP::Promise::Headers::ContentSecurityPolicyReportOnly',
content_type => 'HTTP::Promise::Headers::ContentType',
cookie => 'HTTP::Promise::Headers::Cookie',
expectct => 'HTTP::Promise::Headers::ExpectCT',
forwarded => 'HTTP::Promise::Headers::Forwarded',
generic => 'HTTP::Promise::Headers::Generic',
keepalive => 'HTTP::Promise::Headers::KeepAlive',
link => 'HTTP::Promise::Headers::Link',
range => 'HTTP::Promise::Headers::Range',
server_timing => 'HTTP::Promise::Headers::ServerTiming',
strict_transport_security => 'HTTP::Promise::Headers::StrictTransportSecurity',
te => 'HTTP::Promise::Headers::TE',
wantdigest => 'HTTP::Promise::Headers::WantDigest',
);
foreach( sort( keys( %tests ) ) )
{
my $f = $h->new_field( $_ ) || do
t/14.reader.t view on Meta::CPAN
POST /test HTTP/1.1
Host: www.csm-testcenter.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr-FR,en-GB;q=0.8,fr;q=0.6,en;q=0.4,ja;q=0.2
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------40260073931083483614643569375
Content-Length: 79784
Origin: http://www.csm-testcenter.org
DNT: 1
Connection: keep-alive
Referer: http://www.csm-testcenter.org/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Sec-Fetch-User: ?1
EOT
$io->seek(0,0);
$reader->buffer->reset;
t/14.reader.t view on Meta::CPAN
is( $data, q{POST /test HTTP/1.1
Host: www.csm-testcenter.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr-FR,en-GB;q=0.8,fr;q=0.6,en;q=0.4,ja;q=0.2
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------40260073931083483614643569375
Content-Length: 79784
Origin: http://www.csm-testcenter.org
DNT: 1
Connection: keep-alive
Referer: http://www.csm-testcenter.org/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Sec-Fetch-User: ?1} );
use ok( 'HTTP::Promise::Parser' );
my $p = HTTP::Promise::Parser->new( debug => $DEBUG );
my $def = $p->parse_request_headers( "$data\n\n" ) || bail_out( $p->error );
my $headers = $def->{headers};