Blame lib/HTTP/Status.pm

Packit a09cf7
package HTTP::Status;
Packit a09cf7
Packit a09cf7
use strict;
Packit a09cf7
use warnings;
Packit a09cf7
Packit a09cf7
our $VERSION = '6.18';
Packit a09cf7
Packit a09cf7
require 5.002;   # because we use prototypes
Packit a09cf7
Packit a09cf7
use base 'Exporter';
Packit a09cf7
our @EXPORT = qw(is_info is_success is_redirect is_error status_message);
Packit a09cf7
our @EXPORT_OK = qw(is_client_error is_server_error is_cacheable_by_default);
Packit a09cf7
Packit a09cf7
# Note also addition of mnemonics to @EXPORT below
Packit a09cf7
Packit a09cf7
# Unmarked codes are from RFC 7231 (2017-12-20)
Packit a09cf7
# See also:
Packit a09cf7
# https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
Packit a09cf7
Packit a09cf7
my %StatusCode = (
Packit a09cf7
    100 => 'Continue',
Packit a09cf7
    101 => 'Switching Protocols',
Packit a09cf7
    102 => 'Processing',                      # RFC 2518: WebDAV
Packit a09cf7
    103 => 'Early Hints',                     # RFC 8297: Indicating Hints
Packit a09cf7
#   104 .. 199
Packit a09cf7
    200 => 'OK',
Packit a09cf7
    201 => 'Created',
Packit a09cf7
    202 => 'Accepted',
Packit a09cf7
    203 => 'Non-Authoritative Information',
Packit a09cf7
    204 => 'No Content',
Packit a09cf7
    205 => 'Reset Content',
Packit a09cf7
    206 => 'Partial Content',                 # RFC 7233: Range Requests
Packit a09cf7
    207 => 'Multi-Status',                    # RFC 4918: WebDAV
Packit a09cf7
    208 => 'Already Reported',                # RFC 5842: WebDAV bindings
Packit a09cf7
#   209 .. 225
Packit a09cf7
    226 => 'IM used',                         # RFC 3229: Delta encoding
Packit a09cf7
#   227 .. 299
Packit a09cf7
    300 => 'Multiple Choices',
Packit a09cf7
    301 => 'Moved Permanently',
Packit a09cf7
    302 => 'Found',
Packit a09cf7
    303 => 'See Other',
Packit a09cf7
    304 => 'Not Modified',                    # RFC 7232: Conditional Request
Packit a09cf7
    305 => 'Use Proxy',
Packit a09cf7
    307 => 'Temporary Redirect',
Packit a09cf7
    308 => 'Permanent Redirect',              # RFC 7528: Permanent Redirect
Packit a09cf7
#   309 .. 399
Packit a09cf7
    400 => 'Bad Request',
Packit a09cf7
    401 => 'Unauthorized',                    # RFC 7235: Authentication
Packit a09cf7
    402 => 'Payment Required',
Packit a09cf7
    403 => 'Forbidden',
Packit a09cf7
    404 => 'Not Found',
Packit a09cf7
    405 => 'Method Not Allowed',
Packit a09cf7
    406 => 'Not Acceptable',
Packit a09cf7
    407 => 'Proxy Authentication Required',   # RFC 7235: Authentication
Packit a09cf7
    408 => 'Request Timeout',
Packit a09cf7
    409 => 'Conflict',
Packit a09cf7
    410 => 'Gone',
Packit a09cf7
    411 => 'Length Required',
Packit a09cf7
    412 => 'Precondition Failed',             # RFC 7232: Conditional Request
Packit a09cf7
    413 => 'Request Entity Too Large',
Packit a09cf7
    414 => 'Request-URI Too Large',
Packit a09cf7
    415 => 'Unsupported Media Type',
Packit a09cf7
    416 => 'Request Range Not Satisfiable',   # RFC 7233: Range Requests
Packit a09cf7
    417 => 'Expectation Failed',
Packit a09cf7
#   418 .. 420
Packit a09cf7
    421 => 'Misdirected Request',             # RFC 7540: HTTP/2
Packit a09cf7
    422 => 'Unprocessable Entity',            # RFC 4918: WebDAV
Packit a09cf7
    423 => 'Locked',                          # RFC 4918: WebDAV
Packit a09cf7
    424 => 'Failed Dependency',               # RFC 4918: WebDAV
Packit a09cf7
#   425
Packit a09cf7
    426 => 'Upgrade Required',
Packit a09cf7
#   427
Packit a09cf7
    428 => 'Precondition Required',           # RFC 6585: Additional Codes
Packit a09cf7
    429 => 'Too Many Requests',               # RFC 6585: Additional Codes
Packit a09cf7
#   430
Packit a09cf7
    431 => 'Request Header Fields Too Large', # RFC 6585: Additional Codes
Packit a09cf7
#   432 .. 450
Packit a09cf7
    451 => 'Unavailable For Legal Reasons',   # RFC 7724: Legal Obstacles
Packit a09cf7
#   452 .. 499
Packit a09cf7
    500 => 'Internal Server Error',
Packit a09cf7
    501 => 'Not Implemented',
Packit a09cf7
    502 => 'Bad Gateway',
Packit a09cf7
    503 => 'Service Unavailable',
Packit a09cf7
    504 => 'Gateway Timeout',
Packit a09cf7
    505 => 'HTTP Version Not Supported',
Packit a09cf7
    506 => 'Variant Also Negotiates',         # RFC 2295: Transparant Ngttn
Packit a09cf7
    507 => 'Insufficient Storage',            # RFC 4918: WebDAV
Packit a09cf7
    508 => 'Loop Detected',                   # RFC 5842: WebDAV bindings
Packit a09cf7
#   509
Packit a09cf7
    510 => 'Not Extended',                    # RFC 2774: Extension Framework
Packit a09cf7
    511 => 'Network Authentication Required', # RFC 6585: Additional Codes
Packit a09cf7
);
Packit a09cf7
Packit a09cf7
# keep some unofficial codes that used to be in this distribution
Packit a09cf7
%StatusCode = (
Packit a09cf7
    %StatusCode,
Packit a09cf7
    418 => 'I\'m a teapot',                   # RFC 2324: HTCPC/1.0  1-april
Packit a09cf7
    425 => 'Unordered Collection',            #           WebDAV Draft
Packit a09cf7
    449 => 'Retry with',                      #           microsoft
Packit a09cf7
    509 => 'Bandwidth Limit Exceeded',        #           Apache / cPanel
Packit a09cf7
);
Packit a09cf7
Packit a09cf7
my $mnemonicCode = '';
Packit a09cf7
my ($code, $message);
Packit a09cf7
while (($code, $message) = each %StatusCode) {
Packit a09cf7
    # create mnemonic subroutines
Packit a09cf7
    $message =~ s/I'm/I am/;
Packit a09cf7
    $message =~ tr/a-z \-/A-Z__/;
Packit a09cf7
    $mnemonicCode .= "sub HTTP_$message () { $code }\n";
Packit a09cf7
    $mnemonicCode .= "*RC_$message = \\&HTTP_$message;\n";  # legacy
Packit a09cf7
    $mnemonicCode .= "push(\@EXPORT_OK, 'HTTP_$message');\n";
Packit a09cf7
    $mnemonicCode .= "push(\@EXPORT, 'RC_$message');\n";
Packit a09cf7
}
Packit a09cf7
eval $mnemonicCode; # only one eval for speed
Packit a09cf7
die if $@;
Packit a09cf7
Packit a09cf7
# backwards compatibility
Packit a09cf7
*RC_MOVED_TEMPORARILY = \&RC_FOUND;  # 302 was renamed in the standard
Packit a09cf7
push(@EXPORT, "RC_MOVED_TEMPORARILY");
Packit a09cf7
Packit a09cf7
*RC_NO_CODE = \&RC_UNORDERED_COLLECTION;
Packit a09cf7
push(@EXPORT, "RC_NO_CODE");
Packit a09cf7
Packit a09cf7
our %EXPORT_TAGS = (
Packit a09cf7
   constants => [grep /^HTTP_/, @EXPORT_OK],
Packit a09cf7
   is => [grep /^is_/, @EXPORT, @EXPORT_OK],
Packit a09cf7
);
Packit a09cf7
Packit a09cf7
Packit a09cf7
sub status_message  ($) { $StatusCode{$_[0]}; }
Packit a09cf7
Packit a09cf7
sub is_info                 ($) { $_[0] && $_[0] >= 100 && $_[0] < 200; }
Packit a09cf7
sub is_success              ($) { $_[0] && $_[0] >= 200 && $_[0] < 300; }
Packit a09cf7
sub is_redirect             ($) { $_[0] && $_[0] >= 300 && $_[0] < 400; }
Packit a09cf7
sub is_error                ($) { $_[0] && $_[0] >= 400 && $_[0] < 600; }
Packit a09cf7
sub is_client_error         ($) { $_[0] && $_[0] >= 400 && $_[0] < 500; }
Packit a09cf7
sub is_server_error         ($) { $_[0] && $_[0] >= 500 && $_[0] < 600; }
Packit a09cf7
sub is_cacheable_by_default ($) { $_[0] && ( $_[0] == 200 # OK
Packit a09cf7
                                          || $_[0] == 203 # Non-Authoritative Information
Packit a09cf7
                                          || $_[0] == 204 # No Content
Packit a09cf7
                                          || $_[0] == 206 # Not Acceptable
Packit a09cf7
                                          || $_[0] == 300 # Multiple Choices
Packit a09cf7
                                          || $_[0] == 301 # Moved Permanently
Packit a09cf7
                                          || $_[0] == 404 # Not Found
Packit a09cf7
                                          || $_[0] == 405 # Method Not Allowed
Packit a09cf7
                                          || $_[0] == 410 # Gone
Packit a09cf7
                                          || $_[0] == 414 # Request-URI Too Large
Packit a09cf7
                                          || $_[0] == 451 # Unavailable For Legal Reasons
Packit a09cf7
                                          || $_[0] == 501 # Not Implemented
Packit a09cf7
                                            );
Packit a09cf7
}
Packit a09cf7
Packit a09cf7
1;
Packit a09cf7
Packit a09cf7
=pod
Packit a09cf7
Packit a09cf7
=encoding UTF-8
Packit a09cf7
Packit a09cf7
=head1 NAME
Packit a09cf7
Packit a09cf7
HTTP::Status - HTTP Status code processing
Packit a09cf7
Packit a09cf7
=head1 VERSION
Packit a09cf7
Packit a09cf7
version 6.18
Packit a09cf7
Packit a09cf7
=head1 SYNOPSIS
Packit a09cf7
Packit a09cf7
 use HTTP::Status qw(:constants :is status_message);
