Theo van Hoesel
and 1 contributors

NAME

HTTP::Method - HTTP Request Method and Common Properties according to RFC 7231

VERSION

Version 0.01

SYNOPSIS

    use HTTP::Method;
    
    # prefered instantiation
    my $get_mth = HTTP::Method->GET;
    
    # or from string
    my $str_mth = HTTP::Method->new(uc 'get');
    
    # testing
    if ( $mth->is_GET ) { ... }
    
    # introspection
    $mth->is_method_safe;

or more intuative (and less strict!)

    use HTTP::Method ':case-insesitive';
    
    my $mth = HTTP::Method->new($str);
    printf "%s %s return the payload",
        $mth,
        $mth->is_head ? "does NOT" : "does";
                                    # "GET does return the payload"
                                    # "HEAD does NOT return the payload"

DESCRIPTION

There is a lot to say about HTTP Methods in RFC 7231 Section 4. Request Methods. Most of the developers make the wrong assumption that it is just a 'uppercase string'. This module will help writing better code as it does validation and ensures right capitalization for the HTTP Method names.

As one could read in RFC 7231 Section 4.2 Common Method Properties HTTP Methods do have properties and can be divided in: Safe Methods, Idempotent Methods and Cacheable Methods. These properties are just predicate methods on a HTTP::Method object

CLASS METHODS

import

Called when module is being used. This is used to set case-sensitivity.

    use HTTP::Method ':case-insensitive';

such that:

    my $str = 'get';                # or result from functioncall
    
    my $mth = HTTP::Method->new($str);
                                    # do not need to make uppercase
    
    my $del = HTTP::Method->DEL;    # prefer uppercase
    
    print $mth if $mth->is_get;     # prints "GET"
                                    # predicate method is lowercase

new

Creates a new HTTP::Method object. It takes only 1 argument, a HTTP-METHOD-NAME. It must be one of the methods defined in RFC 7231, SECTION 4.3. Method Definitions. Valid names are: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS and TRACE and additionally PATCH.

If used with :case-insensitive one can use lowercase names as well.

METHODS

is_method_safe

From "RFC 7231 Section 4.2.1. Safe Methods"

Request methods are considered "safe" if their defined semantics are essentially read-only; i.e., the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource. Likewise, reasonable use of a safe method is not expected to cause any harm, loss of property, or unusual burden on the origin server.

is_method_idempotent

From "RFC 7231 Section 4.2.2. Idempotent Methods"

A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request. Of the request methods defined by this specification, PUT, DELETE, and safe request methods are idempotent.

is_method_cachable

From "RFC 7231 Section 4.2.2. Cachable Methods"

Request methods can be defined as "cacheable" to indicate that responses to them are allowed to be stored for future reuse; for specific requirements see [RFC7234]. In general, safe methods that do not depend on a current or authoritative response are defined as cacheable; this specification defines GET, HEAD, and POST as cacheable, although the overwhelming majority of cache implementations only support GET and HEAD.

ALTERNATIVE INSTANTIATION

HTTP::Method objects have an alternative way of instantiation. These help building more robust code. You can use HTTP::Method::HTTP-METHODE-NAME() for most HTTP methods like

    my $mth = HTTP::Method::HTTP-METHOD-NAME();
                                    # non OOP

use the OOP constructors:

    my $mth = HTTP::Method->HTTP-METHOD-NAME
                                    # prefered way

instead of

    my $mth = HTTP::Method->new(uc 'http-method-name')
                                    # don't do this

The list below shows which are available:

HTTP::Method::CONNECT
HTTP::Method::DELETE
HTTP::Method::GET
HTTP::Method::HEAD
HTTP::Method::OPTIONS
HTTP::Method::PATCH
HTTP::Method::POST
HTTP::Method::PUT
HTTP::Method::TRACE

CAVEATS

Case-Insensitive

According to RFC 7231, SECTION 4.1 method tokens are case sensitive, unlike what most developers think it is. This might be surprising and will become very inconvenient if we had to think about it too much.

    use HTTP::Method ':case-insensitive';

Using the module this way will make it behave like we are most familiar with.

HTTP::Method->new($string) creates a new HTTP::Method object that will always have an uppercase name.

$mth = HTTP::Method->HTTP-METHOD-NAME factory methods will be uppercased.

$mth->is_http-method-name predicate methods are lowercased

"$mth" always stringfies to uppercase

If one does NOT use the import ':case-insensitive' The above behaviour will not be swithced on, resulting in some surprises

    my $str = 'get';
    
    my $mth = HTTP::Method->new($str);
                                    # croak "unknown method"
                                    # only uppercase http-method-names
    
    warn "case-sensitive" if $mth ne HTTP::Method->GET;
                                    # $mth stringifies to original $str
                                    # HTTP::Method->GET eq "GET"
    
    $mth->is_get;                   # undefined method
                                    # predicates are spelled according
                                    # to normilization, uppercase
                                    #
                                    # $mth eq "get"
    
    $mth->is_GET;                   # undef
                                    # the internal token is lowercase
    
    $mth->is_method_cachable        # undef
                                    # 'get' is unknown to the RFC

Most of those could had been solved with passin in the right arument into the constructor, using uc like in

    my $mth = HTTP::Method->new(uc $str);
    
    print "$mth";                   # GET
    $mth->is_GET;                   # 1
    $mth->is_method_cachable;       # 1

ACKNOWLEDGEMENTS

Thank you Adam for inspiring me to write better readable code (don't look inside the source!)

AUTHOR

Th. J. van Hoesel

SEE ALSO

RFC-7231