Tools for working with HTTP message headers
Other
Switch branches/tags
Nothing to show

README.md

TITLE

HTTP::Headers

SUBTITLE

Tools for working with HTTP message headers

SYNOPSIS

use HTTP::Headers;
my $headers = HTTP::Headers.new;
$headers.Content-Type = 'text/html';
$headers.Content-Type.charset = "UTF-8";
$headers.Content-Length = $content.encode.bytes;

my $CRLF = "\x0d\x0a";
print "200 OK$CRLF;
print $headers.as-string(:eol($CRLF));
print $CRLF;
print $content;

DESCRIPTION

This module provides convenient tools for working with HTTP headers. An emphasis has been placed on making it easy to use in a way that helps catch errors early. It has also been built for extensibility.

Methods

method new

method new(Bool :$quiet)

Constructs a new object for working with headers. The :$quiet option can be used to suppress all warnings normally generated by this object.

method header

multi method header(HTTP::Header::Standard::Name $name) is rw returns HTTP::Header
multi method header(Str $name) is rw returns HTTP::Header

This method is writable and allows the use of either the values in the HTTP::Header::Standard::Name enumeration or string values. In general, you should not use strings when you can use the enumeration in your code. By using the enumeration, you can find typos and other errors more quickly.

$headers.header(Content-MIME-Type); # I forgot it's just Content-Type
# Undeclared name:
#     Content-MIME-Type used at line 1

The library will remind you of this best practice if you use a string when you could use an enumeration:

$headers.header("Content-Type");
# Calling .header(Content-Type) is preferred to .header("Content-Type") for standard HTTP headers.

If you don't want to see these, you can ask the object or the method to be quiet:

$headers.header("Content-Type", :quiet);
# OR during construction
my $headers = HTTP::Headers.new(:$quiet);

When setting values on a header, you may set either a single or multiples.

$headers.header(Content-Length) = 42;
$headers.header(Accept) = "text/html", "text/*", "*/*";
say $headers.as-string;
# Accept: text/html
# Accept: text/*
# Accept: */*
# Content-Length: 42

By setting with a comma, you will generate multiple headers.

You may also set headers with DateTime, Instant, and Duration objects and it should do the right thing. For example,

$headers.header(Date)        = DateTime.now;
$headers.header(Retry-After) = Duration.new(120);
say $headers.as-string;
# Date: Thu, 14 May 2015 09:48:00 GMT
# Retry-After: 120

When you read a header, the value returns is a HTTP::Header object.

my HTTP::Header $ct = $headers.header(Content-Type);
my HTTP::Header $xf = $headers.header("X-Foo-Custom");

This object stringifies to the value of the header (with multiple values being joined together using a comma, safe according to RFC). It also provides a bunch of additional tools for working with and manipulating the header. For example:

$headers.header(Accept).push: "text/css", "text/js";
$headers.header(Content-Type).charset = "UTF-8";

See HTTP::Header for details.

method remove-header

multi method remove-header($name) returns HTTP::Header
multi method remove-headers(*@names) returns List

These methods will remove headers from the list. The removed HTTP::Header object is returned.

method remove-content-headers

method remove-content-headers

This method removes all the entity headers:

Allow Content-Encoding Content-Language Content-Length
Content-Location Content-MD5 Content-Range Content-Type
Expires Last-Modified

as well as any that start with "Content-".

method clear

method clear

This removes all headers.

method clone

method clone

This performs a deep clone of the object.

method list

method list

This returns all the headers stored in this object, sorted according to the RFC recommendation (general headers first, then request/response headers, then entity/content headers, and finally custom headers).

method for

method for(&code)

Provides a way to iterate over all the headers in the object.

method as-string

method as-string(:$eol = "\n")

Returns the headers for output using the given line separator. If no line separator is given, "\n" is used.

method Str

method Str returns Str

This calls [/method as-string](/method as-string) with no arguments.

method for-PSGI

method for-PSGI returns List

This returns the headers formatted for output from a PSGI application, as an array of Pairs.

Hash-like Operations

You can also treat HTTP::Headers like a hash in some ways. These are experimental and might be removed or changed in the future.

method postcircumfix:<{ }>

method postcircumfix:<{ }>($key)

This may be used to return or assign a head value.

adverb :delete

This may be used to delete headers.

adverb :exists

This may be used to check to see if a head is set.

Convenience Methods

The following methods are provided as a shortcut for [/method header](/method header) and can be used as an accessor or mutator.

# General Headers
method Cache-Control is rw
method Connection is rw
method Date is rw
method Pragma is rw
method Trailer is rw
method Transfer-Encoding is rw
method Upgrade is rw
method Via is rw
method Warning is rw

# Request Headers
method Accept is rw
method Accept-Charset is rw
method Accept-Encoding is rw
method Accept-Language is rw
method Authorization is rw
method Expect is rw
method From is rw
method Host is rw
method If-Match is rw
method If-Modified-Since is rw
method If-None-Match is rw
method If-Range is rw
method If-Unmodified-Since is rw
method Max-Forwards is rw
method Proxy-Authorization is rw
method Range is rw
method Referer is rw
method TE is rw
method User-Agent is rw

# Response Headers
method Accept-Ranges is rw
method Age is rw
method ETag is rw
method Location is rw
method Proxy-Authenticate is rw
method Retry-After is rw
method Server is rw
method Vary is rw
method WWW-Authenticate is rw

# Entity Headers
method Allow is rw
method Content-Encoding is rw
method Content-Language is rw
method Content-Length is rw
method Content-Location is rw
method Content-MD5 is rw
method Content-Range is rw
method Content-Type is rw
method Expires is rw
method Last-Modified is rw

Extending HTTP::Headers

It is possible to create a sub-class of HTTP::Headers more suited to your application. As a simplistic example, here's a customization that provides two new custom headers named "X-Foo" and "X-Bar" which have a default column setting of 42 when used.

class MyApp::CustomHeaders is HTTP::Headers {
    enum MyAppHeader < X-Foo X-Bar >;

    method build-header($name, *@values) {
        if $name ~~ MyAppHeader {
            HTTP::Header::Custom.new(:name($name.Str), :42values);
        }
        else {
            nextsame;
        }
    }

    multi method header(MyAppHeader $name) is rw {
        self.header-proxy($name);
    }

    method X-Foo is rw { self.header(MyAppHeader::X-Foo) }
    method X-Bar is rw { self.header(MyAppHeader::X-Bar) }
}

Here is a description of the methods you'll need to consider in doing this.

method build-header

method build-header($name, *@values) returns HTTP::Header

This is a factory method used to decide how to build the headers being stored. Here is the place where you'll want to add custom roles to your headers, instantiate any custom implementations of HTTP::Header, etc.

It is recommended that you define it to build what you need and then use nextsame to handle all the remaining cases.

method header-proxy

method header-proxy($name) returns Proxy

This is a handy helper that allows you to easily build your own custom version of [/method header](/method header). It returns a Proxy useful for building is rw methods similar to those in HTTP::Headers.