Skip to content

Commit 4b50a62

Browse files
committed
Create PSR-7 messages using PSR-17 factories
1 parent c2b7579 commit 4b50a62

File tree

6 files changed

+453
-189
lines changed

6 files changed

+453
-189
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ before_install:
4242

4343
install:
4444
- if [ "$TRAVIS_PHP_VERSION" != "5.3" ]; then composer require --no-update zendframework/zend-diactoros; fi;
45+
- if [[ $TRAVIS_PHP_VERSION != 5.* ]]; then composer require --no-update http-interop/http-factory-diactoros; fi;
4546
- composer update --prefer-source $COMPOSER_OPTIONS
4647
- vendor/bin/simple-phpunit install
4748

Factory/PsrHttpFactory.php

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\PsrHttpMessage\Factory;
13+
14+
use Psr\Http\Message\ResponseFactoryInterface;
15+
use Psr\Http\Message\ServerRequestFactoryInterface;
16+
use Psr\Http\Message\StreamFactoryInterface;
17+
use Psr\Http\Message\UploadedFileFactoryInterface;
18+
use Psr\Http\Message\UploadedFileInterface;
19+
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
20+
use Symfony\Component\HttpFoundation\BinaryFileResponse;
21+
use Symfony\Component\HttpFoundation\File\UploadedFile;
22+
use Symfony\Component\HttpFoundation\Request;
23+
use Symfony\Component\HttpFoundation\Response;
24+
use Symfony\Component\HttpFoundation\StreamedResponse;
25+
26+
27+
/**
28+
* Builds Psr\HttpMessage instances using a PSR-17 implementation.
29+
*
30+
* @author Antonio J. García Lagar <[email protected]>
31+
*/
32+
class PsrHttpFactory implements HttpMessageFactoryInterface
33+
{
34+
35+
private $serverRequestFactory;
36+
private $streamFactory;
37+
private $uploadedFileFactory;
38+
private $responseFactory;
39+
40+
public function __construct(
41+
ServerRequestFactoryInterface $serverRequestFactory,
42+
StreamFactoryInterface $streamFactory,
43+
UploadedFileFactoryInterface $uploadedFileFactory,
44+
ResponseFactoryInterface $responseFactory
45+
) {
46+
$this->serverRequestFactory = $serverRequestFactory;
47+
$this->streamFactory = $streamFactory;
48+
$this->uploadedFileFactory = $uploadedFileFactory;
49+
$this->responseFactory = $responseFactory;
50+
}
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
public function createRequest(Request $symfonyRequest)
56+
{
57+
$request = $this->serverRequestFactory->createServerRequest(
58+
$symfonyRequest->getMethod(),
59+
$symfonyRequest->getSchemeAndHttpHost().$symfonyRequest->getRequestUri(),
60+
$symfonyRequest->server->all()
61+
);
62+
63+
foreach ($symfonyRequest->headers->all() as $name => $value) {
64+
$request = $request->withHeader($name, $value);
65+
}
66+
67+
if (PHP_VERSION_ID < 50600) {
68+
$body = $this->streamFactory->createStreamFromFile('php://temp', 'wb+');
69+
$body->write($symfonyRequest->getContent());
70+
} else {
71+
$body = $this->streamFactory->createStreamFromResource($symfonyRequest->getContent(true));
72+
}
73+
74+
$request = $request
75+
->withBody($body)
76+
->withUploadedFiles($this->getFiles($symfonyRequest->files->all()))
77+
->withCookieParams($symfonyRequest->cookies->all())
78+
->withQueryParams($symfonyRequest->query->all())
79+
->withParsedBody($symfonyRequest->request->all())
80+
->withRequestTarget($symfonyRequest->getRequestUri())
81+
;
82+
83+
foreach ($symfonyRequest->attributes->all() as $key => $value) {
84+
$request = $request->withAttribute($key, $value);
85+
}
86+
87+
return $request;
88+
}
89+
90+
/**
91+
* Converts Symfony uploaded files array to the PSR one.
92+
*
93+
* @param array $uploadedFiles
94+
*
95+
* @return array
96+
*/
97+
private function getFiles(array $uploadedFiles)
98+
{
99+
$files = array();
100+
101+
foreach ($uploadedFiles as $key => $value) {
102+
if (null === $value) {
103+
$files[$key] = $this->uploadedFileFactory->createUploadedFile(
104+
$this->streamFactory->createStream(),
105+
0,
106+
UPLOAD_ERR_NO_FILE
107+
);
108+
continue;
109+
}
110+
if ($value instanceof UploadedFile) {
111+
$files[$key] = $this->createUploadedFile($value);
112+
} else {
113+
$files[$key] = $this->getFiles($value);
114+
}
115+
}
116+
117+
return $files;
118+
}
119+
120+
/**
121+
* Creates a PSR-7 UploadedFile instance from a Symfony one.
122+
*
123+
* @param UploadedFile $symfonyUploadedFile
124+
*
125+
* @return UploadedFileInterface
126+
*/
127+
private function createUploadedFile(UploadedFile $symfonyUploadedFile)
128+
{
129+
return $this->uploadedFileFactory->createUploadedFile(
130+
$this->streamFactory->createStreamFromFile(
131+
$symfonyUploadedFile->getRealPath()
132+
),
133+
$symfonyUploadedFile->getClientSize(),
134+
$symfonyUploadedFile->getError(),
135+
$symfonyUploadedFile->getClientOriginalName(),
136+
$symfonyUploadedFile->getClientMimeType()
137+
);
138+
}
139+
140+
/**
141+
* {@inheritdoc}
142+
*/
143+
public function createResponse(Response $symfonyResponse)
144+
{
145+
$response = $this->responseFactory->createResponse($symfonyResponse->getStatusCode());
146+
147+
if ($symfonyResponse instanceof BinaryFileResponse) {
148+
$stream = $this->streamFactory->createStreamFromFile(
149+
$symfonyResponse->getFile()->getPathname()
150+
);
151+
} else {
152+
$stream = $this->streamFactory->createStreamFromFile('php://temp', 'wb+');
153+
if ($symfonyResponse instanceof StreamedResponse) {
154+
ob_start(function ($buffer) use ($stream) {
155+
$stream->write($buffer);
156+
157+
return false;
158+
});
159+
160+
$symfonyResponse->sendContent();
161+
ob_end_clean();
162+
} else {
163+
$stream->write($symfonyResponse->getContent());
164+
}
165+
}
166+
167+
$response = $response->withBody($stream);
168+
169+
$headers = $symfonyResponse->headers->all();
170+
171+
$cookies = $symfonyResponse->headers->getCookies();
172+
if (!empty($cookies)) {
173+
$headers['Set-Cookie'] = array();
174+
175+
foreach ($cookies as $cookie) {
176+
$headers['Set-Cookie'][] = $cookie->__toString();
177+
}
178+
}
179+
180+
181+
182+
foreach ($headers as $name => $value) {
183+
$response = $response->withHeader($name, $value);
184+
}
185+
186+
$protocolVersion = $symfonyResponse->getProtocolVersion();
187+
if ('1.1' !== $protocolVersion) {
188+
$response = $response->withProtocolVersion($protocolVersion);
189+
}
190+
191+
return $response;
192+
}
193+
}

0 commit comments

Comments
 (0)