forked from DeNepo/separation-of-concerns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
122 lines (100 loc) · 3.2 KB
/
server.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
121
122
const http = require('http');
const fs = require('fs');
const path = require('path');
const marked = require('./lib/marked.js');
const PORT = process.env.PORT || 3000;
const LOG_DIRNAME = `server-logs`;
const LOG_DIR = path.join(__dirname, LOG_DIRNAME);
const LOG_PATH = path.join(LOG_DIR, `${(new Date()).toJSON().replace(/:/g, '_')}.txt`);
const LOGS_LIMIT = 20;
let cycles = 0;
if (fs.existsSync(LOG_DIR)) {
const logs = fs.readdirSync(LOG_DIR);
if (logs.length > LOGS_LIMIT) {
console.log('--- clearing ' + (logs.length - LOGS_LIMIT) + ' old logs ---');
for (let i = 0; i < logs.length - LOGS_LIMIT; i++) {
const oldLog = path.join(LOG_DIR, logs[i]);
fs.unlinkSync(oldLog);
};
};
} else {
console.log(`--- creating ${LOG_DIRNAME} directory ---`);
fs.mkdirSync(LOG_DIR);
}
const log = (msg) => {
const cleanedMsg = msg.split(__dirname).join(' ... ');
console.log(cleanedMsg);
fs.appendFileSync(LOG_PATH, cleanedMsg + '\n');
};
const mime = {
'.md': 'text/html',
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpg',
'.gif': 'image/gif',
};
console.log('\n--- launching server ---\n');
const handleRequest = (req, res) => {
const cycle = ++cycles;
const studyMode = req.headers.study
? JSON.stringify({ study: req.headers.study })
: '';
log(`${cycle}. req: ${req.method} ${req.url} ${studyMode}`);
const reqUrlMinusParams = req.url.split('?')[0];
const relPath = reqUrlMinusParams === '/'
? './README.md'
: decodeURIComponent(reqUrlMinusParams);
const requestedFilePath = path.normalize(path.join(__dirname, relPath));
const extension = String(path.extname(relPath)).toLowerCase();
const contentType = mime[extension] || 'application/octet-stream';
const serveFile = (error, content) => {
let logMsg = '';
if (error) {
if (error.code === 'ENOENT') {
const html404 = `<!DOCTYPE html><html><head><title>404</title></head><body><h1>404: ${relPath}</h1></body></html>`;
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end(html404, 'utf-8');
logMsg = 'response: 404 ' + relPath;
} else {
const errMsg = `Server error: ${error.code} ..`;
res.writeHead(500);
res.end(errMsg);
res.end();
logMsg = errMsg;
}
} else {
res.writeHead(200, { 'Content-Type': contentType });
const finalContent = extension === '.md'
? marked(content.toString())
: content;
res.end(finalContent, 'utf-8');
logMsg = 'res: ' + relPath;
};
log(cycle + '. ' + logMsg);
};
fs.readFile(requestedFilePath, serveFile);
};
const listeningCB = (err) => {
if (err) {
log(err.stack);
} else {
log('Server running at http://localhost:' + PORT + '/');
};
}
http
.createServer(handleRequest)
.listen(PORT, listeningCB);
process.on('exit', function onExit(code) {
log('process.exit with code ' + code);
});
process.on('SIGINT', function onSIGINT() {
log('\nstopping server ...');
process.exit(0);
});
process.on('uncaughtException', function onUncaughtException(e) {
log('- uncaughtException -\n' + e.stack);
process.exit(99);
});