Initial Commit
This commit is contained in:
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