From 2c4fbcaf6037d799af8148d07b5fa7f62e7c0c3a Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Mon, 12 Feb 2018 21:09:56 +0100 Subject: [PATCH 1/7] Add development console --- src/main/php/xp/web/dev/Buffer.class.php | 25 ++++++++ src/main/php/xp/web/dev/Console.class.php | 76 +++++++++++++++++++++++ src/main/php/xp/web/dev/console.html | 68 ++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100755 src/main/php/xp/web/dev/Buffer.class.php create mode 100755 src/main/php/xp/web/dev/Console.class.php create mode 100755 src/main/php/xp/web/dev/console.html diff --git a/src/main/php/xp/web/dev/Buffer.class.php b/src/main/php/xp/web/dev/Buffer.class.php new file mode 100755 index 00000000..febe2c38 --- /dev/null +++ b/src/main/php/xp/web/dev/Buffer.class.php @@ -0,0 +1,25 @@ +status= $status; + $this->message= $message; + $this->headers= $headers; + } + + public function write($bytes) { + $this->bytes.= $bytes; + } + + public function drain(Output $out) { + fputs(STDOUT, "BUFFER::drain($this->bytes) -> ".var_export($out, 1)."\n"); + $out->begin($this->status, $this->message, $this->headers); + $out->write($this->bytes); + $out->close(); + } +} \ No newline at end of file diff --git a/src/main/php/xp/web/dev/Console.class.php b/src/main/php/xp/web/dev/Console.class.php new file mode 100755 index 00000000..c7cad9d0 --- /dev/null +++ b/src/main/php/xp/web/dev/Console.class.php @@ -0,0 +1,76 @@ +template= $name.'.html'; + } + + /** + * Creates HTML table rows + * + * @param [:var] $headers + * @return string + */ + private function rows($headers) { + $r= ''; + foreach ($headers as $name => $value) { + $r.= ' + '.htmlspecialchars($name).' + '.htmlspecialchars(implode(', ', $value)).' + '; + } + return $r; + } + + /** + * Filters the request + * + * @param web.Request $req + * @param web.Response $res + * @param web.filters.Invocation $invocation + * @return var + */ + public function filter($req, $res, $invocation) { + $buffer= new Buffer(); + + try { + fputs(STDOUT, "Console::ob_start()\n"); + ob_start(); + $result= $invocation->proceed($req, new Response($buffer)); + } finally { + fputs(STDOUT, "Console::ob_get_clean()\n"); + $debug= ob_get_clean(); + ob_end_clean(); + } + + if (empty($debug)) { + $buffer->drain($res->output()); + } else { + $res->status(200, 'Debug'); + $res->send(sprintf( + typeof($this)->getClassLoader()->getResource($this->template), + htmlspecialchars($debug), + $buffer->status, + htmlspecialchars($buffer->message), + $this->rows($buffer->headers), + htmlspecialchars($buffer->bytes) + )); + } + + return $result; + } +} \ No newline at end of file diff --git a/src/main/php/xp/web/dev/console.html b/src/main/php/xp/web/dev/console.html new file mode 100755 index 00000000..cdc3e551 --- /dev/null +++ b/src/main/php/xp/web/dev/console.html @@ -0,0 +1,68 @@ + + + + Debug + + + +
+

+ Debug + + DEBUG +

+
+ +
%1$s
+
+ + +

HTTP/1.1 %2$d %3$s

