Skip to content

Commit

Permalink
Don't die on unexpected errors
Browse files Browse the repository at this point in the history
  • Loading branch information
nichtich committed Mar 13, 2017
1 parent 17387e4 commit 1a05ca1
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 28 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Expand Up @@ -5,8 +5,9 @@ clover.xml
.php_cs.cache
phpdoc/

# config files
config
# config and log files
config/
log/

# API documentation
docs/
2 changes: 1 addition & 1 deletion public/.htaccess
Expand Up @@ -4,5 +4,5 @@
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !robots.txt
RewriteCond %{REQUEST_URI} !favicon.ico
RewriteRule ^(.*)$ index.php/$1 [L]
RewriteRule (.*) index.php/$1 [QSA,L]
</IfModule>
18 changes: 9 additions & 9 deletions public/index.php
@@ -1,8 +1,6 @@
<?php
/**
* GBV DAIA application main script.
*
* All HTTP queries except static files must be routed to this script.
* GBV DAIA main script to route all HTTP queries except static files through.
*/

include __DIR__.'/../vendor/autoload.php';
Expand All @@ -11,20 +9,22 @@

$path = $_SERVER['PATH_INFO'] ?? '/';

if ( $request->method != 'OPTIONS' && (!$path or $path == '/') and !count($request->ids) ) {
if ( $request->method != 'OPTIONS' and $path == '/' and !count($request->ids) ) {
include 'startseite.php';
exit;
}

# TODO: catch errors in config_
# TODO: catch errors during config initialization

$config = '../config';
$level = Psr\Log\LogLevel::DEBUG;
$config = new GBV\DAIA\FileConfig($config, $level);
#$config = new GBV\DAIA\GitConfig($config, $level);

$serverFactory = new GBV\DAIA\ServerFactory($config);
$server = $serverFactory->makeServer($path);

$response = $server->queryResponse($request);
$factory = new GBV\DAIA\ServerFactory($config);
$server = $factory->makeServer($path);
$response = $server->query($request);

# TODO: für ausgewählte Bibliotheken: XML-Format erlauben (veraltet)

$response->send();
2 changes: 1 addition & 1 deletion src/DAIA/ErrorServer.php
Expand Up @@ -17,7 +17,7 @@ public function __construct(Error $error)
$this->error = $error;
}

public function queryImplementation(Request $request): Response
public function queryHandler(Request $request): Response
{
throw $this->error;
}
Expand Down
29 changes: 19 additions & 10 deletions src/DAIA/Server.php
Expand Up @@ -6,30 +6,33 @@
/**
* DAIA Server boilerplate.
*
* A Server derived from this class must implement method `queryImplementation`.
* A Server derived from this class must implement method `queryHandler`.
* This method should return a DAIA Response or throw a DAIA Error. A Server
* can be queried via method `query` that always returns a DAIA ResponseData
* (Response or ErrorResponse).
* can be queried via method `query`.
*
* ~~~php
* use DAIA\Request;
* use DAIA\Response;
*
* class MyDAIAServer extends \DAIA\Server {
* public function queryImplementation(Request $request): Response {
* public function queryHandler(Request $request): Response {
* if (...) throw new \DAIA\Error(...);
* return new Response(...);
* }
* }
*
* $server = new MyDAIAServer();
* $response = $server->query($request); # \DAIA\Response or \DAIA\ErrorResponse
* $response = $server->query($request);
* ~~~
*
* @package DAIA
*/
abstract class Server
{
public abstract function queryHandler(Request $request): Response;

protected function exceptionHandler($context) { }

public function query(Request $request): ResponseData
{
if ($request->method == 'OPTIONS') {
Expand All @@ -40,12 +43,18 @@ public function query(Request $request): ResponseData
if (array_search($request->method, ['GET','HEAD','OPTIONS']) === false) {
throw new Error(405, 'Unexpected HTTP verb');
}
return $this->queryImplementation($request);
return $this->queryHandler($request);
} catch(Error $e) {
return $e->response;
}
# TODO: catch other kinds of errors?
} catch(\Throwable $e) {
if ($this->exceptionHandler([
'request' => $request,
'server' => $this,
'exception' => $e
])) {
throw $e;
}
return new ErrorResponse(500, 'Unexpected internal server error');
}
}

