From 45f4f64f17d237fa5505b59e1cdb223a2d12d18d Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 19 May 2024 14:01:39 +0800 Subject: [PATCH 1/4] Make it possible to pass a function to be run prior to flushing the response --- src/main/php/web/Response.class.php | 13 ++++++++++++ .../php/web/unittest/ResponseTest.class.php | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/main/php/web/Response.class.php b/src/main/php/web/Response.class.php index 0acc48ce..3a772dcd 100755 --- a/src/main/php/web/Response.class.php +++ b/src/main/php/web/Response.class.php @@ -12,6 +12,7 @@ */ class Response { private $output; + private $flushing= null; private $flushed= false; private $status= 200; private $message= 'OK'; @@ -111,6 +112,7 @@ public function headers() { /** @param web.io.Output $output */ private function begin($output) { + $this->flushing && ($this->flushing)($this); $output->begin($this->status, $this->message, $this->cookies ? array_merge($this->headers, ['Set-Cookie' => array_map(function($c) { return $c->header(); }, $this->cookies)]) : $this->headers @@ -118,6 +120,17 @@ private function begin($output) { $this->flushed= true; } + /** + * Passes a function to call before flushing the response + * + * @param ?function(self): void $function + * @return self + */ + public function flushing($function) { + $this->flushing= $function; + return $this; + } + /** * Flushes response * diff --git a/src/test/php/web/unittest/ResponseTest.class.php b/src/test/php/web/unittest/ResponseTest.class.php index 13b9b4d3..d7d6f400 100755 --- a/src/test/php/web/unittest/ResponseTest.class.php +++ b/src/test/php/web/unittest/ResponseTest.class.php @@ -315,4 +315,24 @@ public function flush_twice() { $res->flush(); $res->flush(); } + + #[Test] + public function flushing_explicitely() { + $executed= 0; + $res= (new Response(new TestOutput()))->flushing(function() use(&$executed) { + $executed++; + }); + $res->flush(); + Assert::equals(1, $executed); + } + + #[Test] + public function flushing_implicitely() { + $executed= 0; + $res= (new Response(new TestOutput()))->flushing(function() use(&$executed) { + $executed++; + }); + $res->send('Test', 'text/plain'); + Assert::equals(1, $executed); + } } \ No newline at end of file From a9774720bfe473b2fd0c3e07f4db5132a2d3787e Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 19 May 2024 14:13:51 +0800 Subject: [PATCH 2/4] Allow multiple flushing functions --- src/main/php/web/Response.class.php | 12 +++++++----- src/test/php/web/unittest/ResponseTest.class.php | 11 +++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/php/web/Response.class.php b/src/main/php/web/Response.class.php index 3a772dcd..f24b8f52 100755 --- a/src/main/php/web/Response.class.php +++ b/src/main/php/web/Response.class.php @@ -12,7 +12,7 @@ */ class Response { private $output; - private $flushing= null; + private $flushing= []; private $flushed= false; private $status= 200; private $message= 'OK'; @@ -112,7 +112,9 @@ public function headers() { /** @param web.io.Output $output */ private function begin($output) { - $this->flushing && ($this->flushing)($this); + foreach ($this->flushing as $function) { + $function($this); + } $output->begin($this->status, $this->message, $this->cookies ? array_merge($this->headers, ['Set-Cookie' => array_map(function($c) { return $c->header(); }, $this->cookies)]) : $this->headers @@ -123,11 +125,11 @@ private function begin($output) { /** * Passes a function to call before flushing the response * - * @param ?function(self): void $function + * @param function(self): void $function * @return self */ - public function flushing($function) { - $this->flushing= $function; + public function flushing(callable $function) { + $this->flushing[]= $function; return $this; } diff --git a/src/test/php/web/unittest/ResponseTest.class.php b/src/test/php/web/unittest/ResponseTest.class.php index d7d6f400..c468fb62 100755 --- a/src/test/php/web/unittest/ResponseTest.class.php +++ b/src/test/php/web/unittest/ResponseTest.class.php @@ -335,4 +335,15 @@ public function flushing_implicitely() { $res->send('Test', 'text/plain'); Assert::equals(1, $executed); } + + #[Test] + public function multiple_flushing_functions() { + $executed= ['one' => 0, 'two' => 0]; + $res= (new Response(new TestOutput())) + ->flushing(function() use(&$executed) { $executed['one']++; }) + ->flushing(function() use(&$executed) { $executed['two']++; }) + ; + $res->flush(); + Assert::equals(['one' => 1, 'two' => 1], $executed); + } } \ No newline at end of file From 8edfd2e87c900e3e7316e47f54dd8c4174c47e84 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 19 May 2024 15:59:29 +0800 Subject: [PATCH 3/4] Simplify flush() declaration --- src/main/php/web/Response.class.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/php/web/Response.class.php b/src/main/php/web/Response.class.php index f24b8f52..2b0ec4bd 100755 --- a/src/main/php/web/Response.class.php +++ b/src/main/php/web/Response.class.php @@ -136,16 +136,15 @@ public function flushing(callable $function) { /** * Flushes response * - * @param web.io.Output $output * @return void * @throws lang.IllegalStateException */ - public function flush($output= null) { + public function flush() { if ($this->flushed) { throw new IllegalStateException('Response already flushed'); } - $this->begin($output ?: $this->output); + $this->begin($this->output); } /** @@ -172,8 +171,13 @@ public function end() { * * @param int $size If omitted, uses chunked transfer encoding * @return io.streams.OutputStream + * @throws lang.IllegalStateException */ public function stream($size= null) { + if ($this->flushed) { + throw new IllegalStateException('Response already flushed'); + } + if (null === $size) { $output= $this->output->stream(); } else { @@ -181,7 +185,7 @@ public function stream($size= null) { $output= $this->output; } - $this->flush($output); + $this->begin($output); return $output; } From 59cb0be4588436d84276e7c37f4da694ddb37a33 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 19 May 2024 16:04:38 +0800 Subject: [PATCH 4/4] Add tests for Response::end() --- .../php/web/unittest/ResponseTest.class.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/php/web/unittest/ResponseTest.class.php b/src/test/php/web/unittest/ResponseTest.class.php index c468fb62..2eb8e032 100755 --- a/src/test/php/web/unittest/ResponseTest.class.php +++ b/src/test/php/web/unittest/ResponseTest.class.php @@ -309,6 +309,14 @@ public function flushed() { Assert::true($res->flushed()); } + #[Test] + public function ended() { + $res= new Response(new TestOutput()); + Assert::false($res->flushed()); + $res->end(); + Assert::true($res->flushed()); + } + #[Test, Expect(IllegalStateException::class)] public function flush_twice() { $res= new Response(new TestOutput()); @@ -336,6 +344,16 @@ public function flushing_implicitely() { Assert::equals(1, $executed); } + #[Test] + public function flushing_on_end() { + $executed= 0; + $res= (new Response(new TestOutput()))->flushing(function() use(&$executed) { + $executed++; + }); + $res->end(); + Assert::equals(1, $executed); + } + #[Test] public function multiple_flushing_functions() { $executed= ['one' => 0, 'two' => 0];