Packit a09cf7
Packit a09cf7
 if ($rc != HTTP_OK) {
Packit a09cf7
     print status_message($rc), "\n";
Packit a09cf7
 }
Packit a09cf7
Packit a09cf7
 if (is_success($rc)) { ... }
Packit a09cf7
 if (is_error($rc)) { ... }
Packit a09cf7
 if (is_redirect($rc)) { ... }
Packit a09cf7
Packit a09cf7
=head1 DESCRIPTION
Packit a09cf7
Packit a09cf7
I<HTTP::Status> is a library of routines for defining and
Packit a09cf7
classifying HTTP status codes for libwww-perl.  Status codes are
Packit a09cf7
used to encode the overall outcome of an HTTP response message.  Codes
Packit a09cf7
correspond to those defined in RFC 2616 and RFC 2518.
Packit a09cf7
Packit a09cf7
=head1 CONSTANTS
Packit a09cf7
Packit a09cf7
The following constant functions can be used as mnemonic status code
Packit a09cf7
names.  None of these are exported by default.  Use the C<:constants>
Packit a09cf7
tag to import them all.
Packit a09cf7
Packit a09cf7
   HTTP_CONTINUE                        (100)
Packit a09cf7
   HTTP_SWITCHING_PROTOCOLS             (101)
