Skip to content

Commit d55bd56

Browse files
Fix parsing in Header::normalize() (#476)
Co-Authored-By: Tim Düsterhus <[email protected]> Co-authored-by: Tim Düsterhus <[email protected]>
1 parent ff76777 commit d55bd56

File tree

2 files changed

+94
-11
lines changed

2 files changed

+94
-11
lines changed

src/Header.php

+10-8
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,21 @@ public static function parse($header): array
4747
*/
4848
public static function normalize($header): array
4949
{
50-
if (!is_array($header)) {
51-
return array_map('trim', explode(',', $header));
52-
}
53-
5450
$result = [];
55-
foreach ($header as $value) {
51+
foreach ((array) $header as $value) {
5652
foreach ((array) $value as $v) {
5753
if (strpos($v, ',') === false) {
58-
$result[] = $v;
54+
$trimmed = trim($v);
55+
if ($trimmed !== '') {
56+
$result[] = $trimmed;
57+
}
5958
continue;
6059
}
61-
foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $v) as $vv) {
62-
$result[] = trim($vv);
60+
foreach (preg_split('/,(?=([^"]*"([^"]|\\\\.)*")*[^"]*$)/', $v) as $vv) {
61+
$trimmed = trim($vv);
62+
if ($trimmed !== '') {
63+
$result[] = $trimmed;
64+
}
6365
}
6466
}
6567
}

tests/HeaderTest.php

+84-3
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,90 @@ public function testParseParams($header, $result): void
6363
self::assertSame($result, Psr7\Header::parse($header));
6464
}
6565

66-
public function testParsesArrayHeaders(): void
66+
public function normalizeProvider(): array
6767
{
68-
$header = ['a, b', 'c', 'd, e'];
69-
self::assertSame(['a', 'b', 'c', 'd', 'e'], Psr7\Header::normalize($header));
68+
return [
69+
[
70+
'',
71+
[],
72+
],
73+
[
74+
['a, b', 'c', 'd, e'],
75+
['a', 'b', 'c', 'd', 'e'],
76+
],
77+
// Example 'accept-encoding'
78+
[
79+
'gzip, br',
80+
['gzip', 'br'],
81+
],
82+
// https://httpwg.org/specs/rfc7231.html#rfc.section.5.3.2
83+
[
84+
'text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c',
85+
['text/plain; q=0.5', 'text/html', 'text/x-dvi; q=0.8', 'text/x-c'],
86+
],
87+
// Example 'If-None-Match' with comma within an ETag
88+
[
89+
'"foo", "foo,bar", "bar"',
90+
['"foo"', '"foo,bar"', '"bar"'],
91+
],
92+
// https://httpwg.org/specs/rfc7234.html#cache.control.extensions
93+
[
94+
'private, community="UCI"',
95+
['private', 'community="UCI"'],
96+
],
97+
// The Cache-Control example with a comma within a community
98+
[
99+
'private, community="Guzzle,Psr7"',
100+
['private', 'community="Guzzle,Psr7"'],
101+
],
102+
// The Cache-Control example with an escaped space (quoted-pair) within a community
103+
[
104+
'private, community="Guzzle\\ Psr7"',
105+
['private', 'community="Guzzle\\ Psr7"'],
106+
],
107+
// The Cache-Control example with an escaped quote (quoted-pair) within a community
108+
[
109+
'private, community="Guzzle\\"Psr7"',
110+
['private', 'community="Guzzle\\"Psr7"'],
111+
],
112+
// The Cache-Control example with an escaped quote (quoted-pair) and a comma within a community
113+
[
114+
'private, community="Guzzle\\",Psr7"',
115+
['private', 'community="Guzzle\\",Psr7"'],
116+
],
117+
// The Cache-Control example with an escaped backslash (quoted-pair) within a community
118+
[
119+
'private, community="Guzzle\\\\Psr7"',
120+
['private', 'community="Guzzle\\\\Psr7"'],
121+
],
122+
// The Cache-Control example with an escaped backslash (quoted-pair) within a community
123+
[
124+
'private, community="Guzzle\\\\", Psr7',
125+
['private', 'community="Guzzle\\\\"', 'Psr7'],
126+
],
127+
// https://httpwg.org/specs/rfc7230.html#rfc.section.7
128+
[
129+
'foo ,bar,',
130+
['foo', 'bar'],
131+
],
132+
// https://httpwg.org/specs/rfc7230.html#rfc.section.7
133+
[
134+
'foo , ,bar,charlie ',
135+
['foo', 'bar', 'charlie'],
136+
],
137+
[
138+
"<https://example.gitlab.com>; rel=\"first\",\n<https://example.gitlab.com>; rel=\"next\",\n<https://example.gitlab.com>; rel=\"prev\",\n<https://example.gitlab.com>; rel=\"last\",",
139+
['<https://example.gitlab.com>; rel="first"', '<https://example.gitlab.com>; rel="next"', '<https://example.gitlab.com>; rel="prev"', '<https://example.gitlab.com>; rel="last"'],
140+
],
141+
];
142+
}
143+
144+
/**
145+
* @dataProvider normalizeProvider
146+
*/
147+
public function testNormalize($header, $result): void
148+
{
149+
self::assertSame($result, Psr7\Header::normalize([$header]));
150+
self::assertSame($result, Psr7\Header::normalize($header));
70151
}
71152
}

0 commit comments

Comments
 (0)