loophp/unaltered-psr-http-message-bridge-bundle
Symfony bundle bridging PSR-7 HTTP messages without altering them. Converts between PSR-7 requests/responses and Symfony HttpFoundation safely, preserving headers, body streams, and URIs—useful when integrating PSR-7 middleware or clients in Symfony apps.
Installation Add the package via Composer:
composer require loophp/unaltered-psr-http-message-bridge-bundle
Register the bundle in config/bundles.php:
return [
// ...
Loop\UnalteredPsrHttpMessageBridgeBundle\LoopUnalteredPsrHttpMessageBridgeBundle::class => ['all' => true],
];
First Use Case
Convert a Symfony Request to a PSR-7 ServerRequest without modifying query parameters:
use Loop\UnalteredPsrHttpMessageBridgeBundle\Bridge\SymfonyRequestToPsr7RequestBridge;
$bridge = new SymfonyRequestToPsr7RequestBridge();
$psr7Request = $bridge->toPsr7($symfonyRequest);
Where to Look First
SymfonyRequestToPsr7RequestBridge and Psr7RequestToSymfonyRequestBridge in src/Bridge/.config/packages/loop_unaltered_psr_http_message_bridge.yaml for defaults.tests/ for edge cases and expected behavior.Request Conversion
Convert Symfony Request to PSR-7 ServerRequest in middleware or controllers:
public function handle(Request $symfonyRequest, Closure $next)
{
$bridge = app(SymfonyRequestToPsr7RequestBridge::class);
$psr7Request = $bridge->toPsr7($symfonyRequest);
// Use PSR-7 logic (e.g., with Slim, Zend, or custom PSR-7 handlers)
$response = $this->handlePsr7($psr7Request);
return $bridge->toSymfony($response);
}
Response Conversion
Convert PSR-7 Response back to Symfony Response:
$psr7Response = $this->psr7Handler->handle($psr7Request);
$symfonyResponse = $bridge->toSymfony($psr7Response);
return $symfonyResponse;
Dependency Injection
Bind the bridge in services.yaml for reusable access:
services:
Loop\UnalteredPsrHttpMessageBridgeBundle\Bridge\SymfonyRequestToPsr7RequestBridge:
public: true
Integration with PSR-7 Libraries Use with libraries like Slim, Zend, or Laminas:
$app = new \Slim\App();
$app->add(new \Slim\Middleware\ContentLengthMiddleware());
$app->add(new \Slim\Middleware\BodyParsingMiddleware());
// Convert Symfony Request to PSR-7
$psr7Request = $bridge->toPsr7($symfonyRequest);
$response = $app->handle($psr7Request);
// Convert back to Symfony Response
return $bridge->toSymfony($response);
Custom Middleware Create middleware that bridges requests/responses transparently:
class Psr7BridgeMiddleware
{
public function __construct(private SymfonyRequestToPsr7RequestBridge $bridge) {}
public function __invoke(Request $request, Closure $next)
{
$psr7Request = $this->bridge->toPsr7($request);
$psr7Response = $next($psr7Request);
return $this->bridge->toSymfony($psr7Response);
}
}
Query Parameter Preservation
?foo=bar&baz=qux remains unchanged during conversion.Server Parameters
SERVER parameters (e.g., PHP_SELF, REQUEST_URI) may differ between Symfony and PSR-7. Test thoroughly with your server setup (Apache/Nginx/PHP-FPM).Uploaded Files
_FILES) are converted to PSR-7 UploadedFileInterface. Ensure your PSR-7 handlers support this (e.g., Slim 3+ does).Cookie Handling
Set-Cookie headers correctly (e.g., Symfony’s Response vs. PSR-7 Response).Deprecated Features
Request methods (e.g., getScriptName()) if they’re not mirrored in PSR-7.Verify Conversions Dump the converted request/response to check for discrepancies:
dd($bridge->toPsr7($symfonyRequest)->getQueryParams());
Server Parameter Mismatches
Compare SERVER arrays before/after conversion:
dd([
'Symfony' => $symfonyRequest->server->all(),
'PSR-7' => $psr7Request->getServerParams(),
]);
Uploaded Files Validate file handling:
$files = $psr7Request->getUploadedFiles();
foreach ($files as $file) {
dd($file->getClientFilename(), $file->getSize());
}
Performance
Testing
HttpFoundationTestCase or Psr7TestCase to assert conversions:
$this->assertEquals('qux', $psr7Request->getQueryParams()['foo']);
Extending Functionality
SymfonyRequestToPsr7RequestBridge to add custom logic (e.g., modify headers before conversion):
class CustomBridge extends SymfonyRequestToPsr7RequestBridge
{
public function toPsr7(Request $request)
{
$request->headers->set('X-Custom', 'Value');
return parent::toPsr7($request);
}
}
Configuration
config/packages/loop_unaltered_psr_http_message_bridge.yaml:
loop_unaltered_psr_http_message_bridge:
preserve_query_string: true # Already default; explicit for clarity
Fallback for Missing Features
$psr7Request = $bridge->toPsr7($symfonyRequest);
$psr7Request = new class($psr7Request) extends \Zend\Diactoros\ServerRequest {
public function getAttribute($name, $default = null)
{
return $this->request->attributes->get($name, $default);
}
};
How can I help you explore Laravel packages today?