Added general Exception catch/response. Added extension points to all response methods.

This commit is contained in:
cpenny 2018-03-07 11:41:27 +13:00 committed by Russell Michell
parent 3c1055e2f0
commit 4d5ded4e95
3 changed files with 126 additions and 16 deletions

View File

@ -154,6 +154,7 @@ class RestfulServer extends Controller
// authenticate through HTTP BasicAuth // authenticate through HTTP BasicAuth
$this->member = $this->authenticate(); $this->member = $this->authenticate();
try {
// handle different HTTP verbs // handle different HTTP verbs
if ($this->request->isGET() || $this->request->isHEAD()) { if ($this->request->isGET() || $this->request->isHEAD()) {
return $this->getHandler($className, $id, $relation); return $this->getHandler($className, $id, $relation);
@ -170,6 +171,9 @@ class RestfulServer extends Controller
if ($this->request->isDELETE()) { if ($this->request->isDELETE()) {
return $this->deleteHandler($className, $id, $relation); return $this->deleteHandler($className, $id, $relation);
} }
} catch (\Exception $e) {
return $this->exceptionThrown($this->getRequestDataFormatter($className), $e);
}
// if no HTTP verb matches, return error // if no HTTP verb matches, return error
return $this->methodNotAllowed(); return $this->methodNotAllowed();
@ -681,7 +685,11 @@ class RestfulServer extends Controller
$this->getResponse()->setStatusCode(401); $this->getResponse()->setStatusCode(401);
$this->getResponse()->addHeader('WWW-Authenticate', 'Basic realm="API Access"'); $this->getResponse()->addHeader('WWW-Authenticate', 'Basic realm="API Access"');
$this->getResponse()->addHeader('Content-Type', 'text/plain'); $this->getResponse()->addHeader('Content-Type', 'text/plain');
return "You don't have access to this item through the API.";
$reponse = "You don't have access to this item through the API.";
$this->extend(__FUNCTION__, $reponse);
return $reponse;
} }
/** /**
@ -692,7 +700,11 @@ class RestfulServer extends Controller
// return a 404 // return a 404
$this->getResponse()->setStatusCode(404); $this->getResponse()->setStatusCode(404);
$this->getResponse()->addHeader('Content-Type', 'text/plain'); $this->getResponse()->addHeader('Content-Type', 'text/plain');
return "That object wasn't found";
$reponse = "That object wasn't found";
$this->extend(__FUNCTION__, $reponse);
return $reponse;
} }
/** /**
@ -702,7 +714,11 @@ class RestfulServer extends Controller
{ {
$this->getResponse()->setStatusCode(405); $this->getResponse()->setStatusCode(405);
$this->getResponse()->addHeader('Content-Type', 'text/plain'); $this->getResponse()->addHeader('Content-Type', 'text/plain');
return "Method Not Allowed";
$reponse = "Method Not Allowed";
$this->extend(__FUNCTION__, $reponse);
return $reponse;
} }
/** /**
@ -712,7 +728,11 @@ class RestfulServer extends Controller
{ {
$this->response->setStatusCode(415); // Unsupported Media Type $this->response->setStatusCode(415); // Unsupported Media Type
$this->getResponse()->addHeader('Content-Type', 'text/plain'); $this->getResponse()->addHeader('Content-Type', 'text/plain');
return "Unsupported Media Type";
$reponse = "Unsupported Media Type";
$this->extend(__FUNCTION__, $reponse);
return $reponse;
} }
/** /**
@ -729,6 +749,28 @@ class RestfulServer extends Controller
'messages' => $result->getMessages(), 'messages' => $result->getMessages(),
]; ];
$this->extend(__FUNCTION__, $response, $result);
return $responseFormatter->convertArray($response);
}
/**
* @param DataFormatter $responseFormatter
* @param \Exception $e
* @return string
*/
protected function exceptionThrown(DataFormatter $responseFormatter, \Exception $e)
{
$this->getResponse()->setStatusCode(500);
$this->getResponse()->addHeader('Content-Type', $responseFormatter->getOutputContentType());
$response = [
'type' => get_class($e),
'message' => $e->getMessage(),
];
$this->extend(__FUNCTION__, $response, $e);
return $responseFormatter->convertArray($response); return $responseFormatter->convertArray($response);
} }

View File

@ -3,6 +3,7 @@
namespace SilverStripe\RestfulServer\Tests; namespace SilverStripe\RestfulServer\Tests;
use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestComment; use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestComment;
use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestExceptionThrown;
use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestSecretThing; use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestSecretThing;
use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestPage; use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestPage;
use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestAuthor; use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestAuthor;
@ -38,6 +39,8 @@ class RestfulServerTest extends SapphireTest
RestfulServerTestPage::class, RestfulServerTestPage::class,
RestfulServerTestAuthor::class, RestfulServerTestAuthor::class,
RestfulServerTestAuthorRating::class, RestfulServerTestAuthorRating::class,
RestfulServerTestValidationFailure::class,
RestfulServerTestExceptionThrown::class,
]; ];
protected function urlSafeClassname($classname) protected function urlSafeClassname($classname)
@ -685,4 +688,17 @@ class RestfulServerTest extends SapphireTest
$responseArr = Convert::xml2array($response->getBody()); $responseArr = Convert::xml2array($response->getBody());
$this->assertEquals('SilverStripe\\ORM\\ValidationException', $responseArr['type']); $this->assertEquals('SilverStripe\\ORM\\ValidationException', $responseArr['type']);
} }
public function testExceptionThrownWithPOST()
{
$urlSafeClassname = $this->urlSafeClassname(RestfulServerTestExceptionThrown::class);
$url = "{$this->baseURI}/api/v1/$urlSafeClassname/";
$data = [
'Content' => 'Test',
];
$response = Director::test($url, $data, null, 'POST');
// Assumption: XML is default output
$responseArr = Convert::xml2array($response->getBody());
$this->assertEquals(\Exception::class, $responseArr['type']);
}
} }

View File

@ -0,0 +1,52 @@
<?php
namespace SilverStripe\RestfulServer\Tests\Stubs;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DataObject;
/**
* Class RestfulServerTestExceptionThrown
* @package SilverStripe\RestfulServer\Tests\Stubs
*
* @property string Content
* @property string Title
*/
class RestfulServerTestExceptionThrown extends DataObject implements TestOnly
{
private static $api_access = true;
private static $table_name = 'RestfulServerTestExceptionThrown';
private static $db = array(
'Content' => 'Text',
'Title' => 'Text',
);
public function onBeforeWrite()
{
parent::onBeforeWrite();
throw new \Exception('This is an exception test');
}
public function canView($member = null)
{
return true;
}
public function canEdit($member = null)
{
return true;
}
public function canDelete($member = null)
{
return true;
}
public function canCreate($member = null, $context = array())
{
return true;
}
}