Packit a09cf7
   HTTP_PROCESSING                      (102)
Packit a09cf7
   HTTP_EARLY_HINTS                     (103)
Packit a09cf7
Packit a09cf7
   HTTP_OK                              (200)
Packit a09cf7
   HTTP_CREATED                         (201)
Packit a09cf7
   HTTP_ACCEPTED                        (202)
Packit a09cf7
   HTTP_NON_AUTHORITATIVE_INFORMATION   (203)
Packit a09cf7
   HTTP_NO_CONTENT                      (204)
Packit a09cf7
   HTTP_RESET_CONTENT                   (205)
Packit a09cf7
   HTTP_PARTIAL_CONTENT                 (206)
Packit a09cf7
   HTTP_MULTI_STATUS                    (207)
Packit a09cf7
   HTTP_ALREADY_REPORTED                (208)
Packit a09cf7
Packit a09cf7
   HTTP_IM_USED                         (226)
Packit a09cf7
Packit a09cf7
   HTTP_MULTIPLE_CHOICES                (300)
Packit a09cf7
   HTTP_MOVED_PERMANENTLY               (301)
Packit a09cf7
   HTTP_FOUND                           (302)
Packit a09cf7
   HTTP_SEE_OTHER                       (303)
Packit a09cf7
   HTTP_NOT_MODIFIED                    (304)
