-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
188 lines (179 loc) · 7.19 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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
* A basic HTTP server made using NodeJS which is lightweight, has a small footprint yet is powerful. Reminds me of Yoda! :P
*
* author: kapil kashyap
*/
const config = require('./config.json');
const { parseArgs } = require('node:util');
const fs = require('fs');
const http = require('http');
const url = require('url');
// command line options
const options = {
host: {
type: 'string',
short: 'h',
},
port: {
type: 'string',
short: 'p',
},
deploy: {
type: 'string',
short: 'd',
},
info: {
type: 'string',
short: 'i'
}
};
const args = process.argv.slice(2);
const { values: cmdArgs } = parseArgs({ args, options });
if (config == null || config.base == null) {
console.info(`Server could not be started. Please make sure your configuration file is correct!`);
}
// utility method to determine the type of content being accessed
const getContentType = (urlPath) => {
if (urlPath.indexOf('.js') !== -1 || urlPath.indexOf('.mjs') !== -1) {
return 'text/javascript';
}
if (urlPath.indexOf('.json') !== -1) {
return 'application/json';
}
if (urlPath.indexOf('.css') !== -1) {
return 'text/css';
}
if (config.imageTypeExtensions.find(x => urlPath.indexOf(x) !== -1)) {
return 'image';
}
if (urlPath.indexOf('.txt') !== -1) {
return 'text/plain';
}
if (urlPath.indexOf('.xml') !== -1) {
return 'application/xml';
}
return 'text/html';
};
const protocol = "http";
// Take it from the command line or the config file. Fallback to 'localhost'
const host = cmdArgs.host || config.host || 'localhost';
// Take it from the command line or the config file. Fallback to '3333'
const port = cmdArgs.port || config.port || '3333';
// Take it from the command line or the config file. Fallback to 'examples'
const deploymentFolder = cmdArgs.deploy || config.deploy || 'examples';
// Take it from the command line or the config file. Fallback to false
const showInfo = (cmdArgs.info && cmdArgs.info === 'true') || config.info || false;
// generated a base url to be used to load resources
const baseUrl = __dirname + config.base;
const serverRunningOn = `${protocol}://${host}:${port}`;
// a request listener method that will be used to parse all the incoming requests
const requestListener = (req, res) => {
// parse the requested url
const parsedUrl = url.parse(req.url, true);
// fetch the content type of the requested resource
const contentType = getContentType(parsedUrl.pathname);
// check if we are access the root
if (parsedUrl.pathname === '/') {
// read deployment directory to generate list of projects on runtime
fs.readdir(baseUrl + `/${deploymentFolder}`, (err, directories) => {
let html = '<!-- This file is dynamically generated by the server -->\r\n';
if (err) {
console.log(err);
// cleanup deployments.html
html += `<div class="entry">Something's wrong!</div>`;
fs.writeFile(`${baseUrl}/artifacts/deployments.html`, html, (err) => {
if (err) {
console.log(err);
}
});
} else {
let _url = null;
// iterate through the directories and generate url for each project
directories.forEach((directory) => {
if (config.ignore != null && config.ignore.directories != null && config.ignore.directories.length > 0 && config.ignore.directories.indexOf(directory) !== -1) {
console.log(`ignored directory: ${directory}`);
return;
}
// assuming that index.html is the end-point to access the project
_url = `${serverRunningOn}/${deploymentFolder}/${directory}/index.html`;
// html construct to be displayed on home page
html += `<div class="entry" title="${directory}"><a href="${_url}" target="_blank">${directory}</a></div>`;
});
// once the html construct is ready, write it into deployments.html file
// this file will be used on the home page to display a list of projects, if available
fs.writeFile(`${baseUrl}/artifacts/deployments.html`, html, (err) => {
if (err) {
console.log(err);
}
});
}
});
// load the home page
fs.readFile(`${baseUrl}/artifacts/home.html`, (err, data) => {
if (err) {
throw err;
}
// set the proper content type
res.setHeader('Content-Type', contentType);
res.writeHead(200);
res.end(data);
});
} else {
// if we are not accessing the root, try to read the file and load its contents
fs.readFile(baseUrl + parsedUrl.pathname, (err, data) => {
if (err) {
// if the path is invalid, then display an error page displaying the exception
const errorMsgCntrStyle = `
display: flex;
margin-top: 20px;
justify-content: center;
flex-direction: column;
`;
const errorMsgHeaderStyle = `
display: flex;
background-color: #757575;
height: 40px;
font-size: x-large;
color: #ffffff;
align-items: center;
margin: 0 0 10px 0;
padding: 0 5px;
`;
const errorMsgStyle = `
padding: 0 5px;
`;
// set the proper content type
res.setHeader('Content-Type', 'text/html');
res.writeHead(500);
res.end(`
<div style="${errorMsgCntrStyle}">
<div style="${errorMsgHeaderStyle}">The greatest teacher, failure is.</div>
<div style="${errorMsgStyle}">${err}</div>
</div>
`);
return;
}
// set the proper content type
res.setHeader('Content-Type', contentType);
res.writeHead(200);
res.end(data);
});
}
}
// create HTTP server by passing it the request listener function
const server = http.createServer(requestListener);
// register the server to listen on the configured host and port
server.listen(port, host, () => {
if (showInfo) {
// display the server configuration
console.info('Server configuration:');
console.info({
...config,
host,
port,
deploy: deploymentFolder
});
}
// display a server up and running message on Node CLI
console.info(`Server is up and running on ${serverRunningOn}`);
});