Implements: IteratorAggregate | Traversable | ArrayAccess | Serializable | Countable
The Kohana_HTTP_Header class provides an Object-Orientated interface
to HTTP headers. This can parse header arrays returned from the
PHP functions apache_request_headers()
or the http_parse_headers()
function available within the PECL HTTP library.
Class declared in SYSPATH/classes/http/header.php on line 3.
integer 1
integer 2
array
$default_sort_filterlink to thisDefault positive filter for sorting header values
array(4) ( 0 => string(6) "accept" 1 => string(14) "accept-charset" 2 => string(15) "accept-encoding" 3 => string(15) "accept-language" )
boolean
$sort_by_qualitylink to thisControls whether to automatically sort headers by quality value
bool FALSE
Constructor method for Kohana_HTTP_Header. Uses the standard constructor
of the parent ArrayObject
class.
$header_object
=
new
HTTP_Header(
array
(
'x-powered-by'
=>
'Kohana 3.1.x'
,
'expires'
=>
'...'
));
mixed
$input
required - Input arrayint
$flags
= NULL - Flagsstring
$iterator_class
= string(13) "ArrayIterator" - The iterator class to use
public
function
__construct(
$input
,
$flags
= NULL,
$iterator_class
=
'ArrayIterator'
)
{
// Parse the values into [HTTP_Header_Values]
parent::__construct(HTTP_Header::parse_header_values(
$input
),
$flags
,
$iterator_class
);
// If sort by quality is set, sort the fields by q=0.0 value
if
(HTTP_Header::
$sort_by_quality
)
{
$this
->sort_values_by_quality();
}
}
Returns the header object as a string, including the terminating new line
// Return the header as a string
echo
(string)
$request
->headers();
string
public
function
__toString()
{
$header
=
''
;
foreach
(
$this
as
$key
=>
$value
)
{
if
(
is_array
(
$value
))
{
$header
.=
$key
.
': '
.(implode(
', '
,
$value
)).
"\r\n"
;
}
else
{
$header
.=
$key
.
': '
.
$value
.
"\r\n"
;
}
}
return
$header
.
"\n"
;
}
Overloads the ArrayObject::exchangeArray()
method to ensure all
values passed are parsed correctly into a Kohana_HTTP_Header_Value.
// Input new headers
$headers
->exchangeArray(
array
(
'date'
=>
'Wed, 24 Nov 2010 21:09:23 GMT'
,
'cache-control'
=>
'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
));
array
$array
required - Array to exchangearray
public
function
exchangeArray(
$array
)
{
return
parent::exchangeArray(HTTP_Header::parse_header_values(
$array
));
}
Overloads the ArrayObject::offsetSet
method to ensure any
access is correctly converted to the correct object type.
// Add a new header from encoded string
$headers
[
'cache-control'
] =
'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
mixed
$index
required - Keymixed
$newval
required - Valuevoid
public
function
offsetSet(
$index
,
$newval
)
{
if
(
is_array
(
$newval
) AND (current(
$newval
)
instanceof
HTTP_Header_Value))
return
parent::offsetSet(
strtolower
(
$index
),
$newval
);
elseif
( !
$newval
instanceof
HTTP_Header_Value)
{
$newval
=
new
HTTP_Header_Value((string)
$newval
);
}
parent::offsetSet(
strtolower
(
$index
), (string)
$newval
);
}
Parses HTTP Header values and creating an appropriate object depending on type; i.e. accept-type, accept-char, cache-control etc.
$header_values_array
= HTTP_Header::parse_header_values(
array
(
'cache-control'
=>
'max-age=200; public'
));
array
$header_values
required - Values to parsearray
$header_commas_allowed
= array(4) (
0 => string(10) "user-agent"
1 => string(4) "date"
2 => string(7) "expires"
3 => string(13) "last-modified"
) - Header values where commas are not delimiters (usually date)array
public
static
function
parse_header_values(
array
$header_values
,
array
$header_commas_allowed
=
array
(
'user-agent'
,
'date'
,
'expires'
,
'last-modified'
))
{
/**
*
* HTTP header declarations should be treated as case-insensitive
*/
$header_values
=
array_change_key_case
(
$header_values
, CASE_LOWER);
// Foreach of the header values applied
foreach
(
$header_values
as
$key
=>
$value
)
{
if
(
is_array
(
$value
))
{
$values
=
array
();
if
(Arr::is_assoc(
$value
))
{
foreach
(
$value
as
$k
=>
$v
)
{
$values
[] = HTTP_Header::parse_header_values(
$v
);
}
}
else
{
// RFC 2616 allows multiple headers with same name if they can be
// concatinated using commas without altering the original message.
// This usually occurs with multiple Set-Cookie: headers
$array
=
array
();
foreach
(
$value
as
$k
=>
$v
)
{
// Break value into component parts
$v
=
explode
(
';'
,
$v
);
// Do some nasty parsing to flattern the array into components,
// parsing key values
$array
= Arr::flatten(
array_map
(
'HTTP_Header_Value::parse_key_value'
,
$v
));
// Get the K/V component and extract the first element
$key_value_component
=
array_slice
(
$array
, 0, 1, TRUE);
array_shift
(
$array
);
// Create the HTTP_Header_Value component array
$http_header
[
'key'
] = key(
$key_value_component
);
$http_header
[
'value'
] = current(
$key_value_component
);
$http_header
[
'properties'
] =
$array
;
// Create the HTTP_Header_Value
$values
[] =
new
HTTP_Header_Value(
$http_header
);
}
}
// Assign HTTP_Header_Value array to the header
$header_values
[
$key
] =
$values
;
continue
;
}
// If the key allows commas or no commas are found
if
(in_array(
$key
,
$header_commas_allowed
)
or
(
strpos
(
$value
,
','
) === FALSE))
{
// If the key is user-agent, we don't want to parse the string
if
(
$key
===
'user-agent'
)
{
$header_values
[
$key
] =
new
HTTP_Header_Value(
$value
, TRUE);
}
// Else, behave normally
else
{
$header_values
[
$key
] =
new
HTTP_Header_Value(
$value
);
}
// Move to next header
continue
;
}
// Create an array of the values and clear any whitespace
$value
=
array_map
(
'trim'
,
explode
(
','
,
$value
));
$parsed_values
=
array
();
// Foreach value
foreach
(
$value
as
$v
)
{
$v
=
new
HTTP_Header_Value(
$v
);
// Convert the value string into an object
if
(
$v
->key === NULL)
{
$parsed_values
[] =
$v
;
}
else
{
$parsed_values
[
$v
->key] =
$v
;
}
}
// Apply parsed value to the header
$header_values
[
$key
] =
$parsed_values
;
}
// Return the parsed header values
return
$header_values
;
}
Sort the headers by quality property if the header matches the Kohana_HTTP_Header::$default_sort_filter definition.
array
$filter
= array(0) - Header fields to parseself
public
function
sort_values_by_quality(
array
$filter
=
array
())
{
// If a filter argument is supplied
if
(
$filter
)
{
// Apply filter and store previous
$previous_filter
= HTTP_Header::
$default_sort_filter
;
HTTP_Header::
$default_sort_filter
=
$filter
;
}
// Get a copy of this ArrayObject
$values
=
$this
->getArrayCopy();
foreach
(
$values
as
$key
=>
$value
)
{
if
( !
is_array
(
$value
)
or
! in_array(
$key
, HTTP_Header::
$default_sort_filter
))
{
unset(
$values
[
$key
]);
continue
;
}
// Sort them by comparison
uasort(
$value
,
array
(
$this
,
'_sort_by_comparison'
));
$values
[
$key
] =
$value
;
}
// Return filter to previous state if required
if
(
$filter
)
{
HTTP_Header::
$default_sort_filter
=
$previous_filter
;
}
foreach
(
$values
as
$key
=>
$value
)
{
$this
[
$key
] =
$value
;
}
// Return this
return
$this
;
}
protected
function
_sort_by_comparison(
$value_a
,
$value_b
)
{
// Test for correct instance type
if
( !
$value_a
instanceof
HTTP_Header_Value OR !
$value_b
instanceof
HTTP_Header_Value)
{
// Return neutral if cannot test value
return
0;
}
// Extract the qualities
$a
= (float) Arr::get(
$value_a
->properties,
'q'
, HTTP_Header_Value::
$default_quality
);
$b
= (float) Arr::get(
$value_b
->properties,
'q'
, HTTP_Header_Value::
$default_quality
);
if
(
$a
==
$b
)
return
0;
elseif
(
$a
<
$b
)
return
1;
elseif
(
$a
>
$b
)
return
-1;
}