removed the need for a proxy route for rendering strategies

This commit is contained in:
Fabien Potencier 2013-01-22 09:30:21 +01:00
parent b9f0e17e67
commit ad82893691
16 changed files with 128 additions and 274 deletions

View File

@ -22,7 +22,6 @@
<service id="http_content_renderer.strategy.default" class="%http_content_renderer.strategy.default.class%">
<tag name="kernel.content_renderer_strategy" />
<argument type="service" id="http_kernel" />
<call method="setUrlGenerator"><argument type="service" id="router" /></call>
</service>
<service id="http_content_renderer.strategy.hinclude" class="%http_content_renderer.strategy.hinclude.class%">
@ -30,7 +29,6 @@
<argument type="service" id="templating" on-invalid="null" />
<argument type="service" id="uri_signer" />
<argument>%http_content_renderer.strategy.hinclude.global_template%</argument>
<call method="setUrlGenerator"><argument type="service" id="router" /></call>
</service>
<!-- FIXME: make the listener registration optional via a configuration setting? -->

View File

@ -22,7 +22,6 @@
<tag name="kernel.content_renderer_strategy" />
<argument type="service" id="esi" />
<argument type="service" id="http_content_renderer.strategy.default" />
<call method="setUrlGenerator"><argument type="service" id="router" /></call>
</service>
</services>
</container>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="_proxy" pattern="/_proxy/controller/{_controller}/format/{_format}">
<requirement key="_controller">.+</requirement>
</route>
</routes>

View File

@ -47,7 +47,7 @@ class RouterProxyListener implements EventSubscriberInterface
{
$request = $event->getRequest();
if ('_proxy' !== $request->attributes->get('_route')) {
if ('/_proxy' !== rawurldecode($request->getPathInfo())) {
return;
}
@ -92,7 +92,7 @@ class RouterProxyListener implements EventSubscriberInterface
public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => array(array('onKernelRequest', 16)),
KernelEvents::REQUEST => array(array('onKernelRequest', 48)),
);
}
}

View File

