ENHANCEMENT ajshort: Allow a HTTPResponse to be encapsulated in a HTTPResponse_Exception, which can be later caught by the request handler.

MINOR ajshort: Updated RequestHandler->httpError() to interrupt the execution flow by throwing an exception.

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@80226 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Sam Minnee 2009-06-27 08:48:44 +00:00
parent c0c72e4c53
commit e2dcc48d48
3 changed files with 93 additions and 11 deletions

46
core/control/HTTPResponse.php Normal file → Executable file
View File

@ -234,3 +234,49 @@ class HTTPResponse extends Object {
} }
} }
/**
* A {@link HTTPResponse} encapsulated in an exception, which can interrupt the processing flow and be caught by the
* {@link RequestHandler} and returned to the user.
*
* Example Usage:
* <code>
* throw new HTTPResponse_Exception('This request was invalid.', 400);
* throw new HTTPResponse_Exception(new HTTPResponse('There was an internal server error.', 500));
* </code>
*
* @package sapphire
* @subpackage control
*/
class HTTPResponse_Exception extends Exception {
protected $response;
/**
* @see HTTPResponse::__construct();
*/
public function __construct($body = null, $statusCode = null, $statusDescription = null) {
if($body instanceof HTTPResponse) {
$this->setResponse($body);
} else {
$this->setResponse(new HTTPResponse($body, $statusCode, $statusDescription));
}
parent::__construct($this->getResponse()->getBody(), $this->getResponse()->getStatusCode());
}
/**
* @return HTTPResponse
*/
public function getResponse() {
return $this->response;
}
/**
* @param HTTPResponse $response
*/
public function setResponse(HTTPResponse $response) {
$this->response = $response;
}
}

View File

@ -125,8 +125,13 @@ class RequestHandler extends ViewableData {
$action = "index"; $action = "index";
} else if(!is_string($action)) { } else if(!is_string($action)) {
user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR); user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR);
} }
$result = $this->$action($request);
try {
$result = $this->$action($request);
} catch(HTTPResponse_Exception $responseException) {
$result = $responseException->getResponse();
}
} else { } else {
return $this->httpError(403, "Action '$action' isn't allowed on class $this->class"); return $this->httpError(403, "Action '$action' isn't allowed on class $this->class");
} }
@ -225,14 +230,15 @@ class RequestHandler extends ViewableData {
} }
/** /**
* Throw an HTTP error instead of performing the normal processing * Throws a HTTP error response encased in a {@link HTTPResponse_Exception}, which is later caught in
* @todo This doesn't work properly right now. :-( * {@link RequestHandler::handleAction()} and returned to the user.
*
* @param int $errorCode
* @param string $errorMessage
* @uses HTTPResponse_Exception
*/ */
function httpError($errorCode, $errorMessage = null) { public function httpError($errorCode, $errorMessage = null) {
$r = new HTTPResponse(); throw new HTTPResponse_Exception($errorMessage, $errorCode);
$r->setBody($errorMessage);
$r->setStatuscode($errorCode);
return $r;
} }
/** /**
@ -243,4 +249,4 @@ class RequestHandler extends ViewableData {
function getRequest() { function getRequest() {
return $this->request; return $this->request;
} }
} }

View File

@ -105,6 +105,23 @@ class RequestHandlingTest extends SapphireTest {
$this->assertEquals("extendedMethod", $response->getBody()); $this->assertEquals("extendedMethod", $response->getBody());
} }
public function testHTTPException() {
$exception = Director::test('RequestHandlingTest_Controller/throwexception');
$this->assertEquals(400, $exception->getStatusCode());
$this->assertEquals('This request was invalid.', $exception->getBody());
$responseException = (Director::test('RequestHandlingTest_Controller/throwresponseexception'));
$this->assertEquals(500, $responseException->getStatusCode());
$this->assertEquals('There was an internal server error.', $responseException->getBody());
}
public function testHTTPError() {
$response = Director::test('RequestHandlingTest_Controller/throwhttperror');
$this->assertEquals(404, $response->getStatusCode());
$this->assertEquals('This page does not exist.', $response->getBody());
}
} }
/** /**
@ -176,6 +193,19 @@ class RequestHandlingTest_Controller extends Controller {
new FormAction("myAction") new FormAction("myAction")
)); ));
} }
public function throwexception() {
throw new HTTPResponse_Exception('This request was invalid.', 400);
}
public function throwresponseexception() {
throw new HTTPResponse_Exception(new HTTPResponse('There was an internal server error.', 500));
}
public function throwhttperror() {
$this->httpError(404, 'This page does not exist.');
}
} }
/** /**
@ -311,4 +341,4 @@ class RequestHandlingTest_SubclassedFormField extends RequestHandlingTest_FormFi
function customSomething() { function customSomething() {
return "customSomething"; return "customSomething";
} }
} }