@@ -171,14 +171,14 @@ private function setHeaders(array $headers): void
171
171
private function normalizeHeaderValue ($ value ): array
172
172
{
173
173
if (!is_array ($ value )) {
174
- return $ this ->trimHeaderValues ([$ value ]);
174
+ return $ this ->trimAndValidateHeaderValues ([$ value ]);
175
175
}
176
176
177
177
if (count ($ value ) === 0 ) {
178
178
throw new \InvalidArgumentException ('Header value can not be an empty array. ' );
179
179
}
180
180
181
- return $ this ->trimHeaderValues ($ value );
181
+ return $ this ->trimAndValidateHeaderValues ($ value );
182
182
}
183
183
184
184
/**
@@ -195,7 +195,7 @@ private function normalizeHeaderValue($value): array
195
195
*
196
196
* @see https://tools.ietf.org/html/rfc7230#section-3.2.4
197
197
*/
198
- private function trimHeaderValues (array $ values ): array
198
+ private function trimAndValidateHeaderValues (array $ values ): array
199
199
{
200
200
return array_map (function ($ value ) {
201
201
if (!is_scalar ($ value ) && null !== $ value ) {
@@ -205,7 +205,10 @@ private function trimHeaderValues(array $values): array
205
205
));
206
206
}
207
207
208
- return trim ((string ) $ value , " \t" );
208
+ $ trimmed = trim ((string ) $ value , " \t" );
209
+ $ this ->assertValue ($ trimmed );
210
+
211
+ return $ trimmed ;
209
212
}, array_values ($ values ));
210
213
}
211
214
@@ -232,4 +235,32 @@ private function assertHeader($header): void
232
235
);
233
236
}
234
237
}
238
+
239
+ /**
240
+ * @see https://tools.ietf.org/html/rfc7230#section-3.2
241
+ *
242
+ * field-value = *( field-content / obs-fold )
243
+ * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
244
+ * field-vchar = VCHAR / obs-text
245
+ * VCHAR = %x21-7E
246
+ * obs-text = %x80-FF
247
+ * obs-fold = CRLF 1*( SP / HTAB )
248
+ */
249
+ private function assertValue (string $ value ): void
250
+ {
251
+ // The regular expression intentionally does not support the obs-fold production, because as
252
+ // per RFC 7230#3.2.4:
253
+ //
254
+ // A sender MUST NOT generate a message that includes
255
+ // line folding (i.e., that has any field-value that contains a match to
256
+ // the obs-fold rule) unless the message is intended for packaging
257
+ // within the message/http media type.
258
+ //
259
+ // Clients must not send a request with line folding and a server sending folded headers is
260
+ // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting
261
+ // folding is not likely to break any legitimate use case.
262
+ if (! preg_match ('/^(?:[\x21-\x7E\x80-\xFF](?:[\x20\x09]+[\x21-\x7E\x80-\xFF])?)*$/ ' , $ value )) {
263
+ throw new \InvalidArgumentException (sprintf ('"%s" is not valid header value ' , $ value ));
264
+ }
265
+ }
235
266
}
0 commit comments