-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
120 lines (107 loc) · 3.33 KB
/
index.js
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
const http = require("http");
const https = require("https");
const Koa = require("koa");
const morgan = require("koa-morgan");
const cors = require("koa-cors");
const helmet = require("koa-helmet");
const compress = require("koa-compress");
const bodyParser = require("koa-bodyparser");
const serve = require("koa-static");
const send = require("koa-send");
// const { createNamespace } = require("continuation-local-storage");
const { createNamespace } = require("cls-hooked"); // experimental but works with async/await
const { v4: uuidv4 } = require("uuid");
const {
middleware: forceSSL,
createServer: createRedirectServer,
} = require("@salsita/koa-force-ssl");
const defaultLog = require("@salsita/log");
const requestNSName = "koa request";
const requestId = "requestId";
const request = createNamespace(requestNSName);
const getRequestId = () => request.get(requestId);
morgan.token(requestId, getRequestId);
const app = new Koa();
const createWeb = (options = {}) => {
const { log = defaultLog, ssl, allowUnsecure = !ssl } = options;
app.on("error", (err) => log("error", "Error in Koa framework", err));
// configure server - headers, logging, etc.
app.use(async (ctx, next) => {
const context = request.createContext();
request.enter(context);
try {
request.set(requestId, ctx.request.headers["x-request-id"] || uuidv4());
return await next();
} finally {
request.exit(context);
}
});
app.use(
morgan(
`:date[iso] - web (rid:${requestId}): :method :url :status :res[content-length] - :response-time ms`
)
);
app.use(forceSSL({ allowUnsecure }));
app.use(cors(options.cors));
app.use(helmet(options.helmet));
app.use(compress(options.compress));
app.use(bodyParser(options.bodyParser));
if (!ssl !== allowUnsecure) {
log(
"warn",
`Probably misconfigured server - ${
ssl ? "allowed HTTP while using SSL" : "not allowed HTTP when not using SSL"
}`
);
}
const createServer = async () =>
ssl ? https.createServer(await ssl, app.callback()) : http.createServer(app.callback());
return {
createServer,
addRoutes: (actions, distDir) => {
// api routes
app.use(actions.routes(), actions.allowedMethods());
if (distDir) {
// static assets
app.use(serve(distDir));
// otherwise send index
app.use((ctx) => send(ctx, `${distDir}/index.html`));
}
},
start: (server, port) => {
if (!port) {
throw new Error("No port specified");
}
server.listen(port, (err) => {
if (err) {
log("error", "Error when starting server", err);
process.exit(1);
} else {
const protocol = `http${allowUnsecure ? "" : "s"}`;
log("info", "----");
log("info", `==> Server is running on port ${port}`);
log("info", `==> Send requests to ${protocol}://localhost:${port}`);
}
});
// eslint-disable-next-line eqeqeq
if (ssl && port == 443) {
createRedirectServer().listen(80);
}
},
shutdown: (server) => {
server.close((err) => {
if (err) {
log("error", "Error when shutting down server", err);
process.exitCode = 1;
}
process.exit();
});
},
};
};
module.exports = {
app,
createWeb,
requestNSName,
getRequestId,
};