Packit a09cf7
   HTTP_USE_PROXY                       (305)
Packit a09cf7
   HTTP_TEMPORARY_REDIRECT              (307)
Packit a09cf7
   HTTP_PERMANENT_REDIRECT              (308)
Packit a09cf7
Packit a09cf7
   HTTP_BAD_REQUEST                     (400)
Packit a09cf7
   HTTP_UNAUTHORIZED                    (401)
Packit a09cf7
   HTTP_PAYMENT_REQUIRED                (402)
Packit a09cf7
   HTTP_FORBIDDEN                       (403)
Packit a09cf7
   HTTP_NOT_FOUND                       (404)
Packit a09cf7
   HTTP_METHOD_NOT_ALLOWED              (405)
Packit a09cf7
   HTTP_NOT_ACCEPTABLE                  (406)
Packit a09cf7
   HTTP_PROXY_AUTHENTICATION_REQUIRED   (407)
Packit a09cf7
   HTTP_REQUEST_TIMEOUT                 (408)
Packit a09cf7
   HTTP_CONFLICT                        (409)
Packit a09cf7
   HTTP_GONE                            (410)
Packit a09cf7
   HTTP_LENGTH_REQUIRED                 (411)
Packit a09cf7
   HTTP_PRECONDITION_FAILED             (412)
Packit a09cf7
   HTTP_REQUEST_ENTITY_TOO_LARGE        (413)
Packit a09cf7
   HTTP_REQUEST_URI_TOO_LARGE           (414)
Packit a09cf7
   HTTP_UNSUPPORTED_MEDIA_TYPE          (415)
Packit a09cf7
   HTTP_REQUEST_RANGE_NOT_SATISFIABLE   (416)
Packit a09cf7
   HTTP_EXPECTATION_FAILED              (417)
Packit a09cf7
   HTTP_MISDIRECTED REQUEST             (421)
Packit a09cf7
   HTTP_UNPROCESSABLE_ENTITY            (422)
Packit a09cf7
   HTTP_LOCKED                          (423)
Packit a09cf7
   HTTP_FAILED_DEPENDENCY               (424)
Packit a09cf7
   HTTP_UPGRADE_REQUIRED                (426)
Packit a09cf7
   HTTP_PRECONDITION_REQUIRED           (428)
Packit a09cf7
   HTTP_TOO_MANY_REQUESTS               (429)
Packit a09cf7
   HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE (431)
Packit a09cf7
   HTTP_UNAVAILABLE_FOR_LEGAL_REASONS   (451)
Packit a09cf7
Packit a09cf7
   HTTP_INTERNAL_SERVER_ERROR           (500)
Packit a09cf7
   HTTP_NOT_IMPLEMENTED                 (501)
Packit a09cf7
   HTTP_BAD_GATEWAY                     (502)
Packit a09cf7
   HTTP_SERVICE_UNAVAILABLE             (503)
Packit a09cf7
   HTTP_GATEWAY_TIMEOUT                 (504)
Packit a09cf7
   HTTP_HTTP_VERSION_NOT_SUPPORTED      (505)
Packit a09cf7
   HTTP_VARIANT_ALSO_NEGOTIATES         (506)
Packit a09cf7
   HTTP_INSUFFICIENT_STORAGE            (507)
Packit a09cf7
   HTTP_LOOP_DETECTED                   (508)
Packit a09cf7
   HTTP_NOT_EXTENDED                    (510)
Packit a09cf7
   HTTP_NETWORK_AUTHENTICATION_REQUIRED (511)
