UNPKG

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