Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development console #35

Merged
merged 7 commits into from
Feb 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/main/php/web/Application.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
7 changes: 6 additions & 1 deletion src/main/php/xp/web/SAPI.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
15 changes: 12 additions & 3 deletions src/main/php/xp/web/Source.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
));
}
}

Expand Down
31 changes: 31 additions & 0 deletions src/main/php/xp/web/dev/Buffer.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php namespace xp\web\dev;

use web\io\Output;

class Buffer extends Output {
public $status, $message, $headers;
public $bytes= '';

public function begin($status, $message, $headers) {
$this->status= $status;
$this->message= $message;
$this->headers= $headers;
}

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);
$out->close();
}
}
74 changes: 74 additions & 0 deletions src/main/php/xp/web/dev/Console.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php namespace xp\web\dev;

use web\Filter;
use web\Response;

/**
* The development console captures content written via `var_dump()`,
* `echo` or other builtin output statements and - if any - displays it
* inside an easily readable format above the real output, using a 200
* HTTP response status.
*
* @see php://ob_start
*/
class Console implements Filter {
private $template;

/** @param string $name */
public function __construct($name= 'xp/web/dev/console') {
$this->template= $name.'.html';
}

/**
* Creates HTML table rows
*
* @param [:var] $headers
* @return string
*/
private function rows($headers) {
$r= '';
foreach ($headers as $name => $value) {
$r.= '<tr>
<td class="name">'.htmlspecialchars($name).'</td>
<td class="value">'.htmlspecialchars(implode(', ', $value)).'</td>
</tr>';
}
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 {
ob_start();
$result= $invocation->proceed($req, new Response($buffer));
} finally {
$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;
}
}
68 changes: 68 additions & 0 deletions src/main/php/xp/web/dev/console.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!DOCTYPE html>
<html>
<head>
<title>Debug</title>
<style type="text/css">
body { font-family: "Segoe UI",Arial,Helvetica; background-color: rgb(27, 43, 52); color: rgb(205, 211, 222); }
#content { margin: 2em; }
h1 img { float: left; margin-right: 0.5em; }
h1 #code { padding: 0.1em 0.5em; background-color: rgb(102, 153, 204); color: white; border-radius: 0.1em; }
#debug { border: 1px dotted rgb(205, 211, 222); overflow: hidden; padding: 0.5em; font-size: 13px; }
button.clip { float: right; }
h2 #status { color: rgb(102, 153, 204); }
table { margin-bottom: 1.5em; }
td { padding: 0.3em; }
td.name { background-color: rgb(41, 56, 65); }
td.value { color: rgb(249, 145, 87); font-family: monospace; font-size: 13px; }
button { background-color: rgb(41, 56, 65); cursor: pointer; border-radius: 0.1em; border: none; }
button:hover { opacity: .65; transition: all 150ms linear; }
</style>
</head>
<body bgcolor="#ffffff" text="#000000">
<div id="content">
<h1>
<img width="59" height="48" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAAAwCAYAAACv4gJwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAEeSURBVGhD7ZdNCsIwEEaj1/AILvUCHsStuPIwrsStB/EEnkmTkoESMklq85/vgQwFS+frm2npZrc/fsUgbHUdAoTtFYTtFW/Y0+3RVHXBvnrUye/7VR+1g6tvvGdDRqJmuP6HMmsNG7qvJSYgtC/b/6xj3OKDac6iB5TPLBl9XQ5Tzcn5+Zmqrz+YjWGW7nZKzGvBrIbrP+p7Vt19+tFxCbj+o5tVY0ajpmqJwFnMKkyzOfbZJItZsjo3W4JsZmsg287WAMxKYBZmGwJmJUOZxfcszFrgdiMloX3B7BqzIZB9136H7OESYFaSzCwZ/YcY14bZ1DtbAq5/a9hesY6xYs3OlcTVNxuWxoBObqW61g9j3CsI2ysI2ysDhRXiB5CuA+ASNuP/AAAAAElFTkSuQmCC" alt="Debug"/>

<span id="code">DEBUG</span>
</h1>
<div id="debug">
<button class="clip" title="Copy to clipboard" onclick="clip(document.getElementById('output').innerText); flash(document.getElementById('debug'))">📋</button>
<pre id="output">%1$s</pre>
</div>

<!-- Original HTTP response -->
<h2>HTTP/1.1 <span id="status">%2$d %3$s</span></h2>
<table id="headers">
%4$s
</table>
<pre id="body">%5$s</pre>
</div>
<script type="text/javascript">
function clip(text) {
if (window.clipboardData) {
window.clipboardData.setData('Text', text);
} else {
var t = document.createElement('textarea');
t.value = text;
t.style.position = 'fixed';
t.style.top = 0;
t.style.left = 0;
t.style.width = '2em';
t.style.height = '2em';
t.style.background = 'transparent';
t.style.border = 'none';
document.body.appendChild(t);
t.select();
document.execCommand('copy');
document.body.removeChild(t);
}
}

function flash(div) {
div.style.transition = 'all 150ms linear';
div.style.backgroundColor = 'rgb(41, 56, 65)';
setTimeout(function() { div.style.backgroundColor = null; }, 100);
}
</script>
</body>
</html>
4 changes: 2 additions & 2 deletions src/main/php/xp/web/srv/Develop.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use peer\Socket;
use io\IOException;

class Develop {
class Develop implements Server {
private $host, $port;

/**
Expand Down Expand Up @@ -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);

Expand Down
15 changes: 15 additions & 0 deletions src/main/php/xp/web/srv/Server.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php namespace xp\web\srv;

interface Server {

/**
* Serve requests
*
* @param string $source
* @param string $profile
* @param io.Path $webroot
* @param io.Path $docroot
* @param string[] $config
*/
public function serve($source, $profile, $webroot, $docroot, $config);
}
2 changes: 1 addition & 1 deletion src/main/php/xp/web/srv/Standalone.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use web\Environment;
use xp\web\Source;

abstract class Standalone {
abstract class Standalone implements Server {
private $server, $url;

public function __construct($server, $url) {
Expand Down