-
Notifications
You must be signed in to change notification settings - Fork 2
/
HeaderUtility.php
125 lines (110 loc) · 3.43 KB
/
HeaderUtility.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
declare(strict_types=1);
namespace Cake\Http;
/**
* Provides helper methods related to HTTP headers
*/
class HeaderUtility
{
/**
* Get an array representation of the HTTP Link header values.
*
* @param array $linkHeaders An array of Link header strings.
* @return array
*/
public static function parseLinks(array $linkHeaders): array
{
$result = [];
foreach ($linkHeaders as $linkHeader) {
$result[] = static::parseLinkItem($linkHeader);
}
return $result;
}
/**
* Parses one item of the HTTP link header into an array
*
* @param string $value The HTTP Link header part
* @return array<string, mixed>
*/
protected static function parseLinkItem(string $value): array
{
preg_match('/<(.*)>[; ]?[; ]?(.*)?/i', $value, $matches);
$url = $matches[1];
$parsedParams = ['link' => $url];
$params = $matches[2];
if ($params) {
$explodedParams = explode(';', $params);
foreach ($explodedParams as $param) {
$explodedParam = explode('=', $param);
$trimedKey = trim($explodedParam[0]);
$trimedValue = trim($explodedParam[1], '"');
if ($trimedKey === 'title*') {
// See https://www.rfc-editor.org/rfc/rfc8187#section-3.2.3
preg_match('/(.*)\'(.*)\'(.*)/i', $trimedValue, $matches);
$trimedValue = [
'language' => $matches[2],
'encoding' => $matches[1],
'value' => urldecode($matches[3]),
];
}
$parsedParams[$trimedKey] = $trimedValue;
}
}
return $parsedParams;
}
/**
* Parse the Accept header value into weight => value mapping.
*
* @param string $header The header value to parse
* @return array<string, array<string>>
*/
public static function parseAccept(string $header): array
{
$accept = [];
if (!$header) {
return $accept;
}
$headers = explode(',', $header);
foreach (array_filter($headers) as $value) {
$prefValue = '1.0';
$value = trim($value);
$semiPos = strpos($value, ';');
if ($semiPos !== false) {
$params = explode(';', $value);
$value = trim($params[0]);
foreach ($params as $param) {
$qPos = strpos($param, 'q=');
if ($qPos !== false) {
$prefValue = substr($param, $qPos + 2);
}
}
}
if (!isset($accept[$prefValue])) {
$accept[$prefValue] = [];
}
if ($prefValue) {
$accept[$prefValue][] = $value;
}
}
krsort($accept);
return $accept;
}
/**
* @param string $value The WWW-Authenticate header
* @return array
*/
public static function parseWwwAuthenticate(string $value): array
{
preg_match_all(
'@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@',
$value,
$matches,
PREG_SET_ORDER
);
$return = [];
foreach ($matches as $match) {
$return[$match[1]] = $match[3] ?? $match[2];
}
return $return;
}
}