FIX: ErrorPage generating empty responses for 403/401 requests

Previously by setting the response status code inside the action, this prevented response bodies from being included due to 403/401 being matched by SS_HTTPResponse::isFinished() (which stops popular

I assume SS_HTTPResponse::isFinished() is valid for the permission error use case (and I would be hesitant to change it) so this simply moves the declaration of the response status code till after the parent has populated the body of the response.
This commit is contained in:
Will Rossiter 2013-11-18 16:32:15 +13:00
parent e444b359ec
commit ddc2e3822b
3 changed files with 46 additions and 18 deletions

View File

@ -42,7 +42,9 @@ class ErrorPage extends Page {
/**
* Get a {@link SS_HTTPResponse} to response to a HTTP error code if an
* {@link ErrorPage} for that code is present.
* {@link ErrorPage} for that code is present. First tries to serve it
* through the standard SilverStripe request method. Falls back to a static
* file generated when the user hit's save and publish in the CMS
*
* @param int $statusCode
*
@ -50,11 +52,17 @@ class ErrorPage extends Page {
*/
public static function response_for($statusCode) {
// first attempt to dynamically generate the error page
if($errorPage = DataObject::get_one('ErrorPage', "\"ErrorPage\".\"ErrorCode\" = $statusCode")) {
$errorPage = ErrorPage::get()->filter(array(
"ErrorCode" => $statusCode
))->first();
if($errorPage) {
Requirements::clear();
Requirements::clear_combined_files();
return ModelAsController::controller_for($errorPage)->handleRequest(new SS_HTTPRequest('GET', ''), DataModel::inst());
return ModelAsController::controller_for($errorPage)->handleRequest(
new SS_HTTPRequest('GET', ''), DataModel::inst()
);
}
// then fall back on a cached version
@ -62,13 +70,13 @@ class ErrorPage extends Page {
$statusCode,
class_exists('Translatable') ? Translatable::get_current_locale() : null
);
if(file_exists($cachedPath)) {
$response = new SS_HTTPResponse();
$response->setStatusCode($statusCode);
$response->setBody(file_get_contents($cachedPath));
return $response;
}
}
@ -129,13 +137,12 @@ class ErrorPage extends Page {
}
}
}
}
}
/**
* Returns an array of arrays, each of which defines
* properties for a new ErrorPage record.
* Returns an array of arrays, each of which defines properties for a new
* ErrorPage record.
*
* @return array
*/
@ -159,6 +166,7 @@ class ErrorPage extends Page {
)
)
);
$this->extend('getDefaultRecords', $data);
return $data;
@ -316,14 +324,20 @@ class ErrorPage extends Page {
*/
class ErrorPage_Controller extends Page_Controller {
public function init() {
parent::init();
/**
* Overload the provided {@link Controller::handleRequest()} to append the
* correct status code post request since otherwise permission related error
* pages such as 401 and 403 pages won't be rendered due to
* {@link SS_HTTPResponse::isFinished() ignoring the response body.
*
* @param SS_HTTPRequest
* @param DataModel
*/
public function handleRequest(SS_HTTPRequest $request, DataModel $model = NULL) {
$body = parent::handleRequest($request, $model);
$this->response->setStatusCode($this->ErrorCode);
$action = $this->request->param('Action');
if(!$action || $action == 'index') {
$this->getResponse()->setStatusCode($this->failover->ErrorCode ? $this->failover->ErrorCode : 404);
}
return $this->response;
}
}

View File

@ -60,5 +60,14 @@ class ErrorPageTest extends FunctionalTest {
/* Don't show the error page in the search */
$this->assertEquals($page->ShowInSearch, 0, 'Don\'t show the error page in search');
}
}
public function testBehaviourOf403() {
$page = $this->objFromFixture('ErrorPage', '403');
$page->publish('Stage', 'Live');
$response = $this->get($page->Link());
$this->assertEquals($response->getStatusCode(), '403');
$this->assertNotNull($response->getBody(), 'We have body text from the error page');
}
}

View File

@ -3,4 +3,9 @@ ErrorPage:
Title: Page Not Found
URLSegment: page-not-found
Content: My error page body
ErrorCode: 404
ErrorCode: 404
403:
Title: Permission Failure
URLSegment: permission-denied
Content: You do not have permission to view this page
ErrorCode: 403