diff --git a/src/middleware.ts b/src/middleware.ts
index 05bb025..49720c0 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -162,8 +162,13 @@ function get_route_handler(App: Component, routes: RouteObject[], store_getter:
? () => fs.readFileSync(`${locations.app()}/template.html`, 'utf-8')
: (str => () => str)(fs.readFileSync(`${locations.dest()}/template.html`, 'utf-8'));
- function handle_route(route: RouteObject, req: Req, res: ServerResponse) {
- req.params = route.params(route.pattern.exec(req.path));
+ const not_found_route = routes.find((route: RouteObject) => route.error === '4xx');
+ const error_route = routes.find((route: RouteObject) => route.error === '5xx');
+
+ function handle_route(route: RouteObject, req: Req, res: ServerResponse, status = 200, error: Error | string = null) {
+ req.params = error
+ ? {}
+ : route.params(route.pattern.exec(req.path));
const handlers = route.handlers[Symbol.iterator]();
@@ -174,7 +179,14 @@ function get_route_handler(App: Component, routes: RouteObject[], store_getter:
const { value: handler, done } = handlers.next();
if (done) {
- handle_error(req, res, 404, 'Not found');
+ if (route.error) {
+ // there was an error rendering the error page!
+ res.statusCode = status;
+ res.end(error instanceof Error ? error.message : error);
+ } else {
+ handle_route(not_found_route, req, res, 404, 'Not found');
+ }
+
return;
}
@@ -186,7 +198,7 @@ function get_route_handler(App: Component, routes: RouteObject[], store_getter:
// preload main.js and current route
// TODO detect other stuff we can preload? images, CSS, fonts?
const link = []
- .concat(chunks.main, chunks[route.id])
+ .concat(chunks.main, chunks[route.id] || chunks[`_${route.error}`]) // TODO this is gross
.filter(file => !file.match(/\.map$/))
.map(file => `<${req.baseUrl}/client/${file}>;rel="preload";as="script"`)
.join(', ');
@@ -197,7 +209,7 @@ function get_route_handler(App: Component, routes: RouteObject[], store_getter:
const props = { params: req.params, query: req.query, path: req.path };
let redirect: { statusCode: number, location: string };
- let error: { statusCode: number, message: Error | string };
+ let preload_error: { statusCode: number, message: Error | string };
Promise.resolve(
mod.preload ? mod.preload.call({
@@ -205,7 +217,7 @@ function get_route_handler(App: Component, routes: RouteObject[], store_getter:
redirect = { statusCode, location };
},
error: (statusCode: number, message: Error | string) => {
- error = { statusCode, message };
+ preload_error = { statusCode, message };
},
fetch: (url: string, opts?: any) => {
const parsed = new URL(url, `http://127.0.0.1:${process.env.PORT}${req.baseUrl ? req.baseUrl + '/' :''}`);
@@ -245,7 +257,7 @@ function get_route_handler(App: Component, routes: RouteObject[], store_getter:
store
}, req) : {}
).catch(err => {
- error = { statusCode: 500, message: err };
+ preload_error = { statusCode: 500, message: err };
}).then(preloaded => {
if (redirect) {
res.statusCode = redirect.statusCode;
@@ -255,8 +267,8 @@ function get_route_handler(App: Component, routes: RouteObject[], store_getter:
return;
}
- if (error) {
- handle_error(req, res, error.statusCode, error.message);
+ if (preload_error) {
+ handle_route(error_route, req, res, preload_error.statusCode, preload_error.message);
return;
}
@@ -370,84 +382,19 @@ function get_route_handler(App: Component, routes: RouteObject[], store_getter:
}
}
} catch (error) {
- handle_error(req, res, 500, error);
+ handle_route(error_route, req, res, 500, error || 'Internal server error');
}
}
next();
}
- const not_found_route = routes.find((route: RouteObject) => route.error === '4xx');
- const error_route = routes.find((route: RouteObject) => route.error === '5xx');
-
- function handle_error(req: Req, res: ServerResponse, statusCode: number, message: Error | string) {
- res.statusCode = statusCode;
- res.setHeader('Content-Type', 'text/html');
-
- const error = message instanceof Error ? message : new Error(message);
-
- const not_found = statusCode >= 400 && statusCode < 500;
-
- const route = not_found
- ? not_found_route
- : error_route;
-
- function render_page({ head, css, html }) {
- const page = template()
- .replace('%sapper.base%', ``)
- .replace('%sapper.scripts%', ``)
- .replace('%sapper.html%', html)
- .replace('%sapper.head%', `${head}`)
- .replace('%sapper.styles%', (css && css.code ? `` : ''));
-
- res.end(page);
- }
-
- function handle_notfound() {
- const title: string = not_found
- ? 'Not found'
- : `Internal server error: ${error.message}`;
-
- render_page({ head: '', css: null, html: title });
- }
-
- if (route) {
- const handlers = route.handlers[Symbol.iterator]();
-
- function next() {
- const { value: handler, done } = handlers.next();
-
- if (done) {
- handle_notfound();
- } else if (handler.type === 'page') {
- render_page(handler.module.render({
- status: statusCode,
- error
- }, {
- store: store_getter && store_getter(req)
- }));
- } else {
- const handle_method = mod[method_export];
- if (handle_method) {
- handle_method(req, res, next);
- } else {
- next();
- }
- }
- }
-
- next();
- } else {
- handle_notfound();
- }
- }
-
return function find_route(req: Req, res: ServerResponse) {
for (const route of routes) {
if (!route.error && route.pattern.test(req.path)) return handle_route(route, req, res);
}
- handle_error(req, res, 404, 'Not found');
+ handle_route(not_found_route, req, res, 404, 'Not found');
};
}