From 34e7b956dd46cc03973ba90ce93523557a26a3e0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 23 Nov 2016 13:49:06 +0100 Subject: [PATCH] [HttpKernel] Deprecate checking for cacheable HTTP methods in Request::isMethodSafe() --- .../Component/HttpFoundation/BinaryFileResponse.php | 2 +- src/Symfony/Component/HttpFoundation/Request.php | 12 +++++++++++- .../Component/HttpFoundation/Tests/RequestTest.php | 13 ++++++++++++- .../HttpKernel/EventListener/FragmentListener.php | 2 +- .../Component/HttpKernel/HttpCache/HttpCache.php | 2 +- .../Security/Http/Firewall/ExceptionListener.php | 2 +- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index a39984dffa717..f95d90c364051 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -190,7 +190,7 @@ public function prepare(Request $request) if (!$this->headers->has('Accept-Ranges')) { // Only accept ranges on safe HTTP methods - $this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none'); + $this->headers->set('Accept-Ranges', $request->isMethodSafe(false) ? 'bytes' : 'none'); } if (!$this->headers->has('Content-Type')) { diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index f857ac74fc3be..f17316a06a2d3 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1475,10 +1475,20 @@ public function isMethod($method) /** * Checks whether or not the method is safe. * + * @param bool $andCacheable Adds the additional condition that the method should be cacheable. True by default. + * * @return bool */ - public function isMethodSafe() + public function isMethodSafe(/* $andCacheable = true */) { + if (!func_num_args() || func_get_arg(0)) { + // This deprecation should be turned into a BadMethodCallException in 4.0 (without adding the argument in the signature) + // then setting $andCacheable to false should be deprecated in 4.1 + @trigger_error('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since version 3.2 and will throw an exception in 4.0. Disable checking only for cacheable methods by calling the method with `false` as first argument or use the Request::isMethodCacheable() instead.', E_USER_DEPRECATED); + + return in_array($this->getMethod(), array('GET', 'HEAD')); + } + return in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE')); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 238be7601d321..ab0f3439dd66e 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1994,7 +1994,7 @@ public function testMethodSafe($method, $safe) { $request = new Request(); $request->setMethod($method); - $this->assertEquals($safe, $request->isMethodSafe()); + $this->assertEquals($safe, $request->isMethodSafe(false)); } public function methodSafeProvider() @@ -2013,6 +2013,17 @@ public function methodSafeProvider() ); } + /** + * @group legacy + * @expectedDeprecation Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since version 3.2 and will throw an exception in 4.0. Disable checking only for cacheable methods by calling the method with `false` as first argument or use the Request::isMethodCacheable() instead. + */ + public function testMethodSafeChecksCacheable() + { + $request = new Request(); + $request->setMethod('OPTION'); + $this->assertFalse($request->isMethodSafe()); + } + /** * @dataProvider methodCacheableProvider */ diff --git a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php index 9fdaccfaf6857..37bf15c3a084f 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php @@ -81,7 +81,7 @@ public function onKernelRequest(GetResponseEvent $event) protected function validateRequest(Request $request) { // is the Request safe? - if (!$request->isMethodSafe()) { + if (!$request->isMethodSafe(false)) { throw new AccessDeniedHttpException(); } diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index 3e7ff0aab8251..686f0b852c202 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -182,7 +182,7 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ } $this->traces[$request->getMethod().' '.$path] = array(); - if (!$request->isMethodSafe()) { + if (!$request->isMethodSafe(false)) { $response = $this->invalidate($request, $catch); } elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) { $response = $this->pass($request, $catch); diff --git a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php index 98f5ac04be303..3c9604ea7436b 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php @@ -220,7 +220,7 @@ private function startAuthentication(Request $request, AuthenticationException $ protected function setTargetPath(Request $request) { // session isn't required when using HTTP basic authentication mechanism for example - if ($request->hasSession() && $request->isMethodSafe() && !$request->isXmlHttpRequest()) { + if ($request->hasSession() && $request->isMethodSafe(false) && !$request->isXmlHttpRequest()) { $this->saveTargetPath($request->getSession(), $this->providerKey, $request->getUri()); } }