PSR-7 Bridge
Request and Response are Monad-native classes, not PSR-7 implementations.
Full PSR-7 immutability semantics conflict with the ergonomic accessor API
($request->input('email'), $request->json('customer.name')) — adopting
PSR-7 directly would mean giving up that API. Instead, both classes expose bridge methods that
convert to and from a real PSR-7 value, so anything in your stack that expects PSR-7 — a
third-party middleware, an HTTP client integration — still works.
Request to and from PSR-7
use Monad\Clarity\Services\Request;
$request = Request::capture();
$psrRequest = $request->toPsr7(); // Psr\Http\Message\ServerRequestInterface
// And back:
$request = Request::fromPsr7($psrRequest);
The round trip preserves method, path, query parameters, cookies, uploaded files, and the raw body
— a request built from fromArrays(), converted with toPsr7(), and
converted back with fromPsr7() ends up with the same path and query values it started
with.
Response to PSR-7
use Monad\Clarity\Services\Response;
$response = Response::json(['ok' => true]);
$psrResponse = $response->toPsr7(); // Psr\Http\Message\ResponseInterface
$psrResponse->getStatusCode(); // 200
$psrResponse->getHeaderLine('Content-Type'); // application/json
(string) $psrResponse->getBody(); // {"ok":true}
There's no Response::fromPsr7() — responses are constructed going one direction only,
since your application code is always the one producing them.
What's actually PSR
Logger implements PSR-3, Cache implements PSR-16, and HttpClient implements PSR-18 directly — each is a small, stable interface with no ergonomic conflict with Monad's own API style, so there was no reason to bridge those.
Next steps
- Request/Response Lifecycle — where
Request/Responsesit in a real request.