Issue #2147153 by dawehner, alexpott, Xano: Replace the last instance of $_GET/$_POST; Create a special exception listener / exception controller which allows to use POST requests.

8.0.x
Nathaniel Catchpole 2014-02-10 10:38:41 +00:00
parent 91db25eba4
commit e4e83f0e95
8 changed files with 170 additions and 9 deletions

View File

@ -111,7 +111,7 @@ services:
class: Drupal\Core\Form\FormBuilder
arguments: ['@module_handler', '@keyvalue.expirable', '@event_dispatcher', '@url_generator', '@string_translation', '@?csrf_token', '@?http_kernel']
calls:
- [setRequest, ['@?request']]
- [setRequest, ['@?request=']]
keyvalue:
class: Drupal\Core\KeyValueStore\KeyValueFactory
arguments: ['@service_container', '@settings']
@ -218,6 +218,7 @@ services:
request:
class: Symfony\Component\HttpFoundation\Request
synthetic: true
synchronized: true
request_stack:
class: Symfony\Component\HttpFoundation\RequestStack
event_dispatcher:
@ -546,7 +547,7 @@ services:
calls:
- [setContainer, ['@service_container']]
exception_listener:
class: Symfony\Component\HttpKernel\EventListener\ExceptionListener
class: Drupal\Core\EventSubscriber\ExceptionListener
tags:
- { name: event_subscriber }
arguments: [['@exception_controller', execute]]

View File

@ -146,7 +146,13 @@ class ExceptionController extends HtmlControllerBase implements ContainerAwareIn
$request->query->set('destination', $system_path);
}
$subrequest = Request::create($request->getBaseUrl() . '/' . $path, 'get', array('destination' => $system_path, '_exception_statuscode' => 403), $request->cookies->all(), array(), $request->server->all());
if ($request->getMethod() === 'POST') {
$subrequest = Request::create($request->getBaseUrl() . '/' . $path, 'POST', array('destination' => $system_path, '_exception_statuscode' => 403) + $request->request->all(), $request->cookies->all(), array(), $request->server->all());
$subrequest->query->set('destination', $system_path);
}
else {
$subrequest = Request::create($request->getBaseUrl() . '/' . $path, 'GET', array('destination' => $system_path, '_exception_statuscode' => 403), $request->cookies->all(), array(), $request->server->all());
}
// The active trail is being statically cached from the parent request to
// the subrequest, like any other static. Unfortunately that means the
@ -223,7 +229,13 @@ class ExceptionController extends HtmlControllerBase implements ContainerAwareIn
// @todo The create() method expects a slash-prefixed path, but we store a
// normal system path in the site_404 variable.
$subrequest = Request::create($request->getBaseUrl() . '/' . $path, 'get', array('destination' => $system_path, '_exception_statuscode' => 403), $request->cookies->all(), array(), $request->server->all());
if ($request->getMethod() === 'POST') {
$subrequest = Request::create($request->getBaseUrl() . '/' . $path, 'POST', array('destination' => $system_path, '_exception_statuscode' => 404) + $request->request->all(), $request->cookies->all(), array(), $request->server->all());
$subrequest->query->set('destination', $system_path);
}
else {
$subrequest = Request::create($request->getBaseUrl() . '/' . $path, 'GET', array('destination' => $system_path, '_exception_statuscode' => 404), $request->cookies->all(), array(), $request->server->all());
}
// The active trail is being statically cached from the parent request to
// the subrequest, like any other static. Unfortunately that means the

View File

@ -0,0 +1,36 @@
<?php
/**
* @file
* Contains \Drupal\Core\EventSubscriber\ExceptionListener.
*/
namespace Drupal\Core\EventSubscriber;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\EventListener\ExceptionListener as ExceptionListenerBase;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
/**
* Extends the symfony exception listener to support POST subrequests.
*/
class ExceptionListener extends ExceptionListenerBase {
/**
* {@inheritdoc}
*
* In contrast to the symfony base class, do not override POST requests to GET
* requests.
*/
protected function duplicateRequest(\Exception $exception, Request $request) {
$attributes = array(
'_controller' => $this->controller,
'exception' => FlattenException::create($exception),
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : NULL,
'format' => $request->getRequestFormat(),
);
return $request->duplicate(NULL, NULL, $attributes);
}
}

