Initial Commit
This commit is contained in:
446
database/perl/vendor/lib/Mojo/Message/Request.pm
vendored
Normal file
446
database/perl/vendor/lib/Mojo/Message/Request.pm
vendored
Normal file
@@ -0,0 +1,446 @@
|
||||
package Mojo::Message::Request;
|
||||
use Mojo::Base 'Mojo::Message';
|
||||
|
||||
use Digest::SHA qw(sha1_base64);
|
||||
use Mojo::Cookie::Request;
|
||||
use Mojo::Util qw(b64_encode b64_decode sha1_sum);
|
||||
use Mojo::URL;
|
||||
|
||||
has env => sub { {} };
|
||||
has method => 'GET';
|
||||
has [qw(proxy reverse_proxy)];
|
||||
has request_id => sub {
|
||||
state $seed = $$ . time . rand;
|
||||
state $counter = int rand 0xffffff;
|
||||
my $b64 = substr(sha1_base64($seed . ($counter = ($counter + 1) % 0xffffff)), 0, 8);
|
||||
$b64 =~ tr!+/!-_!;
|
||||
return $b64;
|
||||
};
|
||||
has url => sub { Mojo::URL->new };
|
||||
has via_proxy => 1;
|
||||
|
||||
sub clone {
|
||||
my $self = shift;
|
||||
|
||||
# Dynamic requests cannot be cloned
|
||||
return undef unless my $content = $self->content->clone;
|
||||
my $clone
|
||||
= $self->new(content => $content, method => $self->method, url => $self->url->clone, version => $self->version);
|
||||
$clone->{proxy} = $self->{proxy}->clone if $self->{proxy};
|
||||
|
||||
return $clone;
|
||||
}
|
||||
|
||||
sub cookies {
|
||||
my $self = shift;
|
||||
|
||||
# Parse cookies
|
||||
my $headers = $self->headers;
|
||||
return [map { @{Mojo::Cookie::Request->parse($_)} } $headers->cookie] unless @_;
|
||||
|
||||
# Add cookies
|
||||
my @cookies = map { ref $_ eq 'HASH' ? Mojo::Cookie::Request->new($_) : $_ } $headers->cookie || (), @_;
|
||||
$headers->cookie(join '; ', @cookies);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub every_param { shift->params->every_param(@_) }
|
||||
|
||||
sub extract_start_line {
|
||||
my ($self, $bufref) = @_;
|
||||
|
||||
# Ignore any leading empty lines
|
||||
return undef unless $$bufref =~ s/^\s*(.*?)\x0d?\x0a//;
|
||||
|
||||
# We have a (hopefully) full request-line
|
||||
return !$self->error({message => 'Bad request start-line'}) unless $1 =~ /^(\S+)\s+(\S+)\s+HTTP\/(\d\.\d)$/;
|
||||
my $url = $self->method($1)->version($3)->url;
|
||||
my $target = $2;
|
||||
return !!$url->host_port($target) if $1 eq 'CONNECT';
|
||||
return !!$url->parse($target)->fragment(undef) if $target =~ /^[^:\/?#]+:/;
|
||||
return !!$url->path_query($target);
|
||||
}
|
||||
|
||||
sub fix_headers {
|
||||
my $self = shift;
|
||||
$self->{fix} ? return $self : $self->SUPER::fix_headers(@_);
|
||||
|
||||
# Host
|
||||
my $url = $self->url;
|
||||
my $headers = $self->headers;
|
||||
$headers->host($url->host_port) unless $headers->host;
|
||||
|
||||
# Basic authentication
|
||||
if ((my $info = $url->userinfo) && !$headers->authorization) {
|
||||
$headers->authorization('Basic ' . b64_encode($info, ''));
|
||||
}
|
||||
|
||||
# Basic proxy authentication
|
||||
return $self unless (my $proxy = $self->proxy) && $self->via_proxy;
|
||||
return $self unless my $info = $proxy->userinfo;
|
||||
$headers->proxy_authorization('Basic ' . b64_encode($info, '')) unless $headers->proxy_authorization;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub get_start_line_chunk {
|
||||
my ($self, $offset) = @_;
|
||||
$self->_start_line->emit(progress => 'start_line', $offset);
|
||||
return substr $self->{start_buffer}, $offset, 131072;
|
||||
}
|
||||
|
||||
sub is_handshake { lc($_[0]->headers->upgrade // '') eq 'websocket' }
|
||||
|
||||
sub is_secure {
|
||||
my $url = shift->url;
|
||||
return ($url->protocol || $url->base->protocol) eq 'https';
|
||||
}
|
||||
|
||||
sub is_xhr { (shift->headers->header('X-Requested-With') // '') =~ /XMLHttpRequest/i }
|
||||
|
||||
sub param { shift->params->param(@_) }
|
||||
|
||||
sub params { $_[0]->{params} ||= $_[0]->body_params->clone->append($_[0]->query_params) }
|
||||
|
||||
sub parse {
|
||||
my ($self, $env, $chunk) = (shift, ref $_[0] ? (shift, '') : (undef, shift));
|
||||
|
||||
# Parse CGI environment
|
||||
$self->env($env)->_parse_env($env) if $env;
|
||||
|
||||
# Parse normal message
|
||||
if (($self->{state} // '') ne 'cgi') { $self->SUPER::parse($chunk) }
|
||||
|
||||
# Parse CGI content
|
||||
else { $self->content($self->content->parse_body($chunk))->SUPER::parse('') }
|
||||
|
||||
# Check if we can fix things that require all headers
|
||||
return $self unless $self->is_finished;
|
||||
|
||||
# Base URL
|
||||
my $base = $self->url->base;
|
||||
$base->scheme('http') unless $base->scheme;
|
||||
my $headers = $self->headers;
|
||||
if (!$base->host && (my $host = $headers->host)) { $base->host_port($host) }
|
||||
|
||||
# Basic authentication
|
||||
if (my $basic = _basic($headers->authorization)) { $base->userinfo($basic) }
|
||||
|
||||
# Basic proxy authentication
|
||||
my $basic = _basic($headers->proxy_authorization);
|
||||
$self->proxy(Mojo::URL->new->userinfo($basic)) if $basic;
|
||||
|
||||
# "X-Forwarded-Proto"
|
||||
$base->scheme('https') if $self->reverse_proxy && ($headers->header('X-Forwarded-Proto') // '') eq 'https';
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub query_params { shift->url->query }
|
||||
|
||||
sub start_line_size { length shift->_start_line->{start_buffer} }
|
||||
|
||||
sub _basic { $_[0] && $_[0] =~ /Basic (.+)$/ ? b64_decode $1 : undef }
|
||||
|
||||
sub _parse_env {
|
||||
my ($self, $env) = @_;
|
||||
|
||||
# Bypass normal message parser
|
||||
$self->{state} = 'cgi';
|
||||
|
||||
# Extract headers
|
||||
my $headers = $self->headers;
|
||||
my $url = $self->url;
|
||||
my $base = $url->base;
|
||||
for my $name (keys %$env) {
|
||||
my $value = $env->{$name};
|
||||
next unless $name =~ s/^HTTP_//i;
|
||||
$name =~ y/_/-/;
|
||||
$headers->header($name => $value);
|
||||
|
||||
# Host/Port
|
||||
$value =~ s/:(\d+)$// ? $base->host($value)->port($1) : $base->host($value) if $name eq 'HOST';
|
||||
}
|
||||
|
||||
# Content-Type is a special case on some servers
|
||||
$headers->content_type($env->{CONTENT_TYPE}) if $env->{CONTENT_TYPE};
|
||||
|
||||
# Content-Length is a special case on some servers
|
||||
$headers->content_length($env->{CONTENT_LENGTH}) if $env->{CONTENT_LENGTH};
|
||||
|
||||
# Query
|
||||
$url->query->parse($env->{QUERY_STRING}) if $env->{QUERY_STRING};
|
||||
|
||||
# Method
|
||||
$self->method($env->{REQUEST_METHOD}) if $env->{REQUEST_METHOD};
|
||||
|
||||
# Scheme/Version
|
||||
$base->scheme($1) and $self->version($2) if ($env->{SERVER_PROTOCOL} // '') =~ m!^([^/]+)/([^/]+)$!;
|
||||
|
||||
# HTTPS
|
||||
$base->scheme('https') if uc($env->{HTTPS} // '') eq 'ON';
|
||||
|
||||
# Path
|
||||
my $path = $url->path->parse($env->{PATH_INFO} ? $env->{PATH_INFO} : '');
|
||||
|
||||
# Base path
|
||||
if (my $value = $env->{SCRIPT_NAME}) {
|
||||
|
||||
# Make sure there is a trailing slash (important for merging)
|
||||
$base->path->parse($value =~ m!/$! ? $value : "$value/");
|
||||
|
||||
# Remove SCRIPT_NAME prefix if necessary
|
||||
my $buffer = $path->to_string;
|
||||
$value =~ s!^/|/$!!g;
|
||||
$buffer =~ s!^/?\Q$value\E/?!!;
|
||||
$buffer =~ s!^/!!;
|
||||
$path->parse($buffer);
|
||||
}
|
||||
}
|
||||
|
||||
sub _start_line {
|
||||
my $self = shift;
|
||||
|
||||
return $self if defined $self->{start_buffer};
|
||||
|
||||
# Path
|
||||
my $url = $self->url;
|
||||
my $path = $url->path_query;
|
||||
$path = "/$path" unless $path =~ m!^/!;
|
||||
|
||||
# CONNECT
|
||||
my $method = uc $self->method;
|
||||
if ($method eq 'CONNECT') {
|
||||
my $port = $url->port // ($url->protocol eq 'https' ? '443' : '80');
|
||||
$path = $url->ihost . ":$port";
|
||||
}
|
||||
|
||||
# Proxy
|
||||
elsif ($self->proxy && $self->via_proxy && $url->protocol ne 'https') {
|
||||
$path = $url->clone->userinfo(undef) unless $self->is_handshake;
|
||||
}
|
||||
|
||||
$self->{start_buffer} = "$method $path HTTP/@{[$self->version]}\x0d\x0a";
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Mojo::Message::Request - HTTP request
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Mojo::Message::Request;
|
||||
|
||||
# Parse
|
||||
my $req = Mojo::Message::Request->new;
|
||||
$req->parse("GET /foo HTTP/1.0\x0d\x0a");
|
||||
$req->parse("Content-Length: 12\x0d\x0a");
|
||||
$req->parse("Content-Type: text/plain\x0d\x0a\x0d\x0a");
|
||||
$req->parse('Hello World!');
|
||||
say $req->method;
|
||||
say $req->headers->content_type;
|
||||
say $req->body;
|
||||
|
||||
# Build
|
||||
my $req = Mojo::Message::Request->new;
|
||||
$req->url->parse('http://127.0.0.1/foo/bar');
|
||||
$req->method('GET');
|
||||
say $req->to_string;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
L<Mojo::Message::Request> is a container for HTTP requests, based on L<RFC 7230|https://tools.ietf.org/html/rfc7230>,
|
||||
L<RFC 7231|https://tools.ietf.org/html/rfc7231>, L<RFC 7235|https://tools.ietf.org/html/rfc7235> and L<RFC
|
||||
2817|https://tools.ietf.org/html/rfc2817>.
|
||||
|
||||
=head1 EVENTS
|
||||
|
||||
L<Mojo::Message::Request> inherits all events from L<Mojo::Message>.
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
L<Mojo::Message::Request> inherits all attributes from L<Mojo::Message> and implements the following new ones.
|
||||
|
||||
=head2 env
|
||||
|
||||
my $env = $req->env;
|
||||
$req = $req->env({PATH_INFO => '/'});
|
||||
|
||||
Direct access to the C<CGI> or C<PSGI> environment hash if available.
|
||||
|
||||
# Check CGI version
|
||||
my $version = $req->env->{GATEWAY_INTERFACE};
|
||||
|
||||
# Check PSGI version
|
||||
my $version = $req->env->{'psgi.version'};
|
||||
|
||||
=head2 method
|
||||
|
||||
my $method = $req->method;
|
||||
$req = $req->method('POST');
|
||||
|
||||
HTTP request method, defaults to C<GET>.
|
||||
|
||||
=head2 proxy
|
||||
|
||||
my $url = $req->proxy;
|
||||
$req = $req->proxy(Mojo::URL->new('http://127.0.0.1:3000'));
|
||||
|
||||
Proxy URL for request.
|
||||
|
||||
=head2 reverse_proxy
|
||||
|
||||
my $bool = $req->reverse_proxy;
|
||||
$req = $req->reverse_proxy($bool);
|
||||
|
||||
Request has been performed through a reverse proxy.
|
||||
|
||||
=head2 request_id
|
||||
|
||||
my $id = $req->request_id;
|
||||
$req = $req->request_id('aee7d5d8');
|
||||
|
||||
Request ID, defaults to a reasonably unique value.
|
||||
|
||||
=head2 url
|
||||
|
||||
my $url = $req->url;
|
||||
$req = $req->url(Mojo::URL->new);
|
||||
|
||||
HTTP request URL, defaults to a L<Mojo::URL> object.
|
||||
|
||||
# Get request information
|
||||
my $info = $req->url->to_abs->userinfo;
|
||||
my $host = $req->url->to_abs->host;
|
||||
my $path = $req->url->to_abs->path;
|
||||
|
||||
=head2 via_proxy
|
||||
|
||||
my $bool = $req->via_proxy;
|
||||
$req = $req->via_proxy($bool);
|
||||
|
||||
Request can be performed through a proxy server.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
L<Mojo::Message::Request> inherits all methods from L<Mojo::Message> and implements the following new ones.
|
||||
|
||||
=head2 clone
|
||||
|
||||
my $clone = $req->clone;
|
||||
|
||||
Return a new L<Mojo::Message::Request> object cloned from this request if possible, otherwise return C<undef>.
|
||||
|
||||
=head2 cookies
|
||||
|
||||
my $cookies = $req->cookies;
|
||||
$req = $req->cookies(Mojo::Cookie::Request->new);
|
||||
$req = $req->cookies({name => 'foo', value => 'bar'});
|
||||
|
||||
Access request cookies, usually L<Mojo::Cookie::Request> objects.
|
||||
|
||||
# Names of all cookies
|
||||
say $_->name for @{$req->cookies};
|
||||
|
||||
=head2 every_param
|
||||
|
||||
my $values = $req->every_param('foo');
|
||||
|
||||
Similar to L</"param">, but returns all values sharing the same name as an array reference.
|
||||
|
||||
# Get first value
|
||||
say $req->every_param('foo')->[0];
|
||||
|
||||
=head2 extract_start_line
|
||||
|
||||
my $bool = $req->extract_start_line(\$str);
|
||||
|
||||
Extract request-line from string.
|
||||
|
||||
=head2 fix_headers
|
||||
|
||||
$req = $req->fix_headers;
|
||||
|
||||
Make sure request has all required headers.
|
||||
|
||||
=head2 get_start_line_chunk
|
||||
|
||||
my $bytes = $req->get_start_line_chunk($offset);
|
||||
|
||||
Get a chunk of request-line data starting from a specific position. Note that this method finalizes the request.
|
||||
|
||||
=head2 is_handshake
|
||||
|
||||
my $bool = $req->is_handshake;
|
||||
|
||||
Check C<Upgrade> header for C<websocket> value.
|
||||
|
||||
=head2 is_secure
|
||||
|
||||
my $bool = $req->is_secure;
|
||||
|
||||
Check if connection is secure.
|
||||
|
||||
=head2 is_xhr
|
||||
|
||||
my $bool = $req->is_xhr;
|
||||
|
||||
Check C<X-Requested-With> header for C<XMLHttpRequest> value.
|
||||
|
||||
=head2 param
|
||||
|
||||
my $value = $req->param('foo');
|
||||
|
||||
Access C<GET> and C<POST> parameters extracted from the query string and C<application/x-www-form-urlencoded> or
|
||||
C<multipart/form-data> message body. If there are multiple values sharing the same name, and you want to access more
|
||||
than just the last one, you can use L</"every_param">. Note that this method caches all data, so it should not be
|
||||
called before the entire request body has been received. Parts of the request body need to be loaded into memory to
|
||||
parse C<POST> parameters, so you have to make sure it is not excessively large. There's a 16MiB limit for requests by
|
||||
default.
|
||||
|
||||
=head2 params
|
||||
|
||||
my $params = $req->params;
|
||||
|
||||
All C<GET> and C<POST> parameters extracted from the query string and C<application/x-www-form-urlencoded> or
|
||||
C<multipart/form-data> message body, usually a L<Mojo::Parameters> object. Note that this method caches all data, so it
|
||||
should not be called before the entire request body has been received. Parts of the request body need to be loaded into
|
||||
memory to parse C<POST> parameters, so you have to make sure it is not excessively large. There's a 16MiB limit for
|
||||
requests by default.
|
||||
|
||||
# Get parameter names and values
|
||||
my $hash = $req->params->to_hash;
|
||||
|
||||
=head2 parse
|
||||
|
||||
$req = $req->parse('GET /foo/bar HTTP/1.1');
|
||||
$req = $req->parse({PATH_INFO => '/'});
|
||||
|
||||
Parse HTTP request chunks or environment hash.
|
||||
|
||||
=head2 query_params
|
||||
|
||||
my $params = $req->query_params;
|
||||
|
||||
All C<GET> parameters, usually a L<Mojo::Parameters> object.
|
||||
|
||||
# Turn GET parameters to hash and extract value
|
||||
say $req->query_params->to_hash->{foo};
|
||||
|
||||
=head2 start_line_size
|
||||
|
||||
my $size = $req->start_line_size;
|
||||
|
||||
Size of the request-line in bytes. Note that this method finalizes the request.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
|
||||
|
||||
=cut
|
||||
315
database/perl/vendor/lib/Mojo/Message/Response.pm
vendored
Normal file
315
database/perl/vendor/lib/Mojo/Message/Response.pm
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
package Mojo::Message::Response;
|
||||
use Mojo::Base 'Mojo::Message';
|
||||
|
||||
use Mojo::Cookie::Response;
|
||||
use Mojo::Date;
|
||||
|
||||
has [qw(code message)];
|
||||
has max_message_size => sub { $ENV{MOJO_MAX_MESSAGE_SIZE} // 2147483648 };
|
||||
|
||||
# Unmarked codes are from RFC 7231
|
||||
my %MESSAGES = (
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
102 => 'Processing', # RFC 2518 (WebDAV)
|
||||
103 => 'Early Hints', # RFC 8297
|
||||
200 => 'OK',
|
||||
201 => 'Created',
|
||||
202 => 'Accepted',
|
||||
203 => 'Non-Authoritative Information',
|
||||
204 => 'No Content',
|
||||
205 => 'Reset Content',
|
||||
206 => 'Partial Content',
|
||||
207 => 'Multi-Status', # RFC 2518 (WebDAV)
|
||||
208 => 'Already Reported', # RFC 5842
|
||||
226 => 'IM Used', # RFC 3229
|
||||
300 => 'Multiple Choices',
|
||||
301 => 'Moved Permanently',
|
||||
302 => 'Found',
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
307 => 'Temporary Redirect',
|
||||
308 => 'Permanent Redirect', # RFC 7538
|
||||
400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
403 => 'Forbidden',
|
||||
404 => 'Not Found',
|
||||
405 => 'Method Not Allowed',
|
||||
406 => 'Not Acceptable',
|
||||
407 => 'Proxy Authentication Required',
|
||||
408 => 'Request Timeout',
|
||||
409 => 'Conflict',
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Request Entity Too Large',
|
||||
414 => 'Request-URI Too Long',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Request Range Not Satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
418 => "I'm a teapot", # RFC 2324 :)
|
||||
421 => 'Misdirected Request', # RFC 7540
|
||||
422 => 'Unprocessable Entity', # RFC 2518 (WebDAV)
|
||||
423 => 'Locked', # RFC 2518 (WebDAV)
|
||||
424 => 'Failed Dependency', # RFC 2518 (WebDAV)
|
||||
425 => 'Too Early', # RFC 8470
|
||||
426 => 'Upgrade Required', # RFC 2817
|
||||
428 => 'Precondition Required', # RFC 6585
|
||||
429 => 'Too Many Requests', # RFC 6585
|
||||
431 => 'Request Header Fields Too Large', # RFC 6585
|
||||
451 => 'Unavailable For Legal Reasons', # RFC 7725
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
503 => 'Service Unavailable',
|
||||
504 => 'Gateway Timeout',
|
||||
505 => 'HTTP Version Not Supported',
|
||||
506 => 'Variant Also Negotiates', # RFC 2295
|
||||
507 => 'Insufficient Storage', # RFC 2518 (WebDAV)
|
||||
508 => 'Loop Detected', # RFC 5842
|
||||
509 => 'Bandwidth Limit Exceeded', # Unofficial
|
||||
510 => 'Not Extended', # RFC 2774
|
||||
511 => 'Network Authentication Required' # RFC 6585
|
||||
);
|
||||
|
||||
sub cookies {
|
||||
my $self = shift;
|
||||
|
||||
# Parse cookies
|
||||
my $headers = $self->headers;
|
||||
return [@{Mojo::Cookie::Response->parse($headers->set_cookie)}] unless @_;
|
||||
|
||||
# Add cookies
|
||||
$headers->add('Set-Cookie' => "$_") for map { ref $_ eq 'HASH' ? Mojo::Cookie::Response->new($_) : $_ } @_;
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub default_message { $MESSAGES{$_[1] || $_[0]->code // 404} || '' }
|
||||
|
||||
sub extract_start_line {
|
||||
my ($self, $bufref) = @_;
|
||||
|
||||
# We have a full response line
|
||||
return undef unless $$bufref =~ s/^(.*?)\x0d?\x0a//;
|
||||
return !$self->error({message => 'Bad response start-line'}) unless $1 =~ m!^\s*HTTP/(\d\.\d)\s+(\d\d\d)\s*(.+)?$!;
|
||||
|
||||
my $content = $self->content;
|
||||
$content->skip_body(1) if $self->code($2)->is_empty;
|
||||
defined $content->$_ or $content->$_(1) for qw(auto_decompress auto_relax);
|
||||
return !!$self->version($1)->message($3);
|
||||
}
|
||||
|
||||
sub fix_headers {
|
||||
my $self = shift;
|
||||
$self->{fix} ? return $self : $self->SUPER::fix_headers(@_);
|
||||
|
||||
# Date
|
||||
my $headers = $self->headers;
|
||||
$headers->date(Mojo::Date->new->to_string) unless $headers->date;
|
||||
|
||||
# RFC 7230 3.3.2
|
||||
$headers->remove('Content-Length') if $self->is_empty;
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub get_start_line_chunk {
|
||||
my ($self, $offset) = @_;
|
||||
$self->_start_line->emit(progress => 'start_line', $offset);
|
||||
return substr $self->{start_buffer}, $offset, 131072;
|
||||
}
|
||||
|
||||
sub is_client_error { shift->_status_class(400) }
|
||||
|
||||
sub is_empty {
|
||||
my $self = shift;
|
||||
return undef unless my $code = $self->code;
|
||||
return $self->is_info || $code == 204 || $code == 304;
|
||||
}
|
||||
|
||||
sub is_error { shift->_status_class(400, 500) }
|
||||
sub is_info { shift->_status_class(100) }
|
||||
sub is_redirect { shift->_status_class(300) }
|
||||
sub is_server_error { shift->_status_class(500) }
|
||||
|
||||
sub is_success { shift->_status_class(200) }
|
||||
|
||||
sub start_line_size { length shift->_start_line->{start_buffer} }
|
||||
|
||||
sub _start_line {
|
||||
my $self = shift;
|
||||
|
||||
return $self if defined $self->{start_buffer};
|
||||
my $code = $self->code || 404;
|
||||
my $msg = $self->message || $self->default_message;
|
||||
$self->{start_buffer} = "HTTP/@{[$self->version]} $code $msg\x0d\x0a";
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub _status_class {
|
||||
my ($self, @classes) = @_;
|
||||
return undef unless my $code = $self->code;
|
||||
return !!grep { $code >= $_ && $code < ($_ + 100) } @classes;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Mojo::Message::Response - HTTP response
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Mojo::Message::Response;
|
||||
|
||||
# Parse
|
||||
my $res = Mojo::Message::Response->new;
|
||||
$res->parse("HTTP/1.0 200 OK\x0d\x0a");
|
||||
$res->parse("Content-Length: 12\x0d\x0a");
|
||||
$res->parse("Content-Type: text/plain\x0d\x0a\x0d\x0a");
|
||||
$res->parse('Hello World!');
|
||||
say $res->code;
|
||||
say $res->headers->content_type;
|
||||
say $res->body;
|
||||
|
||||
# Build
|
||||
my $res = Mojo::Message::Response->new;
|
||||
$res->code(200);
|
||||
$res->headers->content_type('text/plain');
|
||||
$res->body('Hello World!');
|
||||
say $res->to_string;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
L<Mojo::Message::Response> is a container for HTTP responses, based on L<RFC 7230|https://tools.ietf.org/html/rfc7230>
|
||||
and L<RFC 7231|https://tools.ietf.org/html/rfc7231>.
|
||||
|
||||
=head1 EVENTS
|
||||
|
||||
L<Mojo::Message::Response> inherits all events from L<Mojo::Message>.
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
L<Mojo::Message::Response> inherits all attributes from L<Mojo::Message> and implements the following new ones.
|
||||
|
||||
=head2 code
|
||||
|
||||
my $code = $res->code;
|
||||
$res = $res->code(200);
|
||||
|
||||
HTTP response status code.
|
||||
|
||||
=head2 max_message_size
|
||||
|
||||
my $size = $res->max_message_size;
|
||||
$res = $res->max_message_size(1024);
|
||||
|
||||
Maximum message size in bytes, defaults to the value of the C<MOJO_MAX_MESSAGE_SIZE> environment variable or
|
||||
C<2147483648> (2GiB). Setting the value to C<0> will allow messages of indefinite size.
|
||||
|
||||
=head2 message
|
||||
|
||||
my $msg = $res->message;
|
||||
$res = $res->message('OK');
|
||||
|
||||
HTTP response status message.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
L<Mojo::Message::Response> inherits all methods from L<Mojo::Message> and implements the following new ones.
|
||||
|
||||
=head2 cookies
|
||||
|
||||
my $cookies = $res->cookies;
|
||||
$res = $res->cookies(Mojo::Cookie::Response->new);
|
||||
$res = $res->cookies({name => 'foo', value => 'bar'});
|
||||
|
||||
Access response cookies, usually L<Mojo::Cookie::Response> objects.
|
||||
|
||||
# Names of all cookies
|
||||
say $_->name for @{$res->cookies};
|
||||
|
||||
=head2 default_message
|
||||
|
||||
my $msg = $res->default_message;
|
||||
my $msg = $res->default_message(418);
|
||||
|
||||
Generate default response message for status code, defaults to using L</"code">.
|
||||
|
||||
=head2 extract_start_line
|
||||
|
||||
my $bool = $res->extract_start_line(\$str);
|
||||
|
||||
Extract status-line from string.
|
||||
|
||||
=head2 fix_headers
|
||||
|
||||
$res = $res->fix_headers;
|
||||
|
||||
Make sure response has all required headers.
|
||||
|
||||
=head2 get_start_line_chunk
|
||||
|
||||
my $bytes = $res->get_start_line_chunk($offset);
|
||||
|
||||
Get a chunk of status-line data starting from a specific position. Note that this method finalizes the response.
|
||||
|
||||
=head2 is_client_error
|
||||
|
||||
my $bool = $res->is_client_error;
|
||||
|
||||
Check if this response has a C<4xx> status L</"code">.
|
||||
|
||||
=head2 is_empty
|
||||
|
||||
my $bool = $res->is_empty;
|
||||
|
||||
Check if this response has a C<1xx>, C<204> or C<304> status L</"code">.
|
||||
|
||||
=head2 is_error
|
||||
|
||||
my $bool = $res->is_error;
|
||||
|
||||
Check if this response has a C<4xx> or C<5xx> status L</"code">.
|
||||
|
||||
=head2 is_info
|
||||
|
||||
my $bool = $res->is_info;
|
||||
|
||||
Check if this response has a C<1xx> status L</"code">.
|
||||
|
||||
=head2 is_redirect
|
||||
|
||||
my $bool = $res->is_redirect;
|
||||
|
||||
Check if this response has a C<3xx> status L</"code">.
|
||||
|
||||
=head2 is_server_error
|
||||
|
||||
my $bool = $res->is_server_error;
|
||||
|
||||
Check if this response has a C<5xx> status L</"code">.
|
||||
|
||||
=head2 is_success
|
||||
|
||||
my $bool = $res->is_success;
|
||||
|
||||
Check if this response has a C<2xx> status L</"code">.
|
||||
|
||||
=head2 start_line_size
|
||||
|
||||
my $size = $req->start_line_size;
|
||||
|
||||
Size of the status-line in bytes. Note that this method finalizes the response.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user