8000 Initial support by dunglas · Pull Request #1 · symfony/psr-http-message-bridge · GitHub
[go: up one dir, main page]

Skip to content

Initial support #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
999be72
Add composer dependencies
dunglas May 21, 2015
47c6564
More dependencies
dunglas May 21, 2015
6a4ab9b
Add interfaces and stubs.
dunglas May 21, 2015
1ed3bff
Add .gitignore
dunglas May 21, 2015
1b81ee0
Make factory methods static. Add test infra.
dunglas May 21, 2015
1e3307c
Setup Travis
dunglas May 21, 2015
7e7fbf6
Add missing static keywords
dunglas May 21, 2015
43d4c48
Use ServerRequestInterface
dunglas May 21, 2015
bb43a07
Basic HttpFoundationFactory::createRequest implementation
dunglas May 21, 2015
656318b
Remove a short array usage
dunglas May 21, 2015
40c2973
Make immutable
dunglas May 22, 2015
a246407
Enforce immutability
dunglas May 22, 2015
77360d6
Uploaded file support
dunglas May 22, 2015
6f5815b
Fix some @stof comments
dunglas May 22, 2015
5240539
Add license headers
dunglas May 22, 2015
8b4a078
More unit tests for uploaded files.
dunglas May 23, 2015
14dac4e
HttpFoundation Response factory and tests
dunglas May 23, 2015
8c3c90e
Fix CS
dunglas May 23, 2015
65261ee
Diactoros factory draft implementation
dunglas May 23, 2015
7e44bc2
New version of DiactorosFactory::createRequest(). Tests.
dunglas May 24, 2015
1e480a9
Rename HttpMessageFactoryInterface
dunglas May 24, 2015
9127c84
Update LICENSE copyright year
dunglas May 24, 2015
b360068
Better stream handling in DiactorosFactory::createRequest
dunglas May 24, 2015
4d11665
New DiactorosFactory::createResponse implementation. Tests.
dunglas May 24, 2015
e129154
StreamedResponse support
dunglas May 24, 2015
91a13dc
Fix BadMethodCallException
dunglas May 25, 2015
ef384ae
Throw an exception if Zend Diactoros isn't installed.
dunglas May 25, 2015
bcfa698
Fix Travis
dunglas May 26, 2015
8a2bd7b
Remove dev dependency to Zend Diactoros
dunglas May 27, 2015
f41f3e4
New DiactorosFactory implementation
dunglas May 27, 2015
9c6f180
Added cookies support
dunglas May 27, 2015
7d8bdc8
PHPUnit optimizations
dunglas May 27, 2015
eacce8f
Remove crap.
dunglas May 27, 2015
7012db5
Enhanced headers support
dunglas May 27, 2015
b887c36
CS fixes
dunglas May 27, 2015
ca2ea3b
BinaryFileResponse support
dunglas May 27, 2015
577e633
Support Symfony 3.0
dunglas May 28, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml
43 changes: 43 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
language: php

sudo: false

matrix:
include:
- php: 5.3
- php: 5.4
- php: 5.5
- php: 5.6
- php: 5.3
env: deps=low
- php: 5.6
env: deps=high
- php: nightly
- php: hhvm
allow_failures:
- php: nightly
- php: hhvm
fast_finish: true

env:
global:
- deps=no
- SYMFONY_DEPRECATIONS_HELPER=weak

before_install:
- composer self-update
- if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then phpenv config-rm xdebug.ini; fi;
- if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]] && [ $(php -r "echo PHP_MINOR_VERSION;") -le 4 ]; then echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;
- if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then php -i; fi;
# Set the COMPOSER_ROOT_VERSION to the right version according to the branch being built
- if [ "$TRAVIS_BRANCH" = "master" ]; then export COMPOSER_ROOT_VERSION=dev-master; else export COMPOSER_ROOT_VERSION="$TRAVIS_BRANCH".x-dev; fi;

install:
- if [[ "$TRAVIS_PHP_VERSION" != "5.3" ]] && [[ "$TRAVIS_PHP_VERSION" != "5.4" ]]; then composer require --no-update zendframework/zend-diactoros; fi;
- if [ "$deps" = "no" ]; then export SYMFONY_DEPRECATIONS_HELPER=strict; fi;
- if [ "$deps" = "no" ]; then composer --prefer-source install; fi;
- if [ "$deps" = "high" ]; then composer --prefer-source update; fi;
- if [ "$deps" = "low" ]; then composer --prefer-source --prefer-lowest --prefer-stable update; fi;

script:
- phpunit
164 changes: 164 additions & 0 deletions Factory/DiactorosFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\PsrHttpMessage\Factory;

