phpsoftbox / http-message
PSR-7/PSR-17 HTTP message implementation for the PhpSoftBox framework
Requires
- php: ^8.5
- psr/http-factory: ^1.0
- psr/http-message: ^2.0
Requires (Dev)
- phpsoftbox/cs-fixer: ^1.2.2
- phpunit/phpunit: ^13.3
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-29 11:53:31 UTC
README
Собственная реализация PSR-7 и PSR-17 для PhpSoftBox.
Пример
use PhpSoftBox\Http\Message\ServerRequest; use PhpSoftBox\Http\Message\Uri; $request = new ServerRequest('GET', new Uri('https://example.com/ping'));
Создание запроса из globals
use PhpSoftBox\Http\Message\ServerRequestCreator; $creator = new ServerRequestCreator(); $request = $creator->fromGlobals();
Разбор host и request target
ServerRequestCreator::fromGlobals():
- host и порт берёт из заголовка
Host; IPv6-адрес указывается в скобках ([::1]:8080), пустой или некорректный порт (example.com:) отбрасывается.SERVER_NAME/SERVER_PORTиспользуются, только еслиHostне пришёл; - некорректный
Host(например, со/) не приводит к ошибке — URI остаётся без host; REQUEST_URIделится на path и query вручную://evil/x?y=1даёт path//evil/x, а не authorityevil;- заголовки запроса с недопустимым именем или значением пропускаются.
Прокси
ServerRequestCreator не учитывает X-Forwarded-Proto: заголовок подделывает клиент. За прокси схему, host, порт и
IP клиента подставляет TrustedProxyMiddleware из phpsoftbox/application — только для запросов от доверенных
прокси. Для замены REMOTE_ADDR у ServerRequest есть withServerParams() (вне PSR-7).
Соответствие PSR-7
Заголовки
- Имя заголовка — token из RFC 7230 (буквы, цифры и
!#$%&'*+-.^_`|~), иначеInvalidArgumentException. - Значение не может содержать CR, LF, NUL и другие управляющие символы, кроме табуляции:
withHeader('X-A', "a\r\nSet-Cookie: x=1")бросаетInvalidArgumentException. Проверка действует в конструкторе,withHeader()иwithAddedHeader(). Пробелы и табуляция по краям значения удаляются. - Значение — строка, число или непустой массив из них; пустой массив и
nullотклоняются.
Метод и request target
Метод регистрозависим и сохраняется как передан: new Request('get', '/')->getMethod() вернёт get. Допустим только
token из RFC 7230. Request target с пробельными символами отклоняется.
Uri
- Path, query, fragment и user info кодируются: недопустимые символы заменяются на
%XX, уже закодированные последовательности не кодируются повторно (/a b→/a%20b,/a%20bостаётся как есть). - Стандартный порт схемы (
http— 80,https— 443,ws/wss) возвращается изgetPort()какnullи не попадает в authority. - При сборке строки rootless path при наличии authority дополняется
/(http://example.com+foo→http://example.com/foo); path на//без authority сокращается до одного/. - Host с пробелами, управляющими символами,
/,?,#,@отклоняется.
Прочее
ServerRequest::getAttribute()возвращает сохранённыйnull, а не значение по умолчанию.StreamFactory::createStreamFromFile()бросаетRuntimeException, если файл не открылся, иInvalidArgumentExceptionдля недопустимого режима.Responseподставляет стандартную reason phrase для всех статусов реестра IANA.UploadedFile::moveTo()переносит файлы, загруженные через SAPI, функциейmove_uploaded_file(); остальные stream копирует с начала. Ошибка открытия или записи целевого файла даётRuntimeException, файл при этом не считается перенесённым.