From eb236a7836c28ddacfb11ccff20af7f44ad1adbe Mon Sep 17 00:00:00 2001 From: Matthew Baggett Date: Sun, 14 Apr 2024 21:13:06 +0200 Subject: [PATCH] Json Flapping --- src/App.php | 2 +- src/Controllers/AbstractController.php | 4 +- src/Guzzle/JsonResponse.php | 90 ------------------- .../JsonResponseExecTimeMiddleware.php | 6 +- .../JsonResponseUnpackerMiddleware.php | 8 +- src/Middleware/JsonValidationMiddleware.php | 2 +- src/{Middleware => PSR}/JsonResponse.php | 7 +- tests/Traits/AppTestTrait.php | 34 +++++-- 8 files changed, 44 insertions(+), 109 deletions(-) delete mode 100644 src/Guzzle/JsonResponse.php rename src/{Middleware => PSR}/JsonResponse.php (93%) diff --git a/src/App.php b/src/App.php index bb0deae..6a48284 100644 --- a/src/App.php +++ b/src/App.php @@ -552,7 +552,7 @@ class App return $this->logger; } - public function loadAllRoutes(ServerRequestInterface $request): self + public function loadAllRoutes(?ServerRequestInterface $request = null): self { $this->debugBar['time']->startMeasure('interrogateControllers', 'Time to interrogate controllers for routes'); $this->interrogateControllers(); diff --git a/src/Controllers/AbstractController.php b/src/Controllers/AbstractController.php index 1abf92f..8f52005 100644 --- a/src/Controllers/AbstractController.php +++ b/src/Controllers/AbstractController.php @@ -25,7 +25,7 @@ abstract class AbstractController { $response->getBody()->write($root->asXML()); - return $response->withHeader('Content-type', 'text/xml'); + return $response->withHeader('Content-Type', 'text/xml'); } public function jsonResponse($json, Request $request, Response $response): Response @@ -33,7 +33,7 @@ abstract class AbstractController $content = json_encode($json, JSON_PRETTY_PRINT); $response->getBody()->write($content); - return $response->withHeader('Content-type', 'application/json'); + return $response->withHeader('Content-Type', 'application/json'); } public function redirect(Response $response, string $url = '/', int $code = 302): Response diff --git a/src/Guzzle/JsonResponse.php b/src/Guzzle/JsonResponse.php deleted file mode 100644 index 670da3d..0000000 --- a/src/Guzzle/JsonResponse.php +++ /dev/null @@ -1,90 +0,0 @@ -response->getBody()->getContents(), false); - } - - public function getProtocolVersion() - { - return $this->response->getProtocolVersion(); - } - - public function withProtocolVersion($version) - { - return $this->response->withProtocolVersion($version); - } - - public function getHeaders() - { - return $this->response->getHeaders(); - } - - public function hasHeader($name) - { - return $this->response->hasHeader($name); - } - - public function getHeader($name) - { - return $this->response->getHeader($name); - } - - public function getHeaderLine($name) - { - return $this->response->getHeaderLine($name); - } - - public function withHeader($name, $value) - { - return $this->response->withHeader($name, $value); - } - - public function withAddedHeader($name, $value) - { - return $this->response->withAddedHeader($name, $value); - } - - public function withoutHeader($name) - { - return $this->response->withoutHeader($name); - } - - public function getBody() - { - return $this->response->getBody(); - } - - public function withBody(StreamInterface $body) - { - return $this->response->withBody($body); - } - - public function getStatusCode() - { - return $this->response->getStatusCode(); - } - - public function withStatus($code, $reasonPhrase = '') - { - return $this->response->withStatus($code, $reasonPhrase); - } - - public function getReasonPhrase() - { - return $this->response->getReasonPhrase(); - } -} diff --git a/src/Middleware/JsonResponseExecTimeMiddleware.php b/src/Middleware/JsonResponseExecTimeMiddleware.php index 2a9b617..62996e0 100644 --- a/src/Middleware/JsonResponseExecTimeMiddleware.php +++ b/src/Middleware/JsonResponseExecTimeMiddleware.php @@ -14,6 +14,10 @@ class JsonResponseExecTimeMiddleware implements MiddlewareInterface { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { + // If path ends in .schema, don't add exec time + if (str_ends_with($request->getUri()->getPath(), '.schema')) { + return $handler->handle($request); + } $response = $handler->handle($request); $response->getBody()->rewind(); $responseJson = json_decode($response->getBody()->getContents(), true); @@ -30,7 +34,7 @@ class JsonResponseExecTimeMiddleware implements MiddlewareInterface $replacementResponse = new Response(); $replacementResponse->getBody()->write(json_encode($responseJson, JSON_PRETTY_PRINT)); - $replacementResponse = $replacementResponse->withHeader('Content-type', 'application/json'); + $replacementResponse = $replacementResponse->withHeader('Content-Type', 'application/json'); $replacementResponse = $replacementResponse->withStatus($response->getStatusCode()); diff --git a/src/Middleware/JsonResponseUnpackerMiddleware.php b/src/Middleware/JsonResponseUnpackerMiddleware.php index 54b59e7..7a6c1ae 100644 --- a/src/Middleware/JsonResponseUnpackerMiddleware.php +++ b/src/Middleware/JsonResponseUnpackerMiddleware.php @@ -9,16 +9,16 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; use Slim\Psr7\Response; +use Benzine\PSR\JsonResponse; class JsonResponseUnpackerMiddleware implements MiddlewareInterface { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $response = $handler->handle($request); - - if(!($response->hasHeader("Content-Type") && $response->getHeader("Content-Type")[0] === "application/json") ) { - return $response; + if($response->hasHeader("Content-Type") && $response->getHeader("Content-Type")[0] === "application/json" && $response instanceof Response) { + $response = new JsonResponse($response); } - return new JsonResponse($response); + return $response; } } \ No newline at end of file diff --git a/src/Middleware/JsonValidationMiddleware.php b/src/Middleware/JsonValidationMiddleware.php index 1da1aec..f6cbea9 100644 --- a/src/Middleware/JsonValidationMiddleware.php +++ b/src/Middleware/JsonValidationMiddleware.php @@ -64,7 +64,7 @@ class JsonValidationMiddleware implements MiddlewareInterface $response->getBody()->write($content); - $response = $response->withHeader('Content-type', 'application/json'); + $response = $response->withHeader('Content-Type', 'application/json'); return $response->withStatus(400); } diff --git a/src/Middleware/JsonResponse.php b/src/PSR/JsonResponse.php similarity index 93% rename from src/Middleware/JsonResponse.php rename to src/PSR/JsonResponse.php index 5c02bd3..9c4bd0f 100644 --- a/src/Middleware/JsonResponse.php +++ b/src/PSR/JsonResponse.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Benzine\Middleware; +namespace Benzine\PSR; use Ergebnis\Json\Json; use Psr\Http\Message\ResponseInterface; @@ -14,10 +14,8 @@ use Slim\Psr7\Response; class JsonResponse implements ResponseInterface { - protected Response $response; - public function __construct(Response $response) + public function __construct(protected Response $response) { - $this->response = $response; } public function getJson() : Json { @@ -103,5 +101,4 @@ class JsonResponse implements ResponseInterface { return $this->response->getReasonPhrase(); } - } \ No newline at end of file diff --git a/tests/Traits/AppTestTrait.php b/tests/Traits/AppTestTrait.php index 5a9a95c..61c091b 100644 --- a/tests/Traits/AppTestTrait.php +++ b/tests/Traits/AppTestTrait.php @@ -7,6 +7,8 @@ namespace Benzine\Tests\Traits; use Benzine\App as BenzineApp; use Benzine\Middleware\JsonResponse; use DI\Container; +use Ergebnis\Json\Json; +use Middlewares\Utils\Factory; use PHPUnit\Framework\MockObject\MockObject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -14,8 +16,12 @@ use Psr\Http\Message\UriInterface; use Slim\App as SlimApp; use Slim\Factory\ServerRequestCreatorFactory; use Slim\Psr7\Factory\ServerRequestFactory; +use Slim\Psr7\Headers; use Slim\Psr7\Request; use Slim\Psr7\Response; +use Benzine\Middleware\JsonResponseUnpackerMiddleware; +use Slim\Psr7\Stream; +use Slim\Psr7\Uri; /** * Container Trait. @@ -145,11 +151,29 @@ trait AppTestTrait $this->assertSame($expected, (array) json_decode($actual, true)); } - protected function send(Request $request) : JsonResponse|Response|ResponseInterface { - return $this - ->app - ->loadAllRoutes($request) + static protected function getHttpHandler() : SlimApp { + return self::$app + ->loadAllRoutes() ->getApp() - ->handle($request); + ->addMiddleware(new JsonResponseUnpackerMiddleware()); + } + + static protected function send(string $method, string $uri, ?array $data = []) : ResponseInterface { + $request = new Request( + method: $method, + uri: new \GuzzleHttp\Psr7\Uri($uri), + headers: new Headers(), + cookies: [], + serverParams: [], + body: new Stream(fopen('php://temp', 'r+')), + uploadedFiles: [] + ); + $request = $request->withParsedBody(Json::fromString(json_encode($data))->decoded()); + $request = $request->withHeader('Content-Type', 'application/json'); + return self::handle($request); + } + + static function handle(Request $request) : JsonResponse|Response|ResponseInterface { + return self::getHttpHandler()->handle($request); } }