@ -21,7 +21,7 @@ use Symfony\Component\HttpKernel\Controller\ControllerReference;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class DefaultRenderingStrategy extends GeneratorAwareRenderingStrategy
class DefaultRenderingStrategy extends ProxyAwareRenderingStrategy
{
private $kernel;

View File

@ -21,7 +21,7 @@ use Symfony\Component\HttpKernel\HttpCache\Esi;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class EsiRenderingStrategy extends GeneratorAwareRenderingStrategy
class EsiRenderingStrategy extends ProxyAwareRenderingStrategy
{
private $esi;
private $defaultStrategy;

View File

@ -1,82 +0,0 @@
<?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\Component\HttpKernel\RenderingStrategy;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
/**
* Adds the possibility to generate a proxy URI for a given Controller.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class GeneratorAwareRenderingStrategy implements RenderingStrategyInterface
{
protected $generator;
/**
* Sets a URL generator to use for proxy URIs generation.
*
* @param UrlGeneratorInterface $generator An UrlGeneratorInterface instance
*/
public function setUrlGenerator(UrlGeneratorInterface $generator)
{
$this->generator = $generator;
}
/**
* Generates a proxy URI for a given controller.
*
* This method only works when using the Symfony Routing component and
* if a "_proxy" route is defined with a {_controller} and {_format}
* placeholders.
*
* @param ControllerReference $reference A ControllerReference instance
* @param Request $request A Request instance
*
* @return string A proxy URI
*
* @throws \LogicException when the _proxy route is not available
* @throws \LogicException when there is no registered route generator
*/
protected function generateProxyUri(ControllerReference $reference, Request $request)
{
if (null === $this->generator) {
throw new \LogicException('Unable to generate a proxy URL as there is no registered route generator.');
}
if (isset($reference->attributes['_format'])) {
$format = $reference->attributes['_format'];
unset($reference->attributes['_format']);
} else {
$format = $request->getRequestFormat();
}
try {
$uri = $this->generator->generate('_proxy', array('_controller' => $reference->controller, '_format' => $format), UrlGeneratorInterface::ABSOLUTE_URL);
} catch (RouteNotFoundException $e) {
throw new \LogicException('Unable to generate a proxy URL as the "_proxy" route is not registered.', 0, $e);
}
if ($path = http_build_query($reference->attributes, '', '&')) {
$reference->query['path'] = $path;
}
if ($qs = http_build_query($reference->query, '', '&')) {
$uri .= '?'.$qs;
}
return $uri;
}
}

View File

@ -22,7 +22,7 @@ use Symfony\Component\HttpKernel\UriSigner;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HIncludeRenderingStrategy extends GeneratorAwareRenderingStrategy
class HIncludeRenderingStrategy extends ProxyAwareRenderingStrategy
{
private $templating;
private $globalDefaultTemplate;

View File

@ -0,0 +1,44 @@
<?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\Component\HttpKernel\RenderingStrategy;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpFoundation\Request;
/**
* Adds the possibility to generate a proxy URI for a given Controller.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class ProxyAwareRenderingStrategy implements RenderingStrategyInterface
{
/**
* Generates a proxy URI for a given controller.
*
* @param ControllerReference $reference A ControllerReference instance
* @param Request $request A Request instance
*
* @return string A proxy URI
*/
protected function generateProxyUri(ControllerReference $reference, Request $request)
{
if (!isset($reference->attributes['_format'])) {
$reference->attributes['_format'] = $request->getRequestFormat();
}
$reference->attributes['_controller'] = $reference->controller;
$reference->query['path'] = http_build_query($reference->attributes, '', '&');
return $request->getUriForPath('/_proxy?'.http_build_query($reference->query, '', '&'));
}
}

View File

@ -28,10 +28,10 @@ class RouterProxyListenerTest extends \PHPUnit_Framework_TestCase
public function testOnlyTriggeredOnProxyRoute()
{
$request = Request::create('http://example.com/foo?path=foo%3D=bar');
$request = Request::create('http://example.com/foo?path=foo%3Dbar%26_controller%3Dfoo');
$listener = new RouterProxyListener(new UriSigner('foo'));
$event = $this->createGetResponseEvent($request, 'foobar');
$event = $this->createGetResponseEvent($request);
$expected = $request->attributes->all();
@ -46,7 +46,7 @@ class RouterProxyListenerTest extends \PHPUnit_Framework_TestCase
*/
public function testAccessDeniedWithNonSafeMethods()
{
$request = Request::create('http://example.com/foo', 'POST');
$request = Request::create('http://example.com/_proxy', 'POST');
$listener = new RouterProxyListener(new UriSigner('foo'));
$event = $this->createGetResponseEvent($request);
@ -59,7 +59,7 @@ class RouterProxyListenerTest extends \PHPUnit_Framework_TestCase
*/
public function testAccessDeniedWithNonLocalIps()
{
$request = Request::create('http://example.com/foo', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
$request = Request::create('http://example.com/_proxy', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
$listener = new RouterProxyListener(new UriSigner('foo'));
$event = $this->createGetResponseEvent($request);
@ -72,7 +72,7 @@ class RouterProxyListenerTest extends \PHPUnit_Framework_TestCase
*/
public function testAccessDeniedWithWrongSignature()
{
$request = Request::create('http://example.com/foo', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
$request = Request::create('http://example.com/_proxy', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
$listener = new RouterProxyListener(new UriSigner('foo'));
$event = $this->createGetResponseEvent($request);
@ -80,40 +80,22 @@ class RouterProxyListenerTest extends \PHPUnit_Framework_TestCase
$listener->onKernelRequest($event);
}
public function testWithSignatureAndNoPath()
public function testWithSignature()
{
$signer = new UriSigner('foo');
$request = Request::create($signer->sign('http://example.com/foo'), 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
$request = Request::create($signer->sign('http://example.com/_proxy?path=foo%3Dbar%26_controller%3Dfoo'), 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
$listener = new RouterProxyListener($signer);
$event = $this->createGetResponseEvent($request);
$listener->onKernelRequest($event);
$this->assertEquals(array('foo' => 'foo'), $request->attributes->get('_route_params'));
$this->assertEquals(array('foo' => 'bar', '_controller' => 'foo'), $request->attributes->get('_route_params'));
$this->assertFalse($request->query->has('path'));
}
public function testWithSignatureAndPath()
private function createGetResponseEvent(Request $request)
{
$signer = new UriSigner('foo');
$request = Request::create($signer->sign('http://example.com/foo?path=bar%3Dbar'), 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
$listener = new RouterProxyListener($signer);
$event = $this->createGetResponseEvent($request);
$listener->onKernelRequest($event);
$this->assertEquals(array('foo' => 'foo', 'bar' => 'bar'), $request->attributes->get('_route_params'));
$this->assertFalse($request->query->has('path'));
}
private function createGetResponseEvent(Request $request, $route = '_proxy')
{
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$request->attributes->set('_route', $route);
$request->attributes->set('_route_params', array('foo' => 'foo'));
return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
return new GetResponseEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST);
}
}

View File

@ -1,29 +0,0 @@
<?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\Component\HttpKernel\Tests\RenderingStrategy;
abstract class AbstractRenderingStrategyTest extends \PHPUnit_Framework_TestCase
{
protected function getUrlGenerator()
{
$generator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface');
$generator
->expects($this->any())
->method('generate')
->will($this->returnCallback(function ($name, $parameters, $referenceType) {
return '/'.$parameters['_controller'].'.'.$parameters['_format'];
}))
;
return $generator;
}
}

View File

@ -18,7 +18,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;
class DefaultRenderingStrategyTest extends AbstractRenderingStrategyTest
class DefaultRenderingStrategyTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
@ -41,7 +41,6 @@ class DefaultRenderingStrategyTest extends AbstractRenderingStrategyTest
public function testRenderWithControllerReference()
{
$strategy = new DefaultRenderingStrategy($this->getKernel($this->returnValue(new Response('foo'))));
$strategy->setUrlGenerator($this->getUrlGenerator());
$this->assertEquals('foo', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent());
}

View File

@ -16,17 +16,13 @@ use Symfony\Component\HttpKernel\RenderingStrategy\EsiRenderingStrategy;
use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpFoundation\Request;
class EsiRenderingStrategyTest extends AbstractRenderingStrategyTest
class EsiRenderingStrategyTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
if (!interface_exists('Symfony\Component\Routing\Generator\UrlGeneratorInterface')) {
$this->markTestSkipped('The "Routing" component is not available');
}
}
public function testRenderFallbackToDefaultStrategyIfNoRequest()
@ -44,7 +40,6 @@ class EsiRenderingStrategyTest extends AbstractRenderingStrategyTest
public function testRender()
{
$strategy = new EsiRenderingStrategy(new Esi(), $this->getDefaultStrategy());
$strategy->setUrlGenerator($this->getUrlGenerator());
$request = Request::create('/');
$request->headers->set('Surrogate-Capability', 'ESI/1.0');
@ -52,7 +47,7 @@ class EsiRenderingStrategyTest extends AbstractRenderingStrategyTest
$this->assertEquals('<esi:include src="/" />', $strategy->render('/', $request)->getContent());
$this->assertEquals("<esi:comment text=\"This is a comment\" />\n<esi:include src=\"/\" />", $strategy->render('/', $request, array('comment' => 'This is a comment'))->getContent());
$this->assertEquals('<esi:include src="/" alt="foo" />', $strategy->render('/', $request, array('alt' => 'foo'))->getContent());
$this->assertEquals('<esi:include src="/main_controller.html" alt="/alt_controller.html" />', $strategy->render(new ControllerReference('main_controller', array(), array()), $request, array('alt' => new ControllerReference('alt_controller', array(), array())))->getContent());
$this->assertEquals('<esi:include src="http://localhost/_proxy?path=_format%3Dhtml%26_controller%3Dmain_controller" alt="http://localhost/_proxy?path=_format%3Dhtml%26_controller%3Dalt_controller" />', $strategy->render(new ControllerReference('main_controller', array(), array()), $request, array('alt' => new ControllerReference('alt_controller', array(), array())))->getContent());
}
private function getDefaultStrategy($called = false)

View File

@ -1,101 +0,0 @@
<?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\Component\HttpKernel\Tests\RenderingStrategy;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\RenderingStrategy\GeneratorAwareRenderingStrategy;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
class GeneratorAwareRenderingStrategyTest extends AbstractRenderingStrategyTest
{
protected function setUp()
{
if (!interface_exists('Symfony\Component\Routing\Generator\UrlGeneratorInterface')) {
$this->markTestSkipped('The "Routing" component is not available');
}
}
/**
* @expectedException \LogicException
*/
public function testGenerateProxyUriWithNoGenerator()
{
$strategy = new Strategy();
$strategy->doGenerateProxyUri(new ControllerReference('controller', array(), array()), Request::create('/'));
}
/**
* @expectedException \LogicException
*/
public function testGenerateProxyUriWhenRouteNotFound()
{
$generator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface');
$generator
->expects($this->once())
->method('generate')
->will($this->throwException(new RouteNotFoundException()))
;
$strategy = new Strategy();
$strategy->setUrlGenerator($generator);
$strategy->doGenerateProxyUri(new ControllerReference('controller', array(), array()), Request::create('/'));
}
/**
* @dataProvider getGeneratorProxyUriData
*/
public function testGenerateProxyUri($uri, $controller)
{
$this->assertEquals($uri, $this->getStrategy()->doGenerateProxyUri($controller, Request::create('/')));
}
public function getGeneratorProxyUriData()
{
return array(
array('/controller.html', new ControllerReference('controller', array(), array())),
array('/controller.xml', new ControllerReference('controller', array('_format' => 'xml'), array())),
array('/controller.json?path=foo%3Dfoo', new ControllerReference('controller', array('foo' => 'foo', '_format' => 'json'), array())),
array('/controller.html?bar=bar&path=foo%3Dfoo', new ControllerReference('controller', array('foo' => 'foo'), array('bar' => 'bar'))),
array('/controller.html?foo=foo', new ControllerReference('controller', array(), array('foo' => 'foo'))),
);
}
public function testGenerateProxyUriWithARequest()
{
$request = Request::create('/');
$request->attributes->set('_format', 'json');
$controller = new ControllerReference('controller', array(), array());
$this->assertEquals('/controller.json', $this->getStrategy()->doGenerateProxyUri($controller, $request));
}
private function getStrategy()
{
$strategy = new Strategy();
$strategy->setUrlGenerator($this->getUrlGenerator());
return $strategy;
}
}
class Strategy extends GeneratorAwareRenderingStrategy
{
public function render($uri, Request $request, array $options = array()) {}
public function getName() {}
public function doGenerateProxyUri(ControllerReference $reference, Request $request)
{
return parent::generateProxyUri($reference, $request);
}
}

View File

@ -16,17 +16,13 @@ use Symfony\Component\HttpKernel\RenderingStrategy\HIncludeRenderingStrategy;
use Symfony\Component\HttpKernel\UriSigner;
use Symfony\Component\HttpFoundation\Request;
class HIncludeRenderingStrategyTest extends AbstractRenderingStrategyTest
class HIncludeRenderingStrategyTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
if (!interface_exists('Symfony\Component\Routing\Generator\UrlGeneratorInterface')) {
$this->markTestSkipped('The "Routing" component is not available');
}
}
/**
@ -41,8 +37,8 @@ class HIncludeRenderingStrategyTest extends AbstractRenderingStrategyTest
public function testRenderWithControllerAndSigner()
{
$strategy = new HIncludeRenderingStrategy(null, new UriSigner('foo'));
$strategy->setUrlGenerator($this->getUrlGenerator());
$this->assertEquals('<hx:include src="/main_controller.html?_hash=6MuxpWUHcqIddMMmoN36uPsEjws%3D"></hx:include>', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent());
$this->assertEquals('<hx:include src="http://localhost/_proxy?path=_format%3Dhtml%26_controller%3Dmain_controller&_hash=hMh5ZalYRj5kWGIGawbIS93KFBE%3D"></hx:include>', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent());
}
public function testRenderWithUri()

View File

@ -0,0 +1,63 @@
<?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\Component\HttpKernel\Tests\RenderingStrategy;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\RenderingStrategy\ProxyAwareRenderingStrategy;
class ProxyAwareRenderingStrategyTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider getGenerateProxyUriData
*/
public function testGenerateProxyUri($uri, $controller)
{
$this->assertEquals($uri, $this->getStrategy()->doGenerateProxyUri($controller, Request::create('/')));
}
public function getGenerateProxyUriData()
{
return array(
array('http://localhost/_proxy?path=_format%3Dhtml%26_controller%3Dcontroller', new ControllerReference('controller', array(), array())),
array('http://localhost/_proxy?path=_format%3Dxml%26_controller%3Dcontroller', new ControllerReference('controller', array('_format' => 'xml'), array())),
array('http://localhost/_proxy?path=foo%3Dfoo%26_format%3Djson%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => 'foo', '_format' => 'json'), array())),
array('http://localhost/_proxy?bar=bar&path=foo%3Dfoo%26_format%3Dhtml%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => 'foo'), array('bar' => 'bar'))),
array('http://localhost/_proxy?foo=foo&path=_format%3Dhtml%26_controller%3Dcontroller', new ControllerReference('controller', array(), array('foo' => 'foo'))),
);
}
public function testGenerateProxyUriWithARequest()
{
$request = Request::create('/');
$request->attributes->set('_format', 'json');
$controller = new ControllerReference('controller', array(), array());
$this->assertEquals('http://localhost/_proxy?path=_format%3Djson%26_controller%3Dcontroller', $this->getStrategy()->doGenerateProxyUri($controller, $request));
}
private function getStrategy()
{
return new Strategy();
}
}
class Strategy extends ProxyAwareRenderingStrategy
{
public function render($uri, Request $request, array $options = array()) {}
public function getName() {}
public function doGenerateProxyUri(ControllerReference $reference, Request $request)
{
return parent::generateProxyUri($reference, $request);
}
}