+ + %4$s +
+
%5$s
+
+ + + From a873bcf69310244bbae81a3e9f5dcb128dca787c Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Mon, 12 Feb 2018 21:10:21 +0100 Subject: [PATCH 2/7] Activate dev console by default in `-m develop` --- src/main/php/xp/web/srv/Develop.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/php/xp/web/srv/Develop.class.php b/src/main/php/xp/web/srv/Develop.class.php index 29561a38..d18e8085 100755 --- a/src/main/php/xp/web/srv/Develop.class.php +++ b/src/main/php/xp/web/srv/Develop.class.php @@ -61,7 +61,7 @@ public function serve($source, $profile, $webroot, $docroot, $config) { // Export environment putenv('DOCUMENT_ROOT='.$docroot); putenv('SERVER_PROFILE='.$profile); - putenv('WEB_SOURCE='.$source); + putenv('WEB_SOURCE='.$source.'+xp.web.dev.Console'); putenv('WEB_CONFIG='.implode('PATH_SEPARATOR', $config)); putenv('WEB_ROOT='.$webroot); From 67f9cff773a80fe8ca0dab107194f9755e868445 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Mon, 12 Feb 2018 21:10:42 +0100 Subject: [PATCH 3/7] Install filters passed along via `application[+filter[,filter[,...]]]` --- src/main/php/web/Application.class.php | 10 ++++++++++ src/main/php/xp/web/Source.class.php | 15 ++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/main/php/web/Application.class.php b/src/main/php/web/Application.class.php index 4719dab2..01dd21b2 100755 --- a/src/main/php/web/Application.class.php +++ b/src/main/php/web/Application.class.php @@ -43,6 +43,16 @@ public final function routing() { */ protected abstract function routes(); + /** + * Installs global filters + * + * @param web.Filter[] $filters + * @return void + */ + public function install($filters) { + $this->routing= Routing::cast(new Filters($filters, $this->routing())); + } + /** * Service delegates to the routing, calling its `service()` method. * diff --git a/src/main/php/xp/web/Source.class.php b/src/main/php/xp/web/Source.class.php index 809c70b2..1ca5d96c 100755 --- a/src/main/php/xp/web/Source.class.php +++ b/src/main/php/xp/web/Source.class.php @@ -8,14 +8,23 @@ class Source { /** * Creates a new application from a given name and environment * - * @param string $name + * @param string $name `application[+filter[,filter[,...]]]` * @param web.Environment $environment */ public function __construct($name, $environment) { - if ('-' === $name) { + sscanf($name, '%[^+]+%s', $application, $filters); + + if ('-' === $application) { $this->application= new ServeDocumentRootStatically($environment); } else { - $this->application= XPClass::forName($name)->newInstance($environment); + $this->application= XPClass::forName($application)->newInstance($environment); + } + + if ($filters) { + $this->application->install(array_map( + function($filter) { return XPClass::forName($filter)->newInstance(); }, + explode(',', $filters) + )); } } From 190fdc7986aa49b4cf32ac80dfcea6f10ed241a2 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Mon, 12 Feb 2018 21:11:40 +0100 Subject: [PATCH 4/7] Remove debug code --- src/main/php/xp/web/dev/Buffer.class.php | 1 - src/main/php/xp/web/dev/Console.class.php | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/main/php/xp/web/dev/Buffer.class.php b/src/main/php/xp/web/dev/Buffer.class.php index febe2c38..76595c89 100755 --- a/src/main/php/xp/web/dev/Buffer.class.php +++ b/src/main/php/xp/web/dev/Buffer.class.php @@ -17,7 +17,6 @@ public function write($bytes) { } public function drain(Output $out) { - fputs(STDOUT, "BUFFER::drain($this->bytes) -> ".var_export($out, 1)."\n"); $out->begin($this->status, $this->message, $this->headers); $out->write($this->bytes); $out->close(); diff --git a/src/main/php/xp/web/dev/Console.class.php b/src/main/php/xp/web/dev/Console.class.php index c7cad9d0..4efdff9c 100755 --- a/src/main/php/xp/web/dev/Console.class.php +++ b/src/main/php/xp/web/dev/Console.class.php @@ -48,11 +48,9 @@ public function filter($req, $res, $invocation) { $buffer= new Buffer(); try { - fputs(STDOUT, "Console::ob_start()\n"); ob_start(); $result= $invocation->proceed($req, new Response($buffer)); } finally { - fputs(STDOUT, "Console::ob_get_clean()\n"); $debug= ob_get_clean(); ob_end_clean(); } From 7b033e6b2519d46150c19f69ee46abc5116d2af1 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Mon, 12 Feb 2018 21:26:23 +0100 Subject: [PATCH 5/7] QA: Add xp.web.srv.Server interface --- src/main/php/xp/web/dev/Buffer.class.php | 7 +++++++ src/main/php/xp/web/srv/Develop.class.php | 2 +- src/main/php/xp/web/srv/Server.class.php | 15 +++++++++++++++ src/main/php/xp/web/srv/Standalone.class.php | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100755 src/main/php/xp/web/srv/Server.class.php diff --git a/src/main/php/xp/web/dev/Buffer.class.php b/src/main/php/xp/web/dev/Buffer.class.php index 76595c89..e975650b 100755 --- a/src/main/php/xp/web/dev/Buffer.class.php +++ b/src/main/php/xp/web/dev/Buffer.class.php @@ -16,6 +16,13 @@ public function write($bytes) { $this->bytes.= $bytes; } + /** + * Drain this buffered output to a given output instance, closing it + * once finished. + * + * @param web.io.Output $out + * @return void + */ public function drain(Output $out) { $out->begin($this->status, $this->message, $this->headers); $out->write($this->bytes); diff --git a/src/main/php/xp/web/srv/Develop.class.php b/src/main/php/xp/web/srv/Develop.class.php index d18e8085..b60ae18c 100755 --- a/src/main/php/xp/web/srv/Develop.class.php +++ b/src/main/php/xp/web/srv/Develop.class.php @@ -10,7 +10,7 @@ use peer\Socket; use io\IOException; -class Develop { +class Develop implements Server { private $host, $port; /** diff --git a/src/main/php/xp/web/srv/Server.class.php b/src/main/php/xp/web/srv/Server.class.php new file mode 100755 index 00000000..de2b3762 --- /dev/null +++ b/src/main/php/xp/web/srv/Server.class.php @@ -0,0 +1,15 @@ + Date: Mon, 12 Feb 2018 21:33:13 +0100 Subject: [PATCH 6/7] Include "Remote-Addr" to be consistent with standalone input --- src/main/php/xp/web/SAPI.class.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/php/xp/web/SAPI.class.php b/src/main/php/xp/web/SAPI.class.php index 8625cab5..0db80cbd 100755 --- a/src/main/php/xp/web/SAPI.class.php +++ b/src/main/php/xp/web/SAPI.class.php @@ -35,7 +35,12 @@ public function scheme() { return 'http'; } public function uri() { return $_SERVER['REQUEST_URI']; } /** @return [:string] */ - public function headers() { return getallheaders(); } + public function headers() { + yield 'Remote-Addr' => $_SERVER['REMOTE_ADDR']; + foreach (getallheaders() as $name => $value) { + yield $name => $value; + } + } /** @return string */ public function readLine() { From 1d03457b8fa46d1c09e8dadd675b3ababfb8e270 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Mon, 12 Feb 2018 21:42:43 +0100 Subject: [PATCH 7/7] Add button title --- src/main/php/xp/web/dev/console.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/php/xp/web/dev/console.html b/src/main/php/xp/web/dev/console.html index cdc3e551..7ff8e308 100755 --- a/src/main/php/xp/web/dev/console.html +++ b/src/main/php/xp/web/dev/console.html @@ -26,7 +26,7 @@

DEBUG

- +
%1$s