ソースを参照

Add strict typing to Http\Middleware.

Refs #11935.
ADmad 7 年 前
コミット
d2a83e2484

+ 8 - 6
src/Http/Middleware/BodyParserMiddleware.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
@@ -15,6 +16,7 @@
 namespace Cake\Http\Middleware;
 
 use Cake\Http\Exception\BadRequestException;
+use Cake\Http\Response;
 use Cake\Utility\Exception\XmlException;
 use Cake\Utility\Xml;
 use Psr\Http\Message\ResponseInterface;
@@ -82,7 +84,7 @@ class BodyParserMiddleware
      * @param array $methods The methods to parse data on.
      * @return $this
      */
-    public function setMethods(array $methods)
+    public function setMethods(array $methods): self
     {
         $this->methods = $methods;
 
@@ -109,7 +111,7 @@ class BodyParserMiddleware
      *   into the request.
      * @return $this
      */
-    public function addParser(array $types, callable $parser)
+    public function addParser(array $types, callable $parser): self
     {
         foreach ($types as $type) {
             $type = strtolower($type);
@@ -129,7 +131,7 @@ class BodyParserMiddleware
      * @param callable $next Callback to invoke the next middleware.
      * @return \Cake\Http\Response A response
      */
-    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
+    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next): Response
     {
         if (!in_array($request->getMethod(), $this->methods)) {
             return $next($request, $response);
@@ -154,9 +156,9 @@ class BodyParserMiddleware
      * Decode JSON into an array.
      *
      * @param string $body The request body to decode
-     * @return array
+     * @return mixed
      */
-    protected function decodeJson($body)
+    protected function decodeJson(string $body)
     {
         return json_decode($body, true);
     }
@@ -167,7 +169,7 @@ class BodyParserMiddleware
      * @param string $body The request body to decode
      * @return array
      */
-    protected function decodeXml($body)
+    protected function decodeXml(string $body): array
     {
         try {
             $xml = Xml::build($body, ['return' => 'domdocument', 'readFile' => false]);

+ 8 - 7
src/Http/Middleware/CsrfProtectionMiddleware.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
@@ -84,12 +85,12 @@ class CsrfProtectionMiddleware
      * @param callable $next Callback to invoke the next middleware.
      * @return \Cake\Http\Response A response
      */
-    public function __invoke(ServerRequest $request, Response $response, $next)
+    public function __invoke(ServerRequest $request, Response $response, callable $next): Response
     {
         $cookies = $request->getCookieParams();
         $cookieData = Hash::get($cookies, $this->_config['cookieName']);
 
-        if (strlen($cookieData) > 0) {
+        if ($cookieData !== null && strlen($cookieData) > 0) {
             $params = $request->getAttribute('params');
             $params['_csrfToken'] = $cookieData;
             $request = $request->withAttribute('params', $params);
@@ -114,7 +115,7 @@ class CsrfProtectionMiddleware
      * @param \Cake\Http\ServerRequest $request The request object.
      * @return \Cake\Http\ServerRequest
      */
-    protected function _validateAndUnsetTokenField(ServerRequest $request)
+    protected function _validateAndUnsetTokenField(ServerRequest $request): ServerRequest
     {
         if (in_array($request->getMethod(), ['PUT', 'POST', 'DELETE', 'PATCH']) || $request->getData()) {
             $this->_validateToken($request);
@@ -133,7 +134,7 @@ class CsrfProtectionMiddleware
      *
      * @return string
      */
-    protected function _createToken()
+    protected function _createToken(): string
     {
         return hash('sha512', Security::randomBytes(16), false);
     }
@@ -145,7 +146,7 @@ class CsrfProtectionMiddleware
      * @param \Cake\Http\ServerRequest $request The request to augment
      * @return \Cake\Http\ServerRequest Modified request
      */
-    protected function _addTokenToRequest($token, ServerRequest $request)
+    protected function _addTokenToRequest(string $token, ServerRequest $request): ServerRequest
     {
         $params = $request->getAttribute('params');
         $params['_csrfToken'] = $token;
@@ -161,7 +162,7 @@ class CsrfProtectionMiddleware
      * @param \Cake\Http\Response $response The response.
      * @return \Cake\Http\Response $response Modified response.
      */
-    protected function _addTokenCookie($token, ServerRequest $request, Response $response)
+    protected function _addTokenCookie(string $token, ServerRequest $request, Response $response): Response
     {
         $expiry = new Time($this->_config['expiry']);
 
@@ -185,7 +186,7 @@ class CsrfProtectionMiddleware
      * @return void
      * @throws \Cake\Http\Exception\InvalidCsrfTokenException When the CSRF token is invalid or missing.
      */
-    protected function _validateToken(ServerRequest $request)
+    protected function _validateToken(ServerRequest $request): void
     {
         $cookies = $request->getCookieParams();
         $cookie = Hash::get($cookies, $this->_config['cookieName']);

+ 8 - 7
src/Http/Middleware/EncryptedCookieMiddleware.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
@@ -65,7 +66,7 @@ class EncryptedCookieMiddleware
      * @param string $key The encryption key to use.
      * @param string $cipherType The cipher type to use. Defaults to 'aes'.
      */
-    public function __construct(array $cookieNames, $key, $cipherType = 'aes')
+    public function __construct(array $cookieNames, string $key, string $cipherType = 'aes')
     {
         $this->cookieNames = $cookieNames;
         $this->key = $key;
@@ -78,9 +79,9 @@ class EncryptedCookieMiddleware
      * @param \Psr\Http\Message\ServerRequestInterface $request The request.
      * @param \Psr\Http\Message\ResponseInterface $response The response.
      * @param callable $next The next middleware to call.
-     * @return \Psr\Http\Message\ResponseInterface A response.
+     * @return \Cake\Http\Response A response.
      */
-    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
+    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next): Response
     {
         if ($request->getCookieParams()) {
             $request = $this->decodeCookies($request);
@@ -103,7 +104,7 @@ class EncryptedCookieMiddleware
      *
      * @return string
      */
-    protected function _getCookieEncryptionKey()
+    protected function _getCookieEncryptionKey(): string
     {
         return $this->key;
     }
@@ -114,7 +115,7 @@ class EncryptedCookieMiddleware
      * @param \Psr\Http\Message\ServerRequestInterface $request The request to decode cookies from.
      * @return \Psr\Http\Message\ServerRequestInterface Updated request with decoded cookies.
      */
-    protected function decodeCookies(ServerRequestInterface $request)
+    protected function decodeCookies(ServerRequestInterface $request): ServerRequestInterface
     {
         $cookies = $request->getCookieParams();
         foreach ($this->cookieNames as $name) {
@@ -132,7 +133,7 @@ class EncryptedCookieMiddleware
      * @param \Cake\Http\Response $response The response to encode cookies in.
      * @return \Cake\Http\Response Updated response with encoded cookies.
      */
-    protected function encodeCookies(Response $response)
+    protected function encodeCookies(Response $response): Response
     {
         $cookies = $response->getCookieCollection();
         foreach ($cookies as $cookie) {
@@ -151,7 +152,7 @@ class EncryptedCookieMiddleware
      * @param \Psr\Http\Message\ResponseInterface $response The response to encode cookies in.
      * @return \Psr\Http\Message\ResponseInterface Updated response with encoded cookies.
      */
-    protected function encodeSetCookieHeader(ResponseInterface $response)
+    protected function encodeSetCookieHeader(ResponseInterface $response): ResponseInterface
     {
         $cookies = CookieCollection::createFromHeader($response->getHeader('Set-Cookie'));
         $header = [];

+ 9 - 8
src/Http/Middleware/SecurityHeadersMiddleware.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
@@ -38,7 +39,7 @@ class SecurityHeadersMiddleware
      * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
      * @return $this
      */
-    public function noSniff()
+    public function noSniff(): self
     {
         $this->headers['x-content-type-options'] = 'nosniff';
 
@@ -53,7 +54,7 @@ class SecurityHeadersMiddleware
      * @link https://msdn.microsoft.com/en-us/library/jj542450(v=vs.85).aspx
      * @return $this
      */
-    public function noOpen()
+    public function noOpen(): self
     {
         $this->headers['x-download-options'] = 'noopen';
 
@@ -68,7 +69,7 @@ class SecurityHeadersMiddleware
      *        'same-origin', 'strict-origin', 'strict-origin-when-cross-origin', 'unsafe-url'
      * @return $this
      */
-    public function setReferrerPolicy($policy = 'same-origin')
+    public function setReferrerPolicy(string $policy = 'same-origin'): self
     {
         $available = [
             'no-referrer', 'no-referrer-when-downgrade', 'origin',
@@ -91,7 +92,7 @@ class SecurityHeadersMiddleware
      * @param string $url URL if mode is `allow-from`
      * @return $this
      */
-    public function setXFrameOptions($option = 'sameorigin', $url = null)
+    public function setXFrameOptions(string $option = 'sameorigin', ?string $url = null): self
     {
         $this->checkValues($option, ['deny', 'sameorigin', 'allow-from']);
 
@@ -114,7 +115,7 @@ class SecurityHeadersMiddleware
      * @param string $mode Mode value. Available Values: '1', '0', 'block'
      * @return $this
      */
-    public function setXssProtection($mode = 'block')
+    public function setXssProtection(string $mode = 'block'): self
     {
         $mode = (string)$mode;
 
@@ -135,7 +136,7 @@ class SecurityHeadersMiddleware
      * @param string $policy Policy value. Available Values: 'all', 'none', 'master-only', 'by-content-type', 'by-ftp-filename'
      * @return $this
      */
-    public function setCrossDomainPolicy($policy = 'all')
+    public function setCrossDomainPolicy(string $policy = 'all'): self
     {
         $this->checkValues($policy, ['all', 'none', 'master-only', 'by-content-type', 'by-ftp-filename']);
         $this->headers['x-permitted-cross-domain-policies'] = $policy;
@@ -151,7 +152,7 @@ class SecurityHeadersMiddleware
      * @param array $allowed List of allowed values
      * @return void
      */
-    protected function checkValues($value, array $allowed)
+    protected function checkValues(string $value, array $allowed): void
     {
         if (!in_array($value, $allowed)) {
             throw new InvalidArgumentException(sprintf(
@@ -170,7 +171,7 @@ class SecurityHeadersMiddleware
      * @param callable $next Callback to invoke the next middleware.
      * @return \Psr\Http\Message\ResponseInterface A response
      */
-    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
+    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next): ResponseInterface
     {
         $response = $next($request, $response);
         foreach ($this->headers as $header => $value) {

+ 18 - 0
tests/TestCase/Http/Middleware/BodyParserMiddlewareTest.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
@@ -159,6 +160,8 @@ class BodyParserMiddlewareTest extends TestCase
         $response = new Response();
         $next = function ($req, $res) {
             $this->assertEquals([], $req->getParsedBody());
+
+            return $res;
         };
         $parser($request, $response, $next);
     }
@@ -183,6 +186,8 @@ class BodyParserMiddlewareTest extends TestCase
         $response = new Response();
         $next = function ($req, $res) {
             $this->assertEquals(['title' => 'yay'], $req->getParsedBody());
+
+            return $res;
         };
         $parser($request, $response, $next);
     }
@@ -207,6 +212,8 @@ class BodyParserMiddlewareTest extends TestCase
         $response = new Response();
         $next = function ($req, $res) {
             $this->assertEquals(['title' => 'yay'], $req->getParsedBody());
+
+            return $res;
         };
         $parser($request, $response, $next);
     }
@@ -230,6 +237,8 @@ class BodyParserMiddlewareTest extends TestCase
         $response = new Response();
         $next = function ($req, $res) {
             $this->assertEquals(['title' => 'yay'], $req->getParsedBody());
+
+            return $res;
         };
         $parser($request, $response, $next);
     }
@@ -254,6 +263,8 @@ class BodyParserMiddlewareTest extends TestCase
         $response = new Response();
         $next = function ($req, $res) {
             $this->assertEquals([], $req->getParsedBody());
+
+            return $res;
         };
         $parser($request, $response, $next);
     }
@@ -285,6 +296,8 @@ XML;
                 'article' => ['title' => 'yay'],
             ];
             $this->assertEquals($expected, $req->getParsedBody());
+
+            return $res;
         };
 
         $parser = new BodyParserMiddleware(['xml' => true]);
@@ -321,6 +334,8 @@ XML;
                 ],
             ];
             $this->assertEquals($expected, $req->getParsedBody());
+
+            return $res;
         };
 
         $parser = new BodyParserMiddleware(['xml' => true]);
@@ -361,6 +376,8 @@ XML;
         $response = new Response();
         $next = function ($req, $res) {
             $this->assertEquals([], $req->getParsedBody());
+
+            return $res;
         };
 
         $parser = new BodyParserMiddleware(['xml' => true]);
@@ -383,6 +400,7 @@ XML;
         ]);
         $response = new Response();
         $next = function ($req, $res) {
+            return $res;
         };
 
         $this->expectException(BadRequestException::class);

+ 7 - 0
tests/TestCase/Http/Middleware/CsrfProtectionMiddlewareTest.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
@@ -84,6 +85,8 @@ class CsrfProtectionMiddlewareTest extends TestCase
             $this->assertEquals(0, $cookie['expire'], 'session duration.');
             $this->assertEquals('/dir/', $cookie['path'], 'session path.');
             $this->assertEquals($cookie['value'], $request->getParam('_csrfToken'));
+
+            return $response;
         };
 
         $middleware = new CsrfProtectionMiddleware();
@@ -179,6 +182,8 @@ class CsrfProtectionMiddlewareTest extends TestCase
 
         $closure = function ($request, $response) {
             $this->assertNull($request->getData('_csrfToken'));
+
+            return $response;
         };
 
         // No exception means everything is OK
@@ -273,6 +278,8 @@ class CsrfProtectionMiddlewareTest extends TestCase
             $this->assertEquals('/dir/', $cookie['path'], 'session path.');
             $this->assertTrue($cookie['secure'], 'cookie security flag missing');
             $this->assertTrue($cookie['httpOnly'], 'cookie httpOnly flag missing');
+
+            return $response;
         };
 
         $middleware = new CsrfProtectionMiddleware([

+ 1 - 0
tests/TestCase/Http/Middleware/EncryptedCookieMiddlewareTest.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)

+ 1 - 0
tests/TestCase/Http/Middleware/SecurityHeadersMiddlewareTest.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)