-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstackblitz-server.js
More file actions
117 lines (95 loc) · 2.9 KB
/
Copy pathstackblitz-server.js
File metadata and controls
117 lines (95 loc) · 2.9 KB
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
var fs = require('fs');
var http = require('http');
var path = require('path');
var url = require('url');
var root = __dirname;
var port = Number(process.env.PORT || 4200);
var host = process.env.HOST || '0.0.0.0';
var contentTypes = {
'.css': 'text/css; charset=utf-8',
'.html': 'text/html; charset=utf-8',
'.js': 'application/javascript; charset=utf-8',
'.json': 'application/json; charset=utf-8',
'.map': 'application/json; charset=utf-8',
'.svg': 'image/svg+xml',
'.ts': 'text/plain; charset=utf-8',
'.txt': 'text/plain; charset=utf-8'
};
function send(response, statusCode, body, contentType) {
response.writeHead(statusCode, {
'Content-Type': contentType || 'text/plain; charset=utf-8',
'Cache-Control': 'no-store'
});
response.end(body);
}
function sendFile(response, filePath) {
fs.readFile(filePath, function (error, body) {
if (error) {
console.error('[stackline] Failed to read static file:', error);
send(response, 500, 'Internal server error');
return;
}
send(response, 200, body, contentTypes[path.extname(filePath)] || 'application/octet-stream');
});
}
function safeFilePath(requestPath) {
var decoded;
var segments;
var safeSegments = [];
var filePath;
var relative;
try {
decoded = decodeURIComponent(requestPath);
} catch (error) {
return null;
}
if (decoded.indexOf('\0') !== -1) return null;
segments = decoded.split(/[\/\\]+/);
for (var index = 0; index < segments.length; index += 1) {
var segment = segments[index];
if (!segment || segment === '.') continue;
if (segment === '..' || !/^[A-Za-z0-9._~!$&'()+,;=:@% -]+$/.test(segment)) return null;
safeSegments.push(segment);
}
filePath = path.resolve.apply(path, [root].concat(safeSegments));
relative = path.relative(root, filePath);
if (relative === '..' || relative.indexOf('..' + path.sep) === 0 || path.isAbsolute(relative)) return null;
return filePath;
}
function handle(request, response) {
var parsed = url.parse(request.url);
var pathname = parsed.pathname || '/';
var filePath;
if (pathname === '/') {
sendFile(response, path.join(root, 'index.html'));
return;
}
filePath = safeFilePath(pathname);
if (!filePath) {
send(response, 400, 'Bad request');
return;
}
fs.stat(filePath, function (error, stat) {
if (!error && stat.isFile()) {
sendFile(response, filePath);
return;
}
if (!path.extname(pathname)) {
sendFile(response, path.join(root, 'index.html'));
return;
}
send(response, 404, 'Not found');
});
}
function startServer() {
return http.createServer(handle).listen(port, host, function () {
console.log('Available on:');
console.log(' http://127.0.0.1:' + port);
console.log('Hit CTRL-C to stop the server');
});
}
if (require.main === module) startServer();
module.exports = {
safeFilePath: safeFilePath,
startServer: startServer
};