abstract public function queryImplementation(Request $request): Response;
}
4 changes: 4 additions & 0 deletions src/GBV/DAIA/FileConfig.php
Expand Up @@ -32,6 +32,10 @@ public function __construct(string $dir, $level = LogLevel::NOTICE)
protected function readConfig()
{
// TODO: read and enable logging configuration
// move to logging class?
// log standard to default log
// send critical errors to critical file
// log everything to detailled log
}

static function defaultLogger($level = LogLevel::NOTICE): LoggerInterface
Expand Down
8 changes: 6 additions & 2 deletions src/GBV/DAIA/Server.php
Expand Up @@ -34,7 +34,7 @@ public function __construct(Config $config)
$this->config = $config;
$this->log = $config->logger();

// configure HTTP logging
// configure HTTP request logging
$stack = \GuzzleHttp\HandlerStack::create();
$stack->unshift(\GuzzleHttp\Middleware::log($this->log,
new \GuzzleHttp\MessageFormatter("{method} {uri} {code}"),
Expand All @@ -57,7 +57,7 @@ public function __construct(Config $config)
/**
* @throws \DAIA\Error
*/
public function queryImplementation(\DAIA\Request $request): \DAIA\Response
public function queryHandler(\DAIA\Request $request): \DAIA\Response
{
// DAIA Request object: INFO
# $this->log->info('request', ['request'=>$request, 'isil' => $isil]);
Expand Down Expand Up @@ -97,6 +97,10 @@ public function queryImplementation(\DAIA\Request $request): \DAIA\Response

return $response;
}

protected function exceptionHandler($context) {
$this->log->critical('Unexpected error', $context);
}

public function queryDocument(DocumentID $id)
{
Expand Down
4 changes: 2 additions & 2 deletions tests/DAIA/ErrorServerTest.php
Expand Up @@ -21,8 +21,8 @@ public function testQuery()
/**
* @expectedException DAIA\Error
*/
public function testQueryImplementation()
public function testQueryHandler()
{
$this->server->queryImplementation(new Request());
$this->server->queryHandler(new Request());
}
}
2 changes: 2 additions & 0 deletions tests/DAIA/ResponseTest.php
Expand Up @@ -18,5 +18,7 @@ public function testResponse()
'Content-Type' => ['application/json; charset=utf-8'],
'X-DAIA-Version' => ['1.0.0'],
]);

$this->assertSame($res->getHeaders('foo')['Content-Type'], ['application/javascript']);
}
}
21 changes: 20 additions & 1 deletion tests/DAIA/ServerTest.php
Expand Up @@ -8,9 +8,16 @@ class ServerTest extends \PHPUnit\Framework\TestCase
public function setUp()
{
$this->server = new class extends Server {
public function queryImplementation(Request $request): Response {
public $context;
public function queryHandler(Request $request): Response {
if (count($request->ids)>1) {
1 % 0;
}
return new Response();
}
public function exceptionHandler($context) {
$this->context = $context;
}
};
}

Expand All @@ -37,4 +44,16 @@ public function testUnexpectedHTTPVerbRequest()

$this->assertSame(405, $res->getStatusCode());
}

public function testUnexpectedServerError()
{
$req = Request::fromGlobals([], ['id'=>'x:1|x:2']);
$res = $this->server->query($req);

$this->assertSame(500, $res->getStatusCode());
$error = $this->server->context;
$this->assertSame($error['server'], $this->server);
$this->assertSame($error['request'], $req);
$this->assertInstanceOf('DivisionByZeroError', $error['exception']);
}
}

0 comments on commit 1a05ca1

Please sign in to comment.