hw4: ex5 passes tests
This commit is contained in:
parent
50d194ac2d
commit
0cb7ed641a
1 changed files with 79 additions and 7 deletions
|
@ -25,12 +25,13 @@ function error(res, code, text = '') {
|
|||
</html>`);
|
||||
}
|
||||
|
||||
function fileData(reqUrl, prefix, wantExt = true) {
|
||||
const uri = decodeURIComponent(url.parse(reqUrl).pathname
|
||||
.substring(prefix.length)).replace(/\/+$/, '');
|
||||
function fileData(reqUrl, prefix, options = {}) {
|
||||
const uri = decodeURIComponent(
|
||||
!options.isPath ? url.parse(reqUrl).pathname.substring(prefix.length) : reqUrl
|
||||
).replace(/\/+$/, '');
|
||||
const file = __dirname + '/NodeStaticFiles' + uri;
|
||||
const name = file.substring(file.lastIndexOf('/') + 1);
|
||||
const ext = wantExt ? name.substring(name.indexOf('.') + 1) : null;
|
||||
const ext = !options.noExt ? name.substring(name.indexOf('.') + 1) : null;
|
||||
|
||||
return {
|
||||
uri: !uri ? '/' : uri,
|
||||
|
@ -46,7 +47,7 @@ routes['explore'] = (req, res) => {
|
|||
return;
|
||||
}
|
||||
|
||||
const { uri, file, name } = fileData(req.url, '/explore', false);
|
||||
const { uri, file, name } = fileData(req.url, '/explore', { noExt: true });
|
||||
|
||||
fs.readdir(file, { withFileTypes: true }, (err, dir) => {
|
||||
if (err) {
|
||||
|
@ -174,8 +175,80 @@ routes['upload'] = (req, res) => {
|
|||
</html>`);
|
||||
};
|
||||
|
||||
function wordMap(string) {
|
||||
const words = string.trim().split(/[^\w]+/);
|
||||
const wordDict = {};
|
||||
for (const word of words) {
|
||||
if (word.trim() == '') {
|
||||
continue;
|
||||
}
|
||||
if (!wordDict[word]) {
|
||||
wordDict[word] = 1;
|
||||
} else {
|
||||
wordDict[word]++;
|
||||
}
|
||||
}
|
||||
return wordDict;
|
||||
}
|
||||
|
||||
routes['stats'] = (req, res) => {
|
||||
res.end()
|
||||
const p = url.parse(req.url, true);
|
||||
if (p.pathname != '/stats' && p.pathname != '/stats') {
|
||||
error(res, 404, 'Only "/stats" path is accessible under this prefix');
|
||||
return;
|
||||
}
|
||||
|
||||
const reqFile = p && p.query && '/' + p.query['file'];
|
||||
if (!reqFile) {
|
||||
error(res, 400, 'Search parameter "file" is required');
|
||||
return;
|
||||
}
|
||||
|
||||
const { file, name, ext } = fileData(reqFile, '/stats', { isPath: true });
|
||||
if (ext != 'txt' && ext != 'html') {
|
||||
error(res, 400, 'Only txt and html files can be processed by /stats');
|
||||
return;
|
||||
}
|
||||
|
||||
fs.readFile(file, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
error(res, 404, 'File not found: ' + JSON.stringify(err));
|
||||
return;
|
||||
}
|
||||
|
||||
const dict = wordMap(data);
|
||||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
res.write(`<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Stats for ${reqFile}</title>
|
||||
<style>
|
||||
table { border-collapse: collapse; }
|
||||
td, th { border: 1px solid black; }
|
||||
th { font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Word frequency count for "${reqFile}"</h1>
|
||||
<table id="frequency-tbl">
|
||||
<thead>
|
||||
<tr><th>Word</th><th>Freq.</th></tr>
|
||||
</thead>
|
||||
<tbody>`);
|
||||
|
||||
for (const word in dict) {
|
||||
res.write(`<tr>
|
||||
<td class="word">${word}</td>
|
||||
<td class="frequency">${dict[word]}</td>
|
||||
</tr>`);
|
||||
}
|
||||
|
||||
res.end(`</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>`);
|
||||
});
|
||||
};
|
||||
|
||||
// Main server handler
|
||||
|
@ -190,6 +263,5 @@ function onRequest(req, res) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
http.createServer(onRequest).listen(3000);
|
||||
console.log('Server started at localhost:3000');
|
||||
|
|
Reference in a new issue