txt: ## dist_cpan-HANENKAMP-HTTP-Headers.md
  # TITLE
  
  HTTP::Headers
  
  # SUBTITLE
  
  Tools for working with HTTP message headers
  
  # SYNOPSIS
  
  ```
  use HTTP::Headers :standard-names;
  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(HTTP::Headers:U: @headers, Bool:D :$quiet = False --> HTTP::Headers:D)
  method new(HTTP::Headers:U: %headers, Bool:D :$quiet = False --> HTTP::Headers:D)
  method new(HTTP::Headers:U: Bool:D :$quiet = False, *@headers, *%headers --> HTTP::Headers:D)
  
  ```
  
  Constructs a new object for working with headers. The `:$quiet` option can be used to suppress all warnings normally generated by this object.
  
  The various `%headers` and `@headers` methods can be used to initialize the object from a list of pairs:
  
  ```
  my $headers = HTTP::Headers.new:
      ::(Content-Type)   => 'text/html',
      ::(Content-Length) => 42,
      'X-Requested-With' => 'XMLHTTPRequest',
      ;
  
  ```
  
  ## method headers
  
  ```
  multi method headers(HTTP::Headers:D: Pair:D @headers)
  multi method headers(HTTP::Headers:D: %headers)
  multi method headers(HTTP::Headers:D: *@headers, *%headers)
  
  ```
  
  Sets all the headers given as pairs or named parameters.
  
  ## method header
  
  ```
  multi method header(HTTP::Headers:D: HTTP::Header::Standard::Name $name --> HTTP::Header) is rw
  multi method header(HTTP::Headers:D: Str $name --> HTTP::Header) is rw
  
  ```
  
  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 discover typos at compile time.
  
  ```
  use HTTP::Headers :standard-names;
  $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](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](http::Header) for details.
  
  ## method remove-header
  
  ```
  multi method remove-header(HTTP::Header:D: $name --> HTTP::Header)
  multi method remove-header(HTTP::Header:D: *@names --> List)
  
  ```
  
  These method will remove headers from the list. The removed [HTTP::Header](http::Header) object is returned.
  
  ## method remove-content-headers
  
  ```
  method remove-content-headers(HTTP::Headers:D: --> List)
  
  ```
  
  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(HTTP::Headers:D:)
  
  ```
  
  This removes all headers.
  
  ## method clone
  
  ```
  method clone(HTTP::Headers:D: --> HTTP::Headers:D)
  
  ```
  
  This performs a deep clone of the object.
  
  ## method sorted-headers
  
  ```
  method sorted-headers(HTTP::Headers:D: --> Seq)
  
  ```
  
  Returns all [HTTP::Header](http::Header) objcts in a sequence sorted by header name.
  
  ## method list
  
  ```
  method list(HTTP::Headers:D: --> 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 map
  
  ```
  method map(HTTP::Headers:D: &code --> Seq)
  
  ```
  
  Provides a way to iterate over all the headers in the object.
  
  ## method as-string
  
  ```
  method as-string(HTTP::Headers:D: Str:D :$eol = "\n" --> Str)
  
  ```
  
  Returns the headers for output using the given line separator. If no line separator is given, "\n" is used.
  
  ## method Str
  
  ```
  multi method Str(:$eol = "\n") returns Str
  
  ```
  
  This calls [/method as-string](/method as-string) with the given arguments.
  
  ## method for-WAPI
  
  ```
  method for-WAPI(HTTP::Headers:D: --> List:D)
  
  ```
  
  This returns the headers formatted for output from a RakuWAPI application, as an array of Pairs.
  
  # Hash-like Operations
  
  You can also treat [HTTP::Headers](http::Headers) like a hash in some ways. These are **experimental** and might be removed or changed in the future.
  
  ## method postcircumfix:<{ }>
  
  ```
  multi method postcircumfix:<{ }>(HTTP::Headers:D: Str:D $key --> HTTP::Header)
  multi method postcircumfix:<{ }>(HTTP::Headers:D: HTTP::Header::Standard::Name:D $key --> HTTP::Header)
  
  ```
  
  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](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
  
  ```
  multi method build-header(HTTP::Headers:D: Str:D $name, *@values --> HTTP::Header:D)
  multi method build-header(HTTP::Headers:D: HTTP::Header::Standard::Name:D $name, *@values --> HTTP::Header:D)
  
  ```
  
  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](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
  
  ```
  multi method header-proxy(HTTP::Headers:D: Str:D $name --> HTTP::Header) is rw
  multi method header-proxy(HTTP::Headers:D: HTTP::Header::Standard::Name:D $name --> HTTP::Header) is rw
  
  ```
  
  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](http::Headers).
  
  # CAVEATS
  
  This module provides a mutator style that is not considered ideal, possibly even un-Perlish. It pretty much completely overuses <Proxy> objects and such to make mutators that perform complex operations during seemingly straightforward assignment operations. This is probably not wise, but it seemed like a good idea at the time of first writing.
  
  For a detailed write-up of why this is not preferable, see this blog post by Jonathan Worthington: [https://6guts.wordpress.com/2016/11/25/perl-6-is-biased-towards-mutators-being-really-simple-thats-a-good-thing/](Perl 6 is biased towards mutators being really simple. That’s a good thing.)
  