use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Zend\Diactoros\Response as DiactorosResponse;
use Zend\Diactoros\ServerRequest;
use Zend\Diactoros\ServerRequestFactory as DiactorosRequestFactory;
use Zend\Diactoros\Stream as DiactorosStream;
use Zend\Diactoros\UploadedFile as DiactorosUploadedFile;

/**
* Builds Psr\HttpMessage instances using the Zend Diactoros implementation.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class DiactorosFactory implements HttpMessageFactoryInterface
{
public function __construct()
{
if (!class_exists('Zend\Diactoros\ServerRequestFactory')) {
throw new \RuntimeException('Zend Diactoros must be installed to use the DiactorosFactory.');
}
}

/**
* {@inheritdoc}
*/
public function createRequest(Request $symfonyRequest)
{
$server = DiactorosRequestFactory::normalizeServer($symfonyRequest->server->all());
$headers = $symfonyRequest->headers->all();

try {
$body = new DiactorosStream($symfonyRequest->getContent(true));
} catch (\LogicException $e) {
$body = new DiactorosStream('php://temp', 'wb+');
$body->write($symfonyRequest->getContent());
}

$request = new ServerRequest(
$server,
DiactorosRequestFactory::normalizeFiles($this->getFiles($symfonyRequest->files->all())),
$symfonyRequest->getUri(),
$symfonyRequest->getMethod(),
$body,
$headers
);

$request = $request
->withCookieParams($symfonyRequest->cookies->all())
->withQueryParams($symfonyRequest->query->all())
->withParsedBody($symfonyRequest->request->all())
;

foreach ($symfonyRequest->attributes->all() as $key => $value) {
$request = $request->withAttribute($key, $value);
}

return $request;
}

/**
* Converts Symfony uploaded files array to the PSR one.
*
* @param array $uploadedFiles
*
* @return array
*/
private function getFiles(array $uploadedFiles)
{
$files = array();

foreach ($uploadedFiles as $key => $value) {
if ($value instanceof UploadedFile) {
$files[$key] = $this->createUploadedFile($value);
} else {
$files[$key] = $this->getFiles($value);
}
}

return $files;
}

/**
* Creates a PSR-7 UploadedFile instance from a Symfony one.
*
* @param UploadedFile $symfonyUploadedFile
*
* @return UploadedFileInterface
*/
private function createUploadedFile(UploadedFile $symfonyUploadedFile)
{
return new DiactorosUploadedFile(
$symfonyUploadedFile->getRealPath(),
$symfonyUploadedFile->getSize(),
$symfonyUploadedFile->getError(),
$symfonyUploadedFile->getClientOriginalName(),
$symfonyUploadedFile->getClientMimeType()
);
}

/**
* {@inheritdoc}
*/
public function createResponse(Response $symfonyResponse)
{
if ($symfonyResponse instanceof BinaryFileResponse) {
$stream = new DiactorosStream($symfonyResponse->getFile()->getPathname(), 'r');
} else {
$stream = new DiactorosStream('php://temp', 'wb+');
if ($symfonyResponse instanceof StreamedResponse) {
ob_start(function ($buffer) use ($stream) {
$stream->write($buffer);

return false;
});

$symfonyResponse->sendContent();
ob_end_clean();
} else {
$stream->write($symfonyResponse->getContent());
}
}

$headers = $symfonyResponse->headers->all();

$cookies = $symfonyResponse->headers->getCookies();
if (!empty($cookies)) {
$headers['Set-Cookie'] = array();

foreach ($cookies as $cookie) {
$headers['Set-Cookie'][] = $cookie->__toString();
}
}

$response = new DiactorosResponse(
$stream,
$symfonyResponse->getStatusCode(),
$headers
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conversion is incomplete here:

  • you are missing the status text (although it might be a pain as we don't have a getter for it)
  • you are missing cookies

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok cookies are not added as headers in Symfony Response.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not always hardcoded: https://github.com/zendframework/zend-diactoros/blob/be067c409377671b8268236443d993374e1987fa/src/Response.php#L160 (which is very similar to what we do in HttpFoundation btw)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed it but still not usable because there is not getter for the status text in the Symfony response.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, if we don't convert the status text, it is not a big issue. I don't think it is the most used feature in HttpFoundation (I'm not even sure it is documented, and setting the status code in the constructor does not allow to set the status text).
But we should convert cookies to Set-Cookie headers


$protocolVersion = $symfonyResponse->getProtocolVersion();
if ('1.1' !== $protocolVersion) {
$response = $response->withProtocolVersion($protocolVersion);
}

return $response;
}
}
Loading
0