From 094ad080eeecb1cf38e4b5f03947d34ab90af066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=B6nthal?= Date: Fri, 31 Oct 2014 16:26:34 +0100 Subject: [PATCH 1/5] upstream fixes --- composer.json | 4 +-- src/React/Espresso/Application.php | 2 +- src/React/Espresso/ControllerCollection.php | 28 +++++++++++++++++---- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 9b97706..7a1e2d9 100644 --- a/composer.json +++ b/composer.json @@ -5,8 +5,8 @@ "license": "MIT", "require": { "php": ">=5.3.3", - "react/http": "0.2.*", - "silex/silex": "1.0.*@dev" + "react/http": "~0.4", + "silex/silex": "~1.0" }, "autoload": { "psr-0": { "React\\Espresso": "src" } diff --git a/src/React/Espresso/Application.php b/src/React/Espresso/Application.php index 4bd9d67..459562d 100644 --- a/src/React/Espresso/Application.php +++ b/src/React/Espresso/Application.php @@ -17,7 +17,7 @@ public function __construct() $app = $this; $this['controllers_factory'] = function () use ($app) { - return new ControllerCollection($app['route_factory']); + return new ControllerCollection($app['route_factory'], $app['resolver']); }; } diff --git a/src/React/Espresso/ControllerCollection.php b/src/React/Espresso/ControllerCollection.php index e50faf6..237184b 100644 --- a/src/React/Espresso/ControllerCollection.php +++ b/src/React/Espresso/ControllerCollection.php @@ -3,24 +3,42 @@ namespace React\Espresso; use Silex\ControllerCollection as BaseControllerCollection; -use Symfony\Component\HttpFoundation\Request; +use Silex\Route; + use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpFoundation\StreamedResponse as SymfonyStreamedResponse; class ControllerCollection extends BaseControllerCollection { - public function match($pattern, $to) + /** + * @var ControllerResolverInterface + */ + private $resolver; + + public function __construct(Route $defaultRoute, ControllerResolverInterface $resolver) { - $wrapped = $this->wrapController($to); + parent::__construct($defaultRoute); + + $this->resolver = $resolver; + } - return parent::match($pattern, $wrapped); + public function match($pattern, $to = null) + { + return parent::match($pattern, $this->wrapController($to)); } private function wrapController($controller) { - return function (Request $sfRequest) use ($controller) { + $resolver = $this->resolver; + + return function (Request $sfRequest) use ($controller, $resolver) { $request = $sfRequest->attributes->get('react.espresso.request'); $response = $sfRequest->attributes->get('react.espresso.response'); + if (!is_callable($controller)) { + $controller = $resolver->getController($sfRequest); + } + call_user_func($controller, $request, $response); return new SymfonyStreamedResponse(); From 28e1f755669d3ae5e283bb40235a0a36a54473ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=B6nthal?= Date: Fri, 31 Oct 2014 17:51:20 +0100 Subject: [PATCH 2/5] catch exceptions --- src/React/Espresso/Application.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/React/Espresso/Application.php b/src/React/Espresso/Application.php index 459562d..85bf0e8 100644 --- a/src/React/Espresso/Application.php +++ b/src/React/Espresso/Application.php @@ -6,6 +6,7 @@ use React\Http\Response; use Silex\Application as BaseApplication; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\HttpKernelInterface; class Application extends BaseApplication @@ -23,8 +24,16 @@ public function __construct() public function __invoke(Request $request, Response $response) { - $sfRequest = $this->buildSymfonyRequest($request, $response); - $this->handle($sfRequest, HttpKernelInterface::MASTER_REQUEST, false); + try { + $sfRequest = $this->buildSymfonyRequest($request, $response); + $this->handle($sfRequest, HttpKernelInterface::MASTER_REQUEST, false); + } catch (HttpException $e) { + $response->writeHead($e->getStatusCode()); + $response->end($e->getMessage()); + } catch (\Exception $e) { + $response->writeHead(500); + $response->end($e->getMessage()); + } } private function buildSymfonyRequest(Request $request, Response $response) From 916b35f15e30ef15acf041d67c32cca3972a6e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=B6nthal?= Date: Fri, 31 Oct 2014 18:14:31 +0100 Subject: [PATCH 3/5] fixing req/res --- src/React/Espresso/ControllerCollection.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/React/Espresso/ControllerCollection.php b/src/React/Espresso/ControllerCollection.php index 237184b..ea8843a 100644 --- a/src/React/Espresso/ControllerCollection.php +++ b/src/React/Espresso/ControllerCollection.php @@ -2,11 +2,13 @@ namespace React\Espresso; +use React\Http\Request; +use React\Http\Response; use Silex\ControllerCollection as BaseControllerCollection; use Silex\Route; - use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpFoundation\StreamedResponse as SymfonyStreamedResponse; +use Symfony\Component\HttpFoundation\Request as SymfonyRequest; class ControllerCollection extends BaseControllerCollection { @@ -31,12 +33,10 @@ private function wrapController($controller) { $resolver = $this->resolver; - return function (Request $sfRequest) use ($controller, $resolver) { - $request = $sfRequest->attributes->get('react.espresso.request'); - $response = $sfRequest->attributes->get('react.espresso.response'); + return function (Request $request, Response $response) use ($controller, $resolver) { if (!is_callable($controller)) { - $controller = $resolver->getController($sfRequest); + $controller = $resolver->getController(SymfonyRequest::create($request->getPath(), $request->getMethod())); } call_user_func($controller, $request, $response); From 63967b5f6933bf0a5c8e6a63a9cd864f561c918a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=B6nthal?= Date: Fri, 31 Oct 2014 18:22:21 +0100 Subject: [PATCH 4/5] fixed exception handling --- src/React/Espresso/Application.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/React/Espresso/Application.php b/src/React/Espresso/Application.php index 85bf0e8..aeef878 100644 --- a/src/React/Espresso/Application.php +++ b/src/React/Espresso/Application.php @@ -32,7 +32,9 @@ public function __invoke(Request $request, Response $response) $response->end($e->getMessage()); } catch (\Exception $e) { $response->writeHead(500); - $response->end($e->getMessage()); + $response->write($e->getMessage()."\n"); + $response->write($e->getFile()."\n"); + $response->end($e->getTraceAsString()."\n"); } } From 458d5936083d75ff3d08625610ab4dbab904bfcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=B6nthal?= Date: Fri, 31 Oct 2014 16:26:34 +0100 Subject: [PATCH 5/5] upstream fixes, simplified controller resolving --- README.md | 45 +- composer.json | 4 +- composer.lock | 417 ++++++++---------- src/React/Espresso/Application.php | 35 +- src/React/Espresso/ControllerCollection.php | 29 -- .../React/Tests/Espresso/ApplicationTest.php | 14 +- 6 files changed, 233 insertions(+), 311 deletions(-) delete mode 100644 src/React/Espresso/ControllerCollection.php diff --git a/README.md b/README.md index a6848a3..f3b6f44 100644 --- a/README.md +++ b/README.md @@ -10,42 +10,41 @@ React/Http. The recommended way to install react/espresso is [through composer](http://getcomposer.org). -```JSON -{ - "require": { - "minimum-stability": "dev", - "react/espresso": "0.2.*" - } -} +``` +$ composer require react/espresso ``` ## Example - $app = new React\Espresso\Application(); +> all your Controllers stay the same, the converting between symfony request/response and react request/response is completely shallow + +```php +get('/', function ($request, $response) { - $response->writeHead(200, array('Content-Type' => 'text/plain')); - $response->end("Hello World\n"); - }); +$app = new React\Espresso\Application(); - $app->get('/favicon.ico', function ($request, $response) { - $response->writeHead(204); - $response->end(); - }); +$app->get('/hello/{name}', function ($name) use ($app) { + return 'Hello '.$app->escape($name); +}); + +$stack = new React\Espresso\Stack($app); +$stack->listen(1337); +``` - $app->get('/humans.txt', function ($request, $response) { - $response->writeHead(200, array('Content-Type' => 'text/plain')); - $response->end("I believe you are a humanoid robot.\n"); - }); +``` +$ php react.php +``` - $stack = new React\Espresso\Stack($app); - $stack->listen(1337); +> now visit [http://localhost:1337/hello/react](http://localhost:1337/hello/react) ## Tests To run the test suite, you need PHPUnit. - $ phpunit +``` +$ phpunit +``` ## License diff --git a/composer.json b/composer.json index 9b97706..7a1e2d9 100644 --- a/composer.json +++ b/composer.json @@ -5,8 +5,8 @@ "license": "MIT", "require": { "php": ">=5.3.3", - "react/http": "0.2.*", - "silex/silex": "1.0.*@dev" + "react/http": "~0.4", + "silex/silex": "~1.0" }, "autoload": { "psr-0": { "React\\Espresso": "src" } diff --git a/composer.lock b/composer.lock index d7136b4..c63c718 100644 --- a/composer.lock +++ b/composer.lock @@ -4,31 +4,37 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "d4cf6de577e04afb0122b0d2e761e06b", + "hash": "3e8eedf7bb73aaad62069488ab1dd9d8", "packages": [ { "name": "evenement/evenement", - "version": "v1.0.0", + "version": "v2.0.0", "source": { "type": "git", - "url": "https://github.com/igorw/evenement", - "reference": "v1.0.0" + "url": "https://github.com/igorw/evenement.git", + "reference": "f6e843799fd4f4184d54d8fc7b5b3551c9fa803e" }, "dist": { "type": "zip", - "url": "https://github.com/igorw/evenement/zipball/v1.0.0", - "reference": "v1.0.0", + "url": "https://api.github.com/repos/igorw/evenement/zipball/f6e843799fd4f4184d54d8fc7b5b3551c9fa803e", + "reference": "f6e843799fd4f4184d54d8fc7b5b3551c9fa803e", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, "autoload": { "psr-0": { "Evenement": "src" } }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -39,114 +45,37 @@ "homepage": "http://wiedler.ch/igor/" } ], - "description": "Événement is a very simple event dispatching library for PHP 5.3", - "keywords": [ - "event-dispatcher" - ], - "time": "2012-05-30 08:01:08" - }, - { - "name": "guzzle/common", - "version": "v2.8.8", - "target-dir": "Guzzle/Common", - "source": { - "type": "git", - "url": "git://github.com/guzzle/common.git", - "reference": "v2.8.8" - }, - "dist": { - "type": "zip", - "url": "https://github.com/guzzle/common/zipball/v2.8.8", - "reference": "v2.8.8", - "shasum": "" - }, - "require": { - "php": ">=5.3.2", - "symfony/event-dispatcher": "2.1.*" - }, - "type": "library", - "autoload": { - "psr-0": { - "Guzzle\\Common": "" - } - }, - "license": [ - "MIT" - ], - "description": "Common libraries used by Guzzle", - "homepage": "http://guzzlephp.org/", + "description": "Événement is a very simple event dispatching library for PHP", "keywords": [ - "Socket", - "batch", - "cache", - "common", - "event", - "inflection", - "log", - "validation" + "event-dispatcher", + "event-emitter" ], - "time": "2012-10-15 17:42:47" - }, - { - "name": "guzzle/http", - "version": "v2.8.8", - "target-dir": "Guzzle/Http", - "source": { - "type": "git", - "url": "https://github.com/guzzle/http.git", - "reference": "1fe3a2cf45b2984934d8a74e2bb4bd6a1de9c357" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/http/zipball/1fe3a2cf45b2984934d8a74e2bb4bd6a1de9c357", - "reference": "1fe3a2cf45b2984934d8a74e2bb4bd6a1de9c357", - "shasum": "" - }, - "require": { - "guzzle/common": "self.version", - "guzzle/parser": "self.version", - "php": ">=5.3.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "Guzzle\\Http": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "HTTP libraries used by Guzzle", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "Guzzle", - "client", - "curl", - "http", - "http client" - ], - "time": "2012-10-16 00:42:47" + "time": "2012-11-02 14:49:47" }, { "name": "guzzle/parser", - "version": "v2.8.8", + "version": "v3.9.2", "target-dir": "Guzzle/Parser", "source": { "type": "git", "url": "https://github.com/guzzle/parser.git", - "reference": "8f5152833af2d9505bcefb0a10c4b6987aa9a6b1" + "reference": "6874d171318a8e93eb6d224cf85e4678490b625c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/parser/zipball/8f5152833af2d9505bcefb0a10c4b6987aa9a6b1", - "reference": "8f5152833af2d9505bcefb0a10c4b6987aa9a6b1", + "url": "https://api.github.com/repos/guzzle/parser/zipball/6874d171318a8e93eb6d224cf85e4678490b625c", + "reference": "6874d171318a8e93eb6d224cf85e4678490b625c", "shasum": "" }, "require": { "php": ">=5.3.2" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7-dev" + } + }, "autoload": { "psr-0": { "Guzzle\\Parser": "" @@ -165,7 +94,7 @@ "message", "url" ], - "time": "2012-09-20 20:28:06" + "time": "2014-02-05 18:29:46" }, { "name": "pimple/pimple", @@ -253,35 +182,35 @@ }, { "name": "react/event-loop", - "version": "v0.2.7", - "target-dir": "React/EventLoop", + "version": "v0.4.1", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "134b94dc555d320bd31253a215c8a65ef151a79a" + "reference": "18c5297087ca01de85518e2b55078f444144aa1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/134b94dc555d320bd31253a215c8a65ef151a79a", - "reference": "134b94dc555d320bd31253a215c8a65ef151a79a", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/18c5297087ca01de85518e2b55078f444144aa1b", + "reference": "18c5297087ca01de85518e2b55078f444144aa1b", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.4.0" }, "suggest": { + "ext-event": "~1.0", "ext-libev": "*", - "ext-libevent": ">=0.0.5" + "ext-libevent": ">=0.1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.2-dev" + "dev-master": "0.4-dev" } }, "autoload": { - "psr-0": { - "React\\EventLoop": "" + "psr-4": { + "React\\EventLoop\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -292,36 +221,36 @@ "keywords": [ "event-loop" ], - "time": "2013-01-05 11:41:26" + "time": "2014-02-26 17:36:58" }, { "name": "react/http", - "version": "v0.2.2", - "target-dir": "React/Http", + "version": "v0.4.0", "source": { "type": "git", "url": "https://github.com/reactphp/http.git", - "reference": "43badbc510d416a482fe967eb300137bf7f7f18b" + "reference": "7b9d293b7a3f73acd840a341497e267d8562d637" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/http/zipball/43badbc510d416a482fe967eb300137bf7f7f18b", - "reference": "43badbc510d416a482fe967eb300137bf7f7f18b", + "url": "https://api.github.com/repos/reactphp/http/zipball/7b9d293b7a3f73acd840a341497e267d8562d637", + "reference": "7b9d293b7a3f73acd840a341497e267d8562d637", "shasum": "" }, "require": { - "guzzle/http": "2.8.*", - "guzzle/parser": "2.8.*", - "php": ">=5.3.3", - "react/socket": "0.2.*" + "guzzle/parser": "~3.0", + "php": ">=5.4.0", + "react/socket": "0.4.*" }, "type": "library", "extra": { - "branch-alias": [] + "branch-alias": { + "dev-master": "0.4-dev" + } }, "autoload": { - "psr-0": { - "React\\Http": "" + "psr-4": { + "React\\Http\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -332,38 +261,37 @@ "keywords": [ "http" ], - "time": "2012-10-28 10:28:35" + "time": "2014-02-02 01:11:26" }, { "name": "react/socket", - "version": "v0.2.6", - "target-dir": "React/Socket", + "version": "v0.4.2", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "21e3fe670b2f18e3c6b2cb73f14e1c58fe7bca84" + "reference": "a6acf405ca53fc6cfbfe7c77778ededff46aa7cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/21e3fe670b2f18e3c6b2cb73f14e1c58fe7bca84", - "reference": "21e3fe670b2f18e3c6b2cb73f14e1c58fe7bca84", + "url": "https://api.github.com/repos/reactphp/socket/zipball/a6acf405ca53fc6cfbfe7c77778ededff46aa7cc", + "reference": "a6acf405ca53fc6cfbfe7c77778ededff46aa7cc", "shasum": "" }, "require": { - "evenement/evenement": "1.0.*", - "php": ">=5.3.3", - "react/event-loop": "0.2.*", - "react/stream": "0.2.*" + "evenement/evenement": "~2.0", + "php": ">=5.4.0", + "react/event-loop": "0.4.*", + "react/stream": "0.4.*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.2-dev" + "dev-master": "0.4-dev" } }, "autoload": { - "psr-0": { - "React\\Socket": "" + "psr-4": { + "React\\Socket\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -374,39 +302,46 @@ "keywords": [ "Socket" ], - "time": "2012-12-14 00:58:14" + "time": "2014-05-25 17:02:16" }, { "name": "react/stream", - "version": "v0.2.1", - "target-dir": "React/Stream", + "version": "v0.4.2", "source": { "type": "git", - "url": "https://github.com/reactphp/stream", - "reference": "v0.2.1" + "url": "https://github.com/reactphp/stream.git", + "reference": "acc7a5fec02e0aea674560e1d13c40ed0c8c5465" }, "dist": { "type": "zip", - "url": "https://github.com/reactphp/stream/zipball/v0.2.1", - "reference": "v0.2.1", + "url": "https://api.github.com/repos/reactphp/stream/zipball/acc7a5fec02e0aea674560e1d13c40ed0c8c5465", + "reference": "acc7a5fec02e0aea674560e1d13c40ed0c8c5465", "shasum": "" }, "require": { - "evenement/evenement": "1.0.*", - "php": ">=5.3.3" + "evenement/evenement": "~2.0", + "php": ">=5.4.0" + }, + "require-dev": { + "react/event-loop": "0.4.*", + "react/promise": "~2.0" }, "suggest": { - "react/event-loop": "0.2.*" + "react/event-loop": "0.4.*", + "react/promise": "~2.0" }, "type": "library", "extra": { - "branch-alias": [] + "branch-alias": { + "dev-master": "0.5-dev" + } }, "autoload": { - "psr-0": { - "React\\Stream": "" + "psr-4": { + "React\\Stream\\": "src" } }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -415,61 +350,63 @@ "pipe", "stream" ], - "time": "2012-10-13 13:12:04" + "time": "2014-09-10 03:32:31" }, { "name": "silex/silex", - "version": "1.0.x-dev", + "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/silexphp/Silex.git", - "reference": "75b8714f00bf4e64eedc0d9283b03eb05af67196" + "reference": "8c5e86eb97f3eee633729b22e950082fb5591328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Silex/zipball/75b8714f00bf4e64eedc0d9283b03eb05af67196", - "reference": "75b8714f00bf4e64eedc0d9283b03eb05af67196", + "url": "https://api.github.com/repos/silexphp/Silex/zipball/8c5e86eb97f3eee633729b22e950082fb5591328", + "reference": "8c5e86eb97f3eee633729b22e950082fb5591328", "shasum": "" }, "require": { "php": ">=5.3.3", - "pimple/pimple": "1.*", - "symfony/event-dispatcher": ">=2.1,<2.4-dev", - "symfony/http-foundation": ">=2.1,<2.4-dev", - "symfony/http-kernel": ">=2.1,<2.4-dev", - "symfony/routing": ">=2.1,<2.4-dev" + "pimple/pimple": "~1.0", + "symfony/event-dispatcher": ">=2.3,<2.6-dev", + "symfony/http-foundation": ">=2.3,<2.6-dev", + "symfony/http-kernel": ">=2.3,<2.6-dev", + "symfony/routing": ">=2.3,<2.6-dev" }, "require-dev": { - "doctrine/dbal": ">=2.2.0,<2.4.0-dev", + "doctrine/dbal": "~2.2", "monolog/monolog": "~1.4,>=1.4.1", + "phpunit/phpunit": "~3.7", "swiftmailer/swiftmailer": "5.*", - "symfony/browser-kit": ">=2.1,<2.4-dev", - "symfony/config": ">=2.1,<2.4-dev", - "symfony/css-selector": ">=2.1,<2.4-dev", - "symfony/dom-crawler": ">=2.1,<2.4-dev", - "symfony/finder": ">=2.1,<2.4-dev", - "symfony/form": ">=2.1.4,<2.4-dev", - "symfony/locale": ">=2.1,<2.4-dev", - "symfony/monolog-bridge": ">=2.1,<2.4-dev", - "symfony/options-resolver": ">=2.1,<2.4-dev", - "symfony/process": ">=2.1,<2.4-dev", - "symfony/security": ">=2.1,<2.4-dev", - "symfony/serializer": ">=2.1,<2.4-dev", - "symfony/translation": ">=2.1,<2.4-dev", - "symfony/twig-bridge": ">=2.1,<2.4-dev", - "symfony/validator": ">=2.1,<2.4-dev", + "symfony/browser-kit": ">=2.3,<2.6-dev", + "symfony/config": ">=2.3,<2.6-dev", + "symfony/css-selector": ">=2.3,<2.6-dev", + "symfony/debug": ">=2.3,<2.6-dev", + "symfony/dom-crawler": ">=2.3,<2.6-dev", + "symfony/finder": ">=2.3,<2.6-dev", + "symfony/form": ">=2.3,<2.6-dev", + "symfony/locale": ">=2.3,<2.6-dev", + "symfony/monolog-bridge": ">=2.3,<2.6-dev", + "symfony/options-resolver": ">=2.3,<2.6-dev", + "symfony/process": ">=2.3,<2.6-dev", + "symfony/security": ">=2.3,<2.6-dev", + "symfony/serializer": ">=2.3,<2.6-dev", + "symfony/translation": ">=2.3,<2.6-dev", + "symfony/twig-bridge": ">=2.3,<2.6-dev", + "symfony/validator": ">=2.3,<2.6-dev", "twig/twig": ">=1.8.0,<2.0-dev" }, "suggest": { - "symfony/browser-kit": ">=2.1,<2.4-dev", - "symfony/css-selector": ">=2.1,<2.4-dev", - "symfony/dom-crawler": ">=2.1,<2.4-dev", - "symfony/form": ">= 2.1.4,<2.4-dev" + "symfony/browser-kit": ">=2.3,<2.6-dev", + "symfony/css-selector": ">=2.3,<2.6-dev", + "symfony/dom-crawler": ">=2.3,<2.6-dev", + "symfony/form": ">=2.3,<2.6-dev" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -484,14 +421,11 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" + "email": "fabien@symfony.com" }, { "name": "Igor Wiedler", - "email": "igor@wiedler.ch", - "homepage": "http://wiedler.ch/igor/" + "email": "igor@wiedler.ch" } ], "description": "The PHP micro-framework based on the Symfony2 Components", @@ -499,25 +433,26 @@ "keywords": [ "microframework" ], - "time": "2014-06-06 05:48:07" + "time": "2014-09-26 09:32:30" }, { "name": "symfony/debug", - "version": "v2.5.6", + "version": "v2.6.0", "target-dir": "Symfony/Component/Debug", "source": { "type": "git", "url": "https://github.com/symfony/Debug.git", - "reference": "2538d5099b9728b6ca09b261566a766f4f847459" + "reference": "e1e27710efabc3f67a2d1f6710641b3bdca289d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Debug/zipball/2538d5099b9728b6ca09b261566a766f4f847459", - "reference": "2538d5099b9728b6ca09b261566a766f4f847459", + "url": "https://api.github.com/repos/symfony/Debug/zipball/e1e27710efabc3f67a2d1f6710641b3bdca289d3", + "reference": "e1e27710efabc3f67a2d1f6710641b3bdca289d3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.3", + "psr/log": "~1.0" }, "require-dev": { "symfony/http-foundation": "~2.1", @@ -530,7 +465,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -554,83 +489,90 @@ ], "description": "Symfony Debug Component", "homepage": "http://symfony.com", - "time": "2014-10-24 05:49:22" + "time": "2014-11-28 10:00:40" }, { "name": "symfony/event-dispatcher", - "version": "v2.1.2", + "version": "v2.5.7", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", - "url": "https://github.com/symfony/EventDispatcher", - "reference": "v2.1.2" + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "bb6fc12085cd195dceaf48016087b12b632df497" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/EventDispatcher/zipball/v2.1.2", - "reference": "v2.1.2", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/bb6fc12085cd195dceaf48016087b12b632df497", + "reference": "bb6fc12085cd195dceaf48016087b12b632df497", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "symfony/dependency-injection": "2.1.*" + "psr/log": "~1.0", + "symfony/config": "~2.0", + "symfony/dependency-injection": "~2.0,<2.6.0", + "symfony/stopwatch": "~2.2" }, "suggest": { - "symfony/dependency-injection": "2.1.*", - "symfony/http-kernel": "2.1.*" + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.5-dev" } }, "autoload": { "psr-0": { - "Symfony\\Component\\EventDispatcher": "" + "Symfony\\Component\\EventDispatcher\\": "" } }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony EventDispatcher Component", "homepage": "http://symfony.com", - "time": "2012-09-10 03:53:42" + "time": "2014-10-30 20:17:55" }, { "name": "symfony/http-foundation", - "version": "v2.3.21", + "version": "v2.5.7", "target-dir": "Symfony/Component/HttpFoundation", "source": { "type": "git", "url": "https://github.com/symfony/HttpFoundation.git", - "reference": "30c90f08f948dd43e7310beae7a85c02ad2b655d" + "reference": "24545d3def96e6d6c3d7f1efdb48f330f27e244d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/30c90f08f948dd43e7310beae7a85c02ad2b655d", - "reference": "30c90f08f948dd43e7310beae7a85c02ad2b655d", + "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/24545d3def96e6d6c3d7f1efdb48f330f27e244d", + "reference": "24545d3def96e6d6c3d7f1efdb48f330f27e244d", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "symfony/expression-language": "~2.4" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -657,29 +599,29 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "http://symfony.com", - "time": "2014-10-23 13:11:04" + "time": "2014-11-20 13:22:25" }, { "name": "symfony/http-kernel", - "version": "v2.3.21", + "version": "v2.5.7", "target-dir": "Symfony/Component/HttpKernel", "source": { "type": "git", "url": "https://github.com/symfony/HttpKernel.git", - "reference": "0154ff659004d4148e8da0f2bdb672efe55e6ee5" + "reference": "03b9f8fbfe75044ff6ca923e6471f117faf7b965" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/0154ff659004d4148e8da0f2bdb672efe55e6ee5", - "reference": "0154ff659004d4148e8da0f2bdb672efe55e6ee5", + "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/03b9f8fbfe75044ff6ca923e6471f117faf7b965", + "reference": "03b9f8fbfe75044ff6ca923e6471f117faf7b965", "shasum": "" }, "require": { "php": ">=5.3.3", "psr/log": "~1.0", - "symfony/debug": "~2.3", - "symfony/event-dispatcher": "~2.1", - "symfony/http-foundation": "~2.2" + "symfony/debug": "~2.5", + "symfony/event-dispatcher": "~2.5", + "symfony/http-foundation": "~2.5" }, "require-dev": { "symfony/browser-kit": "~2.2", @@ -687,6 +629,7 @@ "symfony/config": "~2.0", "symfony/console": "~2.2", "symfony/dependency-injection": "~2.0", + "symfony/expression-language": "~2.4", "symfony/finder": "~2.0", "symfony/process": "~2.0", "symfony/routing": "~2.2", @@ -704,7 +647,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -728,42 +671,44 @@ ], "description": "Symfony HttpKernel Component", "homepage": "http://symfony.com", - "time": "2014-10-24 05:54:08" + "time": "2014-11-20 16:00:03" }, { "name": "symfony/routing", - "version": "v2.3.21", + "version": "v2.5.7", "target-dir": "Symfony/Component/Routing", "source": { "type": "git", "url": "https://github.com/symfony/Routing.git", - "reference": "f7f8ebf9c99e5ebfdb908c3558a818c2883eab1f" + "reference": "f3f5f31d5e227c51eed7ba8b1ed809a97ebaa341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Routing/zipball/f7f8ebf9c99e5ebfdb908c3558a818c2883eab1f", - "reference": "f7f8ebf9c99e5ebfdb908c3558a818c2883eab1f", + "url": "https://api.github.com/repos/symfony/Routing/zipball/f3f5f31d5e227c51eed7ba8b1ed809a97ebaa341", + "reference": "f3f5f31d5e227c51eed7ba8b1ed809a97ebaa341", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "doctrine/common": "~2.2", + "doctrine/annotations": "~1.0", "psr/log": "~1.0", "symfony/config": "~2.2", + "symfony/expression-language": "~2.4", "symfony/http-foundation": "~2.3", "symfony/yaml": "~2.0" }, "suggest": { - "doctrine/common": "", - "symfony/config": "", - "symfony/yaml": "" + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/yaml": "For using the YAML loader" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -787,15 +732,19 @@ ], "description": "Symfony Routing Component", "homepage": "http://symfony.com", - "time": "2014-10-13 12:38:27" + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2014-11-03 20:24:10" } ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "silex/silex": 20 - }, + "stability-flags": [], "prefer-stable": false, "platform": { "php": ">=5.3.3" diff --git a/src/React/Espresso/Application.php b/src/React/Espresso/Application.php index 4bd9d67..3e13348 100644 --- a/src/React/Espresso/Application.php +++ b/src/React/Espresso/Application.php @@ -6,30 +6,39 @@ use React\Http\Response; use Silex\Application as BaseApplication; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\HttpKernelInterface; class Application extends BaseApplication { - public function __construct() - { - parent::__construct(); - - $app = $this; - - $this['controllers_factory'] = function () use ($app) { - return new ControllerCollection($app['route_factory']); - }; - } + /** + * @param Request $request + * @param Response $response + * @throws \Exception + */ public function __invoke(Request $request, Response $response) { - $sfRequest = $this->buildSymfonyRequest($request, $response); - $this->handle($sfRequest, HttpKernelInterface::MASTER_REQUEST, false); + try { + $sfRequest = $this->buildSymfonyRequest($request, $response); + $r = $this->handle($sfRequest, HttpKernelInterface::MASTER_REQUEST, false); + /** @var \Symfony\Component\HttpFoundation\Response $r */ + $response->writeHead($r->getStatusCode(), $r->headers->all()); + $response->end($r->getContent()); + } catch (\Exception $e) { + $response->writeHead($e instanceof HttpException ? $e->getStatusCode() : 500); + $response->end($e->getMessage()); + } } + /** + * @param Request $request + * @param Response $response + * @return SymfonyRequest + */ private function buildSymfonyRequest(Request $request, Response $response) { - $sfRequest = SymfonyRequest::create($request->getPath(), $request->getMethod()); + $sfRequest = SymfonyRequest::create($request->getPath(), $request->getMethod(), $request->getQuery()); $sfRequest->attributes->set('react.espresso.request', $request); $sfRequest->attributes->set('react.espresso.response', $response); diff --git a/src/React/Espresso/ControllerCollection.php b/src/React/Espresso/ControllerCollection.php deleted file mode 100644 index e50faf6..0000000 --- a/src/React/Espresso/ControllerCollection.php +++ /dev/null @@ -1,29 +0,0 @@ -wrapController($to); - - return parent::match($pattern, $wrapped); - } - - private function wrapController($controller) - { - return function (Request $sfRequest) use ($controller) { - $request = $sfRequest->attributes->get('react.espresso.request'); - $response = $sfRequest->attributes->get('react.espresso.response'); - - call_user_func($controller, $request, $response); - - return new SymfonyStreamedResponse(); - }; - } -} diff --git a/tests/React/Tests/Espresso/ApplicationTest.php b/tests/React/Tests/Espresso/ApplicationTest.php index 4cb4286..2f2db39 100644 --- a/tests/React/Tests/Espresso/ApplicationTest.php +++ b/tests/React/Tests/Espresso/ApplicationTest.php @@ -3,7 +3,6 @@ namespace React\Tests\Espresso; use React\Espresso\Application; -use React\Espresso\Stack; use React\Http\Request; use React\Http\Response; @@ -13,20 +12,15 @@ public function testApplicationWithGetRequest() { $app = new Application(); - $app->get('/', function ($request, $response) { - $response->writeHead(200, array('Content-Type' => 'text/plain')); - $response->end("Hello World\n"); + $app->get('/', function (\Symfony\Component\HttpFoundation\Request $request) { + return new \Symfony\Component\HttpFoundation\Response('Hello World'); }); $conn = $this->getMock('React\Socket\ConnectionInterface'); $conn - ->expects($this->at(0)) + ->expects($this->atLeastOnce()) ->method('write') - ->with($this->stringContains("text/plain")); - $conn - ->expects($this->at(1)) - ->method('write') - ->with($this->stringContains("Hello World\n")); + ->with($this->isType('string')); $request = new Request('GET', '/'); $response = new Response($conn);