UNPKG

3.22 kBJavaScriptView Raw
1/*
2 * pub-server handle-errors.js
3 * NOTE:
4 * - this should be the last handler loaded by the server
5 * - depends on serve-pages being invoked before this
6 *
7 * copyright 2015-2020, Jürgen Leschner - github.com/jldec - MIT license
8 */
9
10/*eslint no-unused-vars: "off"*/
11
12var debug = require('debug')('pub:server');
13var path = require('path');
14var ppath = path.posix || path;
15var u = require('pub-util');
16
17module.exports = function handleErrors(server) {
18
19 // sugar
20 var opts = server.opts;
21 var log = opts.log;
22 var app = server.app;
23 var generator = server.generator;
24
25 app.use('/server/echo', testEcho);
26
27 // dev/test routes
28 if (!opts.production) {
29 app.use('/admin/testthrow', testThrow);
30 app.use('/admin/testerr', testErr);
31 app.use('/admin/testpost', testPost);
32 app.use('/admin/testget', testGet);
33 }
34
35 // mount 404 and 500 handlers
36 app.use(notFound);
37 app.use(errHandler);
38
39 return;
40
41 //--//--//--//--//--//--//--//--//--//--//
42
43 // return 404 except for html pages
44 function notFound(req, res) {
45
46 var ext = ppath.extname(req.path);
47 if ((!ext || /\.htm|\.html/i.test(ext)) && !u.size(req.query)) return error(404, req, res);
48
49 debug('notFound 404 %s', req.originalUrl);
50 res.status(404).end();
51 }
52
53 // error handler middleware - must have 4 parameters
54 // body-parser returns err.status = 400 on POST with invalid json (application/json content-type)
55 //
56 function errHandler(err, req, res, next) {
57 // if (!err.status) { log(err); }
58 log(err);
59 error(err.status || 500, req, res, u.str(err));
60 }
61
62 // general purpose error response
63 function error(status, req, res, msg) {
64 debug('error %s %s', status, req.originalUrl);
65 msg = msg || '';
66
67 var page = generator.page$['/' + status];
68
69 // avoid exposing error pages unless authorized
70 if (page) {
71 if (!server.isPageAuthorized || !server.isPageAuthorized(req, page)) {
72 if (server.login) return server.login(req, res);
73 else page = null;
74 }
75 }
76
77 if (!page) return res.status(status).send(u.escape(msg));
78
79 res.status(status).send(
80 generator.renderDoc(page)
81 .replace(/%s/g, u.escape(msg)) // TODO - replace with humane.js or proper template
82 .replace('<body', '<body data-err-status="' + status + '"' + (msg ? ' data-err-msg="' + u.escape(msg) + '"' : ''))
83 );
84 }
85
86 function testThrow() {
87 throw new Error('test throw');
88 }
89
90 function testErr(req, res) {
91 log(new Error('test err')); // will throw if no on('error') handler - see session.log
92 error(403, req, res, '/admin/testerr'); // forbidden
93 }
94
95 function testPost(req, res) {
96 log('/admin/testpost', req.body);
97 res.status(200).send('OK');
98 }
99
100 function testGet(req, res) {
101 log('/admin/testget', req.query);
102 res.status(200).send('OK');
103 }
104
105 function testEcho(req, res) {
106 res.send(echoreq(req));
107 }
108
109 function echoreq(req) {
110 return {
111 ip: req.ip,
112 method: req.method,
113 url: req.originalUrl,
114 headers: req.headers,
115 query: req.query,
116 params: req.params,
117 body: req.body,
118 now: Date(),
119 user: req.user,
120 sessionID: req.sessionID,
121 session: req.session
122 };
123 }
124};