brnc / psr7-symfony1-adapter
Partial PSR-7 Adapters for Symfony 1.5
Installs: 27 875
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 1
Forks: 1
Open Issues: 0
Requires
- php: ^7.4 || ^8.0
- guzzlehttp/psr7: ^1.9.1 || ^2.4.5
- psr/http-factory: ^1.0
- webmozart/assert: ^1.10
Requires (Dev)
- composer/package-versions-deprecated: ^1.11
- ergebnis/composer-normalize: ^2.15
- php-http/psr7-integration-tests: ^1.1
- phpmd/phpmd: ^2.10.1
- phpstan/phpstan: ^1.10
- phpstan/phpstan-webmozart-assert: ^1.2
- phpunit/phpunit: ^9.6.7
- roave/security-advisories: dev-master
- vimeo/psalm: ^5.9
README
To enable the use of future-proof PSR-15 middlewares via partial PSR-7 adapters.
Quickstart
// not fully PSR-7 compliant lazy adapters $serverRequestAdapter = \brnc\Symfony1\Message\Adapter\Request::fromSfWebRequest($sfWebRequest); $responseAdapter = \brnc\Symfony1\Message\Adapter\Response::fromSfWebResponse($sfWebResponse);
ServerRequest
Please mind the following PSR-7 violation which is enabled by default:
No immutability by default
as this is just an adapter for \sfWebRequest
which cannot easily be replaced with another instance.
This adapter – by default – also returns the very same instance when calling with*()
methods. For the same reason calls to methods which cannot act on and alter the underlying \sfWebRequest
will throw an \brnc\Symfony1\Message\Exception\LogicException
.
This default behaviour can be changed by creating the Request
using the Request::OPTION_IMMUTABLE_VIOLATION
option set to false
. The Request
-adapter will then always return new instances when with*()
-methods are called and won't throw exceptions on calls which cannot transparently act on the \sfWebRequest
- object.
use brnc\Symfony1\Message\Adapter\Request; $serverRequestAdapter = Request::fromSfWebRequest( $sfWebRequest, [ // If set to true a stream on php://input is used instead of creating one over sfWebRequest::getContent() → defaults to false Request::OPTION_BODY_USE_STREAM => false, // sfWebRequest-compatibility mode – set to false if you need PSR-7's immutability Request::OPTION_IMMUTABLE_VIOLATION => true, ] );
Response
Please mind the default to mutability!
use brnc\Symfony1\Message\Adapter\Response; $responseAdapter = Response::fromSfWebResponse( $sfWebResponse, [Response::OPTION_IMMUTABLE_VIOLATION => false] ); $newInstance = $responseAdapter->withBody( \GuzzleHttp\Psr7\Utils::streamFor( '<html><head><title>Hello World!</title></head><body><h1>PSR-7 Adapters!</h1></body></html>' ) ); $newestInstance = $newInstance->withBody( \GuzzleHttp\Psr7\Utils::streamFor( '<html><head><body><h1>dead end</h1></body></html>' ) ); // selects the content of $newInstance to be send instead of the most recent instance's one (i.e. $newestInstance) $newInstance->preSend(); // N.b. The stream of $newestInstance is still held in memory until $responseAdapter and all copies got destroyed! // This might change in the future when this will be refactored to use WeakMap. $sfWebResponse->send();
Pass it down to a PSR-15 sub-stack
You may use the ResponseFactory
implementing \Psr\Http\Message\ResponseFactoryInterface
in order to "spawn" responses within your PSR-15 sub-stack.
$request = \brnc\Symfony1\Message\Adapter\Request::fromSfWebRequest($sfWebRequest); $responseFactory = new \brnc\Symfony1\Message\Factory\ResponseFactory($sfWebResponse); // (dependency) inject the ResponseFactory to your dispatcher, middlewares, and handlers $entryPoint = new YourPSR15Dispatcher($responseFactory); // Dispatch your sub-stack via PSR-15 $response = $entryPoint->handler($response); // As $response will be linked to $sfWebResponse you don't need to do anything // if you are in the context of a Symfony1 action. Only call $response->getSfWebResponse() in dire need!
Manually transcribe a PSR-7 Response to Symfony1
Assume you couldn't use other means, and you're confronted with an arbitrary PSR-7 response you can use the ResponseTranscriptor
to copy the data from your PSR-7 response to your \sfWebResponse
.
Currently the ResponseTranscriptor
doesn't support cookies, and will fail fast and hard if it encounters some. You are free to implement your own Cookie-Handler implementing CookieTranscriptorInterface
and pass it as an optional constructor argument
// Given arbitrary PSR-7 response… $psr7response = $psr7responseFactory(); // …use the ResponseTranscriptor in order to– $transcriptor = new \brnc\Symfony1\Message\Transcriptor\ResponseTranscriptor(); // copy the response's contents. // The returned object will be the same as in the argument! $sfWebResponse = $transcriptor->transcribe($psr7response, $sfWebResponse);
Pass it down to http-foundation i.e. present-day Symfony
Combine this PSR7-Symfony1 Adapter and symfony/psr-http-message-bridge
to connect your Symfony1 stack via PSR-7 to symfony/http-foundation
objects and leverage using embedded (present-day) Symfony components.
// Use this chain to create a http-foundation request from a Symfony1's \sfWebRequest $psrRequest = \brnc\Symfony1\Message\Adapter\Request::fromSfWebRequest($sfWebRequest); $httpFoundationFactory = \Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory(); $symfonyRequest = $httpFoundationFactory->createRequest($psrRequest); // Handle the request with some present day Symfony component $symfonyResponse = $httpKernel->handle($symfonyRequest); // Possibly ResponseFactory is best created in the Symfony1 context $responseFactory = new \brnc\Symfony1\Message\Factory\ResponseFactory($sfWebResponse); // Obtain other PSR17 factories, // while only ResponseFactory & StreamFactory will be used (as of today) $streamFactory = \brnc\Symfony1\Message\Factory\GuzzleStreamFactory(); $decoyFactory = \brnc\Symfony1\Message\Factory\DecoyHttpFactory(); // Construct the PsrHttpFactory from symfony/psr-http-message-bridge and translate… $psrHttpFactory = Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory( $decoyFactory, $streamFactory, $decoyFactory, $responseFactory ); $psrResponse = $psrHttpFactory->createResponse($symfonyResponse); // As $psrResponse will be linked to $sfWebResponse as it was created through the // ResponseFactory you don't need to do anything if you exit via an Symfony1 action. // Only call $psrResponse->getSfWebResponse() in dire need!