diff --git a/labs/04/lang/en/en.json b/labs/04/lang/en/en.json new file mode 100644 index 0000000..e9660bb --- /dev/null +++ b/labs/04/lang/en/en.json @@ -0,0 +1,3 @@ +{ + "greeting": "Hello %1, What a beautiful day. Server current date and time is %2" +} diff --git a/labs/04/modules/fileManager.js b/labs/04/modules/fileManager.js new file mode 100644 index 0000000..4fa346f --- /dev/null +++ b/labs/04/modules/fileManager.js @@ -0,0 +1,26 @@ +const fs = require("fs"); +const path = require("path"); + +class FileManager { + constructor(baseDir) { + this.baseDir = baseDir; + } + + resolve(fileName) { + return path.join(this.baseDir, path.basename(fileName)); + } + + exists(fileName) { + return fs.existsSync(this.resolve(fileName)); + } + + append(fileName, text) { + fs.appendFileSync(this.resolve(fileName), `${text}\n`); + } + + read(fileName) { + return fs.readFileSync(this.resolve(fileName), "utf8"); + } +} + +module.exports = FileManager; diff --git a/labs/04/modules/math.js b/labs/04/modules/math.js new file mode 100644 index 0000000..8e3dbfc --- /dev/null +++ b/labs/04/modules/math.js @@ -0,0 +1,13 @@ +const PI = 3.141592654; + +exports.add = (a, b) => { + return a + b +} + +exports.subtract = (a, b) => { + return a - b +} + +exports.area = (r) => { + return 2*PI*r; +} diff --git a/labs/04/modules/utils.js b/labs/04/modules/utils.js new file mode 100644 index 0000000..da493f9 --- /dev/null +++ b/labs/04/modules/utils.js @@ -0,0 +1,19 @@ +class Utils { + getDate() { + return new Date().toString(); + } + + format(template, ...values) { + return template.replace(/%(\d+)/g, (match, index) => { + const value = values[Number(index) - 1]; + return value === undefined ? match : value; + }); + } + + escapeHtml(text) { + const entities = {"&": "&", "<": "<", ">": ">", "\"": """, "'": "'"}; + return text.replace(/[&<>"']/g, (char) => entities[char]); + } +} + +module.exports = Utils; diff --git a/labs/04/server.js b/labs/04/server.js new file mode 100644 index 0000000..25aee53 --- /dev/null +++ b/labs/04/server.js @@ -0,0 +1,89 @@ +const http = require("http"); +const fs = require("fs"); +const path = require("path"); +const Utils = require("./modules/utils"); +const FileManager = require("./modules/fileManager"); + +const PORT = process.env.PORT || 8000; + +class Server { + constructor(port) { + this.port = port; + this.utils = new Utils(); + this.files = new FileManager(__dirname); + this.strings = JSON.parse(fs.readFileSync(path.join(__dirname, "lang", "en", "en.json"), "utf8")); + } + + start() { + http.createServer((req, res) => this.handleRequest(req, res)).listen(this.port, () => { + console.log(`listening on port :${this.port}`); + }); + } + + handleRequest(req, res) { + if (req.method !== "GET") { + return this.send(res, 405, "text/plain", "Method not allowed"); + } + + const url = new URL(req.url, "http://localhost"); + + try { + if (url.pathname === "/") { + return this.send(res, 200, "text/plain", "Server Status: OK"); + } + if (/\/getDate\/?$/.test(url.pathname)) { + return this.handleGetDate(url, res); + } + if (/\/writeFile\/?$/.test(url.pathname)) { + return this.handleWriteFile(url, res); + } + const readMatch = url.pathname.match(/\/readFile\/(.+)$/); + if (readMatch) { + return this.handleReadFile(decodeURIComponent(readMatch[1]), res); + } + return this.send(res, 404, "text/plain", "Not found"); + } catch (err) { + return this.send(res, 500, "text/plain", `Server error: ${err.message}`); + } + } + + handleGetDate(url, res) { + const name = url.searchParams.get("name"); + if (!name) { + return this.send(res, 400, "text/plain", "Missing required query parameter: name"); + } + + const message = this.utils.format( + this.strings.greeting, + this.utils.escapeHtml(name), + this.utils.getDate() + ); + const html = `
${message}
`; + return this.send(res, 200, "text/html", html); + } + + handleWriteFile(url, res) { + const text = url.searchParams.get("text"); + if (text === null) { + return this.send(res, 400, "text/plain", "Missing required query parameter: text"); + } + + this.files.append("file.txt", text); + return this.send(res, 200, "text/plain", `Appended a new line to file.txt`); + } + + handleReadFile(fileName, res) { + if (!this.files.exists(fileName)) { + return this.send(res, 404, "text/plain", `File not found: ${fileName}`); + } + + return this.send(res, 200, "text/plain; charset=utf-8", this.files.read(fileName)); + } + + send(res, status, contentType, body) { + res.writeHead(status, {"Content-Type": contentType}); + res.end(body); + } +} + +new Server(PORT).start(); diff --git a/labs/04/testModule.js b/labs/04/testModule.js new file mode 100644 index 0000000..c840ae5 --- /dev/null +++ b/labs/04/testModule.js @@ -0,0 +1,2 @@ +const mo = require("./modules/math"); +console.log(`Hello Braeden. The area is ${mo.area(r)}`);