Skip to content
This repository has been archived by the owner on Jul 2, 2021. It is now read-only.

Commit

Permalink
Allows to configure default (or custom) error pages
Browse files Browse the repository at this point in the history
Through the start options we can configure custom error pages for
4xx or 5xx errors. If not, there are default pages loaded.

Issue #17
  • Loading branch information
Mystilund committed Jun 8, 2019
1 parent 638c4cd commit 744a8d7
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 18 deletions.
8 changes: 8 additions & 0 deletions examples/01-basic/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ const path = require('path')

module.exports = {
router: [
{
type: 'ROUTE',
method: ['GET'],
path: '/error-page',
callback: (req, res) => {
throw new Error('Simulate 500')
}
},
{
type: 'ROUTE',
method: ['GET'],
Expand Down
43 changes: 43 additions & 0 deletions src/assets/default_pages/4xx.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<style>
html {
height: 100%;
}
body {
min-height: 100%;
height: 100%;
}
* {
font-family: Verdana, Arial, Tahoma, sans-serif;
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
height: 100%;
}
.container .center-block {
font-size: 18px;
text-align: center;
}
.container .center-block strong {
font-size: 50px;
}
</style>
</head>
<body>
<div class="container">
<div class="center-block">
<div>
<strong>404</strong>
</div>
<div>The page could not be found</div>
</div>
</div>
</body>
</html>
41 changes: 41 additions & 0 deletions src/assets/default_pages/5xx.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<style>
html { height: 100%; }
body {
min-height: 100%;
height: 100%;
}
* {
font-family: Verdana, Tahoma, Arial, sans-serif;
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
height: 100%;
}
.container .center-block {
font-size: 18px;
text-align: center;
}
.container .center-block strong {
font-size: 50px;
}
</style>
</head>
<body>
<div class="container">
<div class="center-block">
<div>
<strong>500</strong>
</div>
<div>The page could not be found</div>
</div>
</div>
</body>
</html>
7 changes: 3 additions & 4 deletions src/cherry.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const PluginConfigurator = require('./configuration/PluginConfigurator')
const HookConfigurator = require('./configuration/HookConfigurator')
const MiddlewareConfigurator = require('./configuration/MiddlewareConfigurator')
const RouteConfigurator = require('./configuration/RouteConfigurator')
const DefaultErrorPageConfigurator = require('./configuration/DefaultErrorPageConfigurator')
const ORMManager = require('./orm/ORMManager')
const CherryServerManager = require('./server/CherryServerManager')

Expand All @@ -14,6 +15,7 @@ class Cherry {
this.hookConfigurator = new HookConfigurator()
this.middlewareConfigurator = new MiddlewareConfigurator()
this.routeConfigurator = new RouteConfigurator()
this.defaultErrorPageConfigurator = new DefaultErrorPageConfigurator()

this.ormManager = new ORMManager(this)
this.cherryServerManager = new CherryServerManager(this)
Expand All @@ -24,14 +26,11 @@ class Cherry {
* @param {Object} options The options to configure Cherry
*/
configure (options = {}) {
// if (check.isDefined(options, 'onError')) {
// this.dispatcher.onError(options.onError)
// }

this.pluginConfigurator.configure(options)
this.hookConfigurator.configure(options)
this.middlewareConfigurator.configure(options)
this.routeConfigurator.configure(options)
this.defaultErrorPageConfigurator.configure(options)

if (this.pluginConfigurator.getPlugin('DatabaseEngine') && typeof options.database !== 'undefined') {
this.ormManager.setPlugin(this.pluginConfigurator.getPlugin('DatabaseEngine'))
Expand Down
51 changes: 51 additions & 0 deletions src/configuration/DefaultErrorPageConfigurator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const path = require('path')
const CherryConfigurator = require('../abstract/CherryConfigurator')
const check = require('../helpers/check')

/**
* The configurator of the default error pages
* Inherits from the abstract CherryConfigurator
*/
class DefaultErrorPageConfigurator extends CherryConfigurator {
constructor () {
super({})

this.manager.clientErrorPage = this.clientErrorPage
this.manager.serverErrorPage = this.serverErrorPage
}

/**
* Configure the default pages process in case of error
* @param {Object} options The options set to the cherry instance
*/
configure (options) {
if (check.isDefined(options, 'defaultPages')) {
Object.keys(this.manager).forEach((defaultPage) => {
if (check.isDefined(options.defaultPages, defaultPage)) {
this.manager[defaultPage] = options.defaultPages[defaultPage]
}
})
}
}

/**
* The default process in case of a 4xx page
* @param {CherryIncomingMessage} req The current request
* @param {CherryServerResponse} res The response object
*/
clientErrorPage (req, res) {
res.html(path.join(__dirname, '../assets/default_pages/4xx.html'), { statusCode: 404 })
}

/**
* The default process in case of a 5xx page
* @param {CherryIncomingMessage} req The current request
* @param {CherryServerResponse} res The response object
* @param {Error} err The error catch
*/
serverErrorPage (req, res, err) {
res.html(path.join(__dirname, '../assets/default_pages/5xx.html'), { statusCode: 500 })
}
}

module.exports = DefaultErrorPageConfigurator
8 changes: 2 additions & 6 deletions src/processor/Dispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,11 @@ class Dispatcher {
request._route = matchingRouteResponse.getMatchingRoute()
this.resolver.resolve(request, response)
}).catch((err) => {
// @todo : manage error
console.log(err)
response.writeHead(500)
response.end('')
this.cherry.defaultErrorPageConfigurator.manager.serverErrorPage(request, response, err)
})
}
} else {
response.writeHead(404)
response.end('')
this.cherry.defaultErrorPageConfigurator.manager.clientErrorPage(request, response)
}
}
}
Expand Down
7 changes: 2 additions & 5 deletions src/processor/Resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,9 @@ class Resolver {
{ request, response, processResult: asyncResult },
asyncResult
)
}).catch((e) => {
// @todo use the onError method
console.log('Error in _resolve', e)
}).catch((error) => {
if (!response.finished) {
response.writeHead(500, { 'Content-Type': 'application/json' })
response.end(JSON.stringify(e))
this.cherry.defaultErrorPageConfigurator.manager.serverErrorPage(request, response, error)
}
})
} else {
Expand Down
39 changes: 39 additions & 0 deletions test/specs/configuration/DefaultErrorPageConfigurator.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const DefaultErrorPageConfigurator = require(path.join(__root, './src/configuration/DefaultErrorPageConfigurator'))

const default404 = () => {
return 404
}
let defaultErrorPageConfigurator = null
let customDefaultErrorPageConfigurator = null
const fakeResponse = {
errorCode: 0,
html: function (path, options) {
this.errorCode = options.statusCode
}
}

describe('DefaultErrorPageConfigurator', () => {
before(() => {
defaultErrorPageConfigurator = new DefaultErrorPageConfigurator()
customDefaultErrorPageConfigurator = new DefaultErrorPageConfigurator()
})

it('Tests the method configure', () => {
customDefaultErrorPageConfigurator.configure({
defaultPages: {
clientErrorPage: default404
}
})
})

it('Tests the method clientErrorPage', () => {
defaultErrorPageConfigurator.manager.clientErrorPage({}, fakeResponse)
expect(fakeResponse.errorCode).to.be.equal(404)
expect(customDefaultErrorPageConfigurator.manager.clientErrorPage({}, fakeResponse)).to.be.equal(404)
})

it('Tests the method serverErrorPage', () => {
defaultErrorPageConfigurator.manager.serverErrorPage({}, fakeResponse)
expect(fakeResponse.errorCode).to.be.equal(500)
})
})
9 changes: 6 additions & 3 deletions test/specs/processor/Dispatcher.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint no-unused-expressions: 0 */
const Dispatcher = require(path.join(__root, './src/processor/Dispatcher'))
const DefaultErrorPageConfigurator = require(path.join(__root, './src/configuration/DefaultErrorPageConfigurator'))

/* Simulation values */

Expand Down Expand Up @@ -28,7 +29,8 @@ let fakeCherryInstance = {
}
}
}
}
},
defaultErrorPageConfigurator: new DefaultErrorPageConfigurator()
}
let fakeRequest = {
url: 'http://localhost:3000/test',
Expand All @@ -44,10 +46,11 @@ let fakeRequest = {
boundDataToRequest: async () => {}
}
let fakeResponse = {
writeHead (httpCode) {
html: () => {},
writeHead: (httpCode) => {
expect(httpCode).to.be.above(400)
},
end (response) {
end: (response) => {
expect(typeof response).to.be.equal('string')
}
}
Expand Down

0 comments on commit 744a8d7

Please sign in to comment.