Packit a09cf7
Packit a09cf7
=head1 FUNCTIONS
Packit a09cf7
Packit a09cf7
The following additional functions are provided.  Most of them are
Packit a09cf7
exported by default.  The C<:is> import tag can be used to import all
Packit a09cf7
the classification functions.
Packit a09cf7
Packit a09cf7
=over 4
Packit a09cf7
Packit a09cf7
=item status_message( $code )
Packit a09cf7
Packit a09cf7
The status_message() function will translate status codes to human
Packit a09cf7
readable strings. The string is the same as found in the constant
Packit a09cf7
names above. If the $code is not registered in the L
Packit a09cf7
Codes|https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml>
Packit a09cf7
then C<undef> is returned. 
Packit a09cf7
Packit a09cf7
=item is_info( $code )
Packit a09cf7
Packit a09cf7
Return TRUE if C<$code> is an I<Informational> status code (1xx).  This
Packit a09cf7
class of status code indicates a provisional response which can't have
Packit a09cf7
any content.
Packit a09cf7
Packit a09cf7
=item is_success( $code )
Packit a09cf7
Packit a09cf7
Return TRUE if C<$code> is a I<Successful> status code (2xx).
Packit a09cf7
Packit a09cf7
=item is_redirect( $code )
Packit a09cf7
Packit a09cf7
Return TRUE if C<$code> is a I<Redirection> status code (3xx). This class of
Packit a09cf7
status code indicates that further action needs to be taken by the
Packit a09cf7
user agent in order to fulfill the request.
Packit a09cf7
Packit a09cf7
=item is_error( $code )
Packit a09cf7
Packit a09cf7
Return TRUE if C<$code> is an I<Error> status code (4xx or 5xx).  The function
Packit a09cf7
returns TRUE for both client and server error status codes.
Packit a09cf7
Packit a09cf7
=item is_client_error( $code )
Packit a09cf7
Packit a09cf7
Return TRUE if C<$code> is a I<Client Error> status code (4xx). This class
Packit a09cf7
of status code is intended for cases in which the client seems to have
Packit a09cf7
erred.
Packit a09cf7
Packit a09cf7
This function is B<not> exported by default.
Packit a09cf7
Packit a09cf7
=item is_server_error( $code )
Packit a09cf7
Packit a09cf7
Return TRUE if C<$code> is a I<Server Error> status code (5xx). This class
Packit a09cf7
of status codes is intended for cases in which the server is aware
Packit a09cf7
that it has erred or is incapable of performing the request.
Packit a09cf7
Packit a09cf7
This function is B<not> exported by default.
Packit a09cf7
Packit a09cf7
=item is_cacheable_by_default( $code )
Packit a09cf7
Packit a09cf7
Return TRUE if C<$code> indicates that a response is cacheable by default, and
Packit a09cf7
it can be reused by a cache with heuristic expiration. All other status codes
Packit a09cf7
are not cacheable by default. See L
Packit a09cf7
Section 6.1. Overview of Status Codes|https://tools.ietf.org/html/rfc7231#section-6.1>.
Packit a09cf7
Packit a09cf7
This function is B<not> exported by default.
Packit a09cf7
Packit a09cf7
=back
Packit a09cf7
Packit a09cf7
=head1 SEE ALSO
Packit a09cf7
Packit a09cf7
L<IANA HTTP Status Codes|https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml>
Packit a09cf7
Packit a09cf7
=head1 BUGS
Packit a09cf7
Packit a09cf7
For legacy reasons all the C<HTTP_> constants are exported by default
Packit a09cf7
with the prefix C<RC_>.  It's recommended to use explicit imports and
Packit a09cf7
the C<:constants> tag instead of relying on this.
Packit a09cf7
Packit a09cf7
=head1 AUTHOR
Packit a09cf7
Packit a09cf7
Gisle Aas <gisle@activestate.com>
Packit a09cf7
Packit a09cf7
=head1 COPYRIGHT AND LICENSE
Packit a09cf7
Packit a09cf7
This software is copyright (c) 1994-2017 by Gisle Aas.
Packit a09cf7
Packit a09cf7
This is free software; you can redistribute it and/or modify it under
Packit a09cf7
the same terms as the Perl 5 programming language system itself.
Packit a09cf7
Packit a09cf7
=cut
Packit a09cf7
Packit a09cf7
__END__
Packit a09cf7
Packit a09cf7
Packit a09cf7
#ABSTRACT: HTTP Status code processing