-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
135 lines (116 loc) · 4.29 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
123
124
125
126
127
128
129
130
131
132
133
134
135
/* jshint esnext: true, node: true */
/*
Improved server, based (very loosely) on the script provided from
the WPI CS4241 course.
Author: Andrew Ray
Supports:
Direct full-path requests: http://domain/path will load the file at /path, if it exists
Directory index requests: http://domain/path will load the file at /path/indexname,
if it exists and /path is not a file
File requests w/o ext: http://domain/path will load the file at /path.assumeext, if it
exists and /path is not a file or a directory, and does not already have an extension
404 Handling: http://domain/path will load the file at /path404, in other
cases. If /path404 does not exist, then no content will be served.
Logging:
All requests are logged to console. The path that was assumed by the system, and the
status code it returned are listed.
*/
const exts = {"html": "text/html",
"css" : "text/css",
"js" : "application/javascript",
"png" : "image/png",
"jpg" : "image/jpeg",
"txt" : "text/plain",
"ico" : "image/vnd.microsoft.icon",
"json": "application/json",
"md" : "text/markdown",
"svg" : "image/svg+xml",
"default" : "text/html"
};
const path404 = "404.html"; // path to 404 error page
const path403 = "403.html"; // path to 403 error page
const indexname = "index.html"; // index pages will be located at this file in each folder
const assumeext = "html"; // extension to assume if none given
const defport = 8080; // port to use if process.env.PORT not set
var http = require('http'),
fs = require('fs'),
url = require('url'),
port = process.env.PORT || defport,
pad = require('pad');
function log (path, status, ip, type) {
type = type || "";
if (path.length < 25) {
console.log(pad(path,25) + status + " " + pad(type, 25) + ip);
}
else {
console.log(path);
console.log(pad("",25) + status + " " + pad(type, 25) + ip);
}
}
var server = http.createServer( (req, res) => {
var stats, path, ext, mime;
var uri = url.parse(req.url);
path = uri.pathname;
path = "public" + path;
if ((path.substr(path.lastIndexOf("/") + 1,1) === ".") ||
(path.includes(".."))) {
// permission denied, file was private
fs.readFile(path403, (error, content) => { // Load the 404 page!
res.writeHead(403);
if (error) { // could not load 403 page. Should just end response here.
res.end();
console.log(path + ": 403 Forbidden, and 403 page could not be loaded.");
}
else {
res.end(content, {'Content-type': 'text/html'});
console.log(pad(path, 25) + "403 ");
}
});
return;
}
if (path.toLocaleLowerCase() === "public/readme.md") {
path = "public/../README.md";
}
ext = path.substring(path.lastIndexOf(".") + 1);
mime = exts[ext] || exts.default;
if (!path) path = indexname; // check edge case where the path is now empty (no directory component)
try {
stats = fs.lstatSync(path);
if (stats.isDirectory()) { // handle case where path is a directory
path += "/" + indexname; // append /index.html to get the index for that directory
}
}
catch (e) { // this will trigger if the path doesn't point to something.
if (!path.includes(".")) {
path += "." + assumeext; // handle the case where a file was requested with no extension; assume html
}
}
/*
There is an edge case where a directory path that already ended in a slash will
result in a double slash in the final path. Replace that double slash with a
single slash. In HTTP, double slashes and single slashes are equivalent, but
can break some server and client scripts.
*/
path = path.replace(/\/\//g, '/');
fs.readFile(path, (error, content) => {
if (error) {
fs.readFile(path404, (error, content) => { // Load the 404 page!
res.writeHead(404);
if (error) { // could not load 404 page. Should just end response here.
res.end();
}
else {
res.end(content, {'Content-type': 'text/html'});
}
log(path, 404, req.connection.remoteAddress);
});
}
else {
res.writeHead(200, {'Content-type': mime});
res.end(content, 'utf-8');
log(path, 200, req.connection.remoteAddress, mime);
}
});
});
server.listen(port);
console.log('Process listening on '+port);