View File

@ -200,7 +200,7 @@ class FormBuilder implements FormBuilderInterface {
$form_id = $this->getFormId($form_id, $form_state);
if (!isset($form_state['input'])) {
$form_state['input'] = $form_state['method'] == 'get' ? $_GET : $_POST;
$form_state['input'] = $form_state['method'] == 'get' ? $this->request->query->all() : $this->request->request->all();
}
if (isset($_SESSION['batch_form_state'])) {

View File

@ -67,7 +67,7 @@ class LanguageUILanguageNegotiationTest extends WebTestBase {
function setUp() {
parent::setUp();
$this->request = Request::create('http://example.com/');
$this->request = Request::createFromGlobals();
$this->container->set('request', $this->request);
$admin_user = $this->drupalCreateUser(array('administer languages', 'translate interface', 'access administration pages', 'administer blocks'));

View File

@ -33,7 +33,7 @@ class SessionHttpsTest extends WebTestBase {
public function setUp() {
parent::setUp();
$this->request = Request::create('http://example.com/');
$this->request = Request::createFromGlobals();
$this->container->set('request', $this->request);
}

View File

@ -35,8 +35,7 @@ class FloodTest extends WebTestBase {
// Flood backends need a request object. Create a dummy one and insert it
// to the container.
$this->request = Request::create('http://example.com/');
$this->request->server->set('REMOTE_ADDR', '3.3.3.3');
$this->request = Request::createFromGlobals();
$this->container->set('request', $this->request);
}

View File

@ -0,0 +1,113 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\EventSubscriber\ExceptionListenerTest.
*/
namespace Drupal\Tests\Core\EventSubscriber;
use Drupal\Component\Utility\Url;
use Drupal\Core\EventSubscriber\ExceptionListener;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
/**
* Tests the exception listener.
*
* @group Drupal
* @group Routing
*
* @see \Drupal\Core\EventSubscriber\ExceptionListener
*/
class ExceptionListenerTest extends UnitTestCase {
/**
* The tested exception listener.
*
* @var \Drupal\Core\EventSubscriber\ExceptionListener
*/
protected $exceptionListener;
/**
* The mocked HTTP kernel.
*
* @var \Symfony\Component\HttpKernel\HttpKernelInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $kernel;
/**
* The PHP error log settings before the test.
*
* @var string
*/
protected $errorLog;
/**
* {@inheritdoc}
*/
public static function getInfo() {
return array(
'name' => 'Exception listener',
'description' => 'Tests the exception listener',
'group' => 'Routing',
);
}
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->exceptionListener = new ExceptionListener('example');
$this->kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
// You can't create an exception in PHP without throwing it. Store the
// current error_log, and disable it temporarily.
$this->errorLog = ini_set('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul');
}
/**
* {@inheritdoc}
*/
protected function tearDown() {
ini_set('error_log', $this->errorLog);
}
/**
* Tests onHandleException with a POST request.
*/
public function testHandleWithPostRequest() {
$request = Request::create('/test', 'POST', array('name' => 'druplicon', 'pass' => '12345'));
$this->kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
return new Response($request->getMethod());
}));
$event = new GetResponseForExceptionEvent($this->kernel, $request, 'foo', new \Exception('foo'));
$this->exceptionListener->onKernelException($event);
$response = $event->getResponse();
$this->assertEquals('POST name=druplicon&pass=12345', $response->getContent() . " " . Url::buildQuery($request->request->all()));
}
/**
* Tests onHandleException with a GET request.
*/
public function testHandleWithGetRequest() {
$request = Request::create('/test', 'GET', array('name' => 'druplicon', 'pass' => '12345'));
$this->kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
return new Response($request->getMethod() . ' ' . Url::buildQuery($request->query->all()));
}));
$event = new GetResponseForExceptionEvent($this->kernel, $request, 'foo', new \Exception('foo'));
$this->exceptionListener->onKernelException($event);
$response = $event->getResponse();
$this->assertEquals('GET name=druplicon&pass=12345 ', $response->getContent() . " " . Url::buildQuery($request->request->all()));
}
}