-
-
Notifications
You must be signed in to change notification settings - Fork 38
/
app.ts
95 lines (92 loc) · 2.48 KB
/
app.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright 2019-2020 Yusuke Sakurai. All rights reserved. MIT license.
import {
listenAndServe,
listenAndServeTls,
ServeListener,
ServeOptions,
ServerRequest,
} from "./server.ts";
import { createLogger, Logger, Loglevel, namedLogger } from "./logger.ts";
import { createRouter, Router } from "./router.ts";
import { RoutingError } from "./error.ts";
export interface App extends Router {
/** Start listening with given addr */
listen(addr: Deno.ListenOptions, opts?: ServeOptions): ServeListener;
/** Start listening for HTTPS server */
listenTls(
tlsOptions: Deno.ListenTlsOptions,
opts?: ServeOptions,
): ServeListener;
}
export interface AppOptions {
logger?: Logger;
logLevel?: Loglevel;
}
/** Create App */
export function createApp(
opts: AppOptions = {
logger: createLogger(),
},
): App {
const { info, error } = namedLogger("servest:router", opts.logger);
const router = createRouter();
const finalErrorHandler = async (e: any, req: ServerRequest) => {
if (e instanceof RoutingError) {
await req.respond({
status: e.status,
body: e.message,
});
} else {
if (e instanceof Error) {
await req.respond({
status: 500,
body: e.stack,
});
if (e.stack) {
error(e.stack);
}
} else {
await req.respond({
status: 500,
body: "Internal Server Error",
});
error(e);
}
}
};
const handleRoute = async (p: string, req: ServerRequest) => {
try {
await router.handleRoute(p, req);
} catch (e) {
if (!req.isResponded()) {
await finalErrorHandler(e, req);
}
} finally {
if (!req.isResponded()) {
await finalErrorHandler(new RoutingError(404), req);
}
info(`${req.respondedStatus()} ${req.method} ${req.url}`);
}
};
function listen(
addr: Deno.ListenOptions,
opts?: ServeOptions,
): ServeListener {
const listener = listenAndServe(addr, (req) => handleRoute("", req), opts);
info(`listening on ${addr.hostname || ""}:${addr.port}`);
return listener;
}
function listenTls(
listenOptions: Deno.ListenTlsOptions,
opts?: ServeOptions,
): ServeListener {
const listener = listenAndServeTls(
listenOptions,
(req) => handleRoute("", req),
opts,
);
info(`listening on ${listenOptions.hostname || ""}:${listenOptions.port}`);
return listener;
}
return { ...router, handleRoute, listen, listenTls };
}