koa.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. const _render = require('./page-renderer');
  2. const _path = require('path');
  3. const _fs = require('fs-magic');
  4. const _jsonReader = require('./json-reader');
  5. // wrapper to add custom options
  6. async function createDispatcher(options={}){
  7. // merge options
  8. const opt = {
  9. template: options.template || _path.join(__dirname, '../assets/template.ejs'),
  10. css: options.css || _path.join(__dirname, '../assets/layout.css'),
  11. lang: options.lang || 'en_US',
  12. footer: options.footer || null,
  13. error: options.error || null,
  14. page_title: options.page_title || null
  15. };
  16. // load page template
  17. const tpl = await _fs.readFile(opt.template, 'utf8');
  18. // load styles
  19. const css = await _fs.readFile(opt.css, 'utf8');
  20. // load page definitions
  21. const pages = await _jsonReader(_path.join(__dirname, '../i18n/pages-' + opt.lang + '.json'));
  22. // multi-type support
  23. // @see https://github.com/koajs/koa/blob/master/docs/api/response.md#responseistypes
  24. return function dispatchRequest(page, httpStatusCode, ctx){
  25. // page available ?
  26. if (!pages[page]){
  27. // use "internal server error" as default
  28. page = '500';
  29. httpStatusCode = null;
  30. }
  31. // set http status code
  32. ctx.status = httpStatusCode || 500;
  33. // extract page date
  34. const pageData = pages[page];
  35. // set page title
  36. let page_title = undefined;
  37. if(opt && opt.page_title) {
  38. page_title = opt.page_title.replace('%code%', page);
  39. page_title = page_title.replace('%title%', pageData.title);
  40. }
  41. // set error
  42. let error = 'Error '+ page
  43. if(opt && opt.error) {
  44. error = opt.error.replace('%code%', page);
  45. }
  46. // multiple response formats
  47. switch (ctx.accepts('json', 'html', 'text')){
  48. // jsonn response
  49. case 'json':
  50. ctx.type = 'json';
  51. ctx.body = {
  52. error: pageData.title + ' - ' + pageData.message
  53. }
  54. break;
  55. // html response
  56. case 'html':
  57. ctx.type = 'html';
  58. ctx.body = _render(tpl, css, {
  59. code: httpStatusCode,
  60. title: pageData.title,
  61. message: pageData.message,
  62. footer: opt.footer,
  63. lang: opt.lang.substr(0, 2),
  64. error: error,
  65. page_title: page_title
  66. });
  67. break;
  68. // default: text response
  69. default:
  70. ctx.type = 'text/plain';
  71. ctx.body = pageData.title + ' - ' + pageData.message;
  72. }
  73. }
  74. }
  75. module.exports = async function httpErrorPages(options={}){
  76. // create new disptacher with given options
  77. const dispatch = await createDispatcher(options);
  78. // create error handler
  79. // @see https://github.com/koajs/koa/blob/master/docs/error-handling.md
  80. return async (ctx, next) => {
  81. try{
  82. // dispatch middleware chain
  83. await next();
  84. // route not found ?
  85. if (ctx.status === 404) {
  86. dispatch('404', 404, ctx);
  87. }
  88. }catch(err){
  89. // status code given ?
  90. if (err.status){
  91. // custom errorpage set ?
  92. dispatch(err.errorpage || err.status, err.status, ctx);
  93. // use default http500 page
  94. }else{
  95. dispatch('500', 500, ctx);
  96. }
  97. }
  98. }
  99. }