From f6d54b18fd874329cca82258cc6310b87a082c48 Mon Sep 17 00:00:00 2001 From: "Claudio Maggioni (maggicl)" Date: Sun, 13 Oct 2019 13:29:03 +0200 Subject: [PATCH] hw4: ready for submission --- hw4/Claudio_Maggioni/readme.md | 4 ++ hw4/Claudio_Maggioni/server.js | 77 ++++++++++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 hw4/Claudio_Maggioni/readme.md diff --git a/hw4/Claudio_Maggioni/readme.md b/hw4/Claudio_Maggioni/readme.md new file mode 100644 index 0000000..780f491 --- /dev/null +++ b/hw4/Claudio_Maggioni/readme.md @@ -0,0 +1,4 @@ +# Bonuses implemented: +- *Excercise 5*, File statistics +- *Excercise 6*, Tag cloud +- *Excercise 7*, JSON Tag cloud diff --git a/hw4/Claudio_Maggioni/server.js b/hw4/Claudio_Maggioni/server.js index f4bf563..f369133 100755 --- a/hw4/Claudio_Maggioni/server.js +++ b/hw4/Claudio_Maggioni/server.js @@ -8,6 +8,16 @@ const formidable = require('formidable'); const routes = Object.create(null); +function noSubPaths(req, path) { + const p = url.parse(req.url); + if (p.pathname != path && p.pathname != path) { + error(res, 404, `Only "${path}" path is accessible under this prefix`); + return true; + } else { + return false; + } +} + function error(res, code, text = '') { res.writeHead(code, { 'Content-Type': 'text/html' }); res.end(` @@ -28,7 +38,7 @@ function error(res, code, text = '') { function fileData(reqUrl, prefix, options = {}) { const uri = decodeURIComponent( !options.isPath ? url.parse(reqUrl).pathname.substring(prefix.length) : reqUrl - ).replace(/\/+$/, ''); + ).replace(/\/+$/, ''); const file = __dirname + '/NodeStaticFiles' + uri; const name = file.substring(file.lastIndexOf('/') + 1); const ext = !options.noExt ? name.substring(name.indexOf('.') + 1) : null; @@ -69,7 +79,7 @@ routes['explore'] = (req, res) => { name: e.name, dir: !e.isFile(), path: (e.isFile() ? '/file' : '/explore') + uri + - (uri == '/' ? '' : '/') + e.name + (uri == '/' ? '' : '/') + e.name }); } @@ -191,12 +201,8 @@ function wordMap(string) { return wordDict; } -routes['stats'] = (req, res) => { +function getFileStats(req, res, path, callback) { 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) { @@ -204,9 +210,9 @@ routes['stats'] = (req, res) => { return; } - const { file, name, ext } = fileData(reqFile, '/stats', { isPath: true }); + const { file, name, ext } = fileData(reqFile, path, { isPath: true }); if (ext != 'txt' && ext != 'html') { - error(res, 400, 'Only txt and html files can be processed by /stats'); + error(res, 400, `Only txt and html files can be processed by ${path}`); return; } @@ -217,6 +223,18 @@ routes['stats'] = (req, res) => { } const dict = wordMap(data); + + callback({ reqFile: reqFile, dict: dict }); + }); +} + + +routes['stats'] = (req, res) => { + if (noSubPaths(req, '/stats')) { + return; + } + + getFileStats(req, res, '/stats', ({ reqFile, dict }) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.write(` @@ -251,6 +269,47 @@ routes['stats'] = (req, res) => { }); }; +routes['cloud'] = (req, res) => { + if (noSubPaths(req, '/cloud')) { + return; + } + + getFileStats(req, res, '/cloud', ({ reqFile, dict }) => { + if (req.headers.accept && req.headers.accept == 'application/json') { + res.writeHead(200, {'Content-Type': 'application/json' }); + res.end(JSON.stringify(dict, null, 2)); + } else { + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.write(` + + + + Cloud for ${reqFile} + + + +

Tag cloud for "${reqFile}"

+
`); + + const max = Math.max(...Object.values(dict)); + const min = Math.min(...Object.values(dict)); + + for (const word in dict) { + const size = 0.75 + ((dict[word] - min) / max) * 4 + 'rem'; + res.write(` ${word} `); + } + + res.end(`
+ + `); + } + }); +}; + // Main server handler function onRequest(req, res) { const pathname = url.parse(req.url).pathname;