The Sapien classes do not model HTTP messages per se. Instead, the Request is a readonly value object composed of other readonly value objects representing the PHP superglobals and data structures derived from or composed of them. Similarly, the Response is a wrapper around and buffer for the various response-related global PHP functions.
Read more about Sapien at http://sapienphp.com.
In the after-action report on the failed RFC, I recorded the prevailing opinion that things like request and response objects should stay in userland. The problem with that, in the case of ext-request, was that readonly immutable objects were possible more effectively in C code than in userland PHP.
However, with the advent of PHP 8.1 and
readonly properties, all the functionality of the C code is now available in userland PHP. In a way, that means Sapien is a third version of ext-request, but fully in userland.
Sapien makes extensive use of
readonly, presenting a Request value object that is designed to be unchanging after instantiation. And because it's much easier to work in PHP than in C, there are many more value objects composed into the Request than in the C versions, such as:
Content, built up from various content-related headers and the request body itself
Url, computed from the various
Accept value object collections for Type, Charset, Encoding, and Language
XForwarded, distilled from the various
Forwarded value object collections derived from the
Authorization\Scheme value objects for basic, bearer, and digest authorization
The Response is fundamentally the same as it was in ext-request v1, though the custom file- and JSON-specific response logic has been extracted to specialized classes. Even so, the generic response is capable of handling all sorts of content, including iterables and resources.
So, if you're starting a new PHP 8.1 project, or refactoring a legacy system to PHP 8.1, try out Sapien, because request and response objects make life so much easier.