guzzle / psr7

PSR-7 HTTP message library
MIT License
7.88k stars 3 forks source link

Exception in \GuzzleHttp\Psr7\Message::toString with poor (numeric) header #575

Closed tifeit closed 1 year ago

tifeit commented 1 year ago

PHP version: PHP 8.2.6 (cli)

Description When calling \GuzzleHttp\Psr7\Message::toString on the payload with numeric header it throws an error instead of providing the result

How to reproduce

<?php
require_once ('vendor/autoload.php');

$message = 'HTTP/1.1 200 OK
0: 256
Content-Type: application/json;charset=utf-8
Date: Mon, 21 Aug 2023 11:32:46 GMT
Host: hostname.domain
Vary: Accept-Encoding
X-Powered-By: PHP/8.2.6
Transfer-Encoding: chunked

{"success":false,"code":403,"msg":"Missing Authorization Header"}';

$response = \GuzzleHttp\Psr7\Message::parseResponse($message);

$messageStr = \GuzzleHttp\Psr7\Message::toString($response);

echo $messageStr;

will produce exception

PHP Fatal error:  Uncaught TypeError: strtolower(): Argument #1 ($string) must be of type string, int given in /.../vendor/guzzlehttp/psr7/src/Message.php:36

Possible Solution

if (strtolower((string)$name) === 'set-cookie') {

instead of

if (strtolower($name) === 'set-cookie') {

in Message.php

Additional context I'm not sure if numeric headers are valid in HTTP, but even if they are not, the exception should not be generic PHP type error The header itself becomes numeric instead of string here:

\GuzzleHttp\Utils::headersFromLines

$headers[\trim($parts[0])][] = isset($parts[1]) ? \trim($parts[1]) : null;

because of the way PHP works, $arr["0"] = 'asdf'; will be cast to integer array key.

GrahamCampbell commented 1 year ago

What version of this package are you using?

tifeit commented 1 year ago

Sorry, my bad.

I was using 2.5.0 but upgrading to latest 2.6.0 didn't help

tifeit commented 1 year ago

Thank you a lot!