From 367413d569b53432768a0df6f4f08e9fef7bfe65 Mon Sep 17 00:00:00 2001 From: Mykhailo Forkosh Date: Fri, 12 Dec 2025 12:21:32 +0200 Subject: [PATCH 1/3] solution --- src/createServer.js | 138 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 2 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index 1cf1dda..da458e5 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,8 +1,142 @@ 'use strict'; +const http = require('http'); +const fs = require('fs/promises'); +const path = require('path'); + +class CustomServer extends http.Server { + #endpoints = {}; + + get(endpoint, cb) { + if (!this.#endpoints.hasOwnProperty(endpoint)) { + this.#endpoints[endpoint] = {}; + } + + this.#endpoints[endpoint].get = cb; + } + + post(endpoint, cb) { + if (!this.#endpoints.hasOwnProperty(endpoint)) { + this.#endpoints[endpoint] = {}; + } + + this.#endpoints[endpoint].post = cb; + } + + useCb(req, res) { + const normalizeMethod = req.method.toLowerCase(); + const normalizeUrl = new URL(req.url, `http://${req.headers.host}`); + const urlPath = normalizeUrl.pathname || '/'; + + if (!this.#endpoints.hasOwnProperty(urlPath)) { + throw new Error(404); + } else if (!this.#endpoints[urlPath].hasOwnProperty(normalizeMethod)) { + throw new Error(405); + } + + const cb = this.#endpoints[urlPath][normalizeMethod]; + + return cb(req, res); + } + + initServer() { + this.on('request', async (req, res) => { + try { + this.useCb(req, res); + } catch (err) { + const status = Number(err.message) || 520; + + res.statusCode = status; + + switch (status) { + case 404: + res.end('The requested resource could not be found on this server'); + break; + case 405: + res.end( + 'The requested HTTP method is not supported for this endpoint', + ); + break; + + default: + res.statusCode = 520; + res.end('The server returned an unknown error.'); + } + } + }); + } +} + function createServer() { - /* Write your code here */ - // Return instance of http.Server class + const server = new CustomServer(); + + server.initServer(); + + server.get('/', (_r, res) => { + const form = `
+ + + + +
`; + + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(form); + }); + + server.post('/add-expense', async (req, res) => { + const pathToDb = path.resolve(__dirname, '..', 'db', 'expense.json'); + const chunks = []; + + for await (const chunk of req) { + chunks.push(chunk); + } + + const data = Buffer.concat(chunks).toString(); + let dataObject; + + switch (req.headers['content-type']) { + case 'application/json': + dataObject = JSON.parse(data); + break; + case 'application/x-www-form-urlencoded': + const entriesForObj = new URLSearchParams(data); + + dataObject = Object.fromEntries(entriesForObj); + break; + default: + res.writeHead(400, { 'Content-Type': 'text/plain' }); + res.end('Сontent type not supported'); + + return; + } + + const { date, title, amount } = dataObject; + + if (!date || !title || !amount) { + res.writeHead(400, { 'Content-Type': 'text/plain' }); + res.end('Invalid data'); + + return; + } + + const jsonData = JSON.stringify(dataObject); + + try { + await fs.writeFile(pathToDb, jsonData); + } catch (err) { + res.writeHead(500, { 'Content-Type': 'text/plain' }); + res.end('Something went wrong'); + + return; + } + + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(jsonData); + }); + + return server; } module.exports = { From aa5782213278ed3d94e3e40eeb332ab970c40962 Mon Sep 17 00:00:00 2001 From: Mykhailo Forkosh Date: Fri, 12 Dec 2025 16:51:45 +0200 Subject: [PATCH 2/3] fix --- src/createServer.js | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index da458e5..fde5039 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -120,10 +120,33 @@ function createServer() { return; } - const jsonData = JSON.stringify(dataObject); + try { + await fs.access(pathToDb, fs.constants.F_OK); + } catch (_e) { + try { + await fs.mkdir(path.join(pathToDb, '..'), { recursive: true }); + } catch (_err) { + res.writeHead(500, { 'Content-Type': 'text/plain' }); + res.end('Something went wrong'); + + return; + } + } + + let expensesList; try { - await fs.writeFile(pathToDb, jsonData); + expensesList = JSON.parse(await fs.readFile(pathToDb)); + + if (!Array.isArray(expensesList)) { + expensesList = JSON.stringify([dataObject]); + } else { + const copyList = [...expensesList, dataObject]; + + expensesList = JSON.stringify(copyList); + } + + await fs.writeFile(pathToDb, expensesList); } catch (err) { res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('Something went wrong'); @@ -132,8 +155,8 @@ function createServer() { } res.statusCode = 200; - res.setHeader('Content-Type', 'application/json'); - res.end(jsonData); + res.setHeader('Content-Type', 'text/html'); + res.end(`
${expensesList}
`); }); return server; From 39a37a6c154075f207ba39acbbbbfd1459129890 Mon Sep 17 00:00:00 2001 From: Mykhailo Forkosh Date: Fri, 12 Dec 2025 17:41:19 +0200 Subject: [PATCH 3/3] fix1 --- src/createServer.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index fde5039..fbd7a1e 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -121,7 +121,7 @@ function createServer() { } try { - await fs.access(pathToDb, fs.constants.F_OK); + await fs.access(path.join(pathToDb, '..'), fs.constants.F_OK); } catch (_e) { try { await fs.mkdir(path.join(pathToDb, '..'), { recursive: true }); @@ -134,20 +134,27 @@ function createServer() { } let expensesList; + let readedData = await fs.readFile(pathToDb).catch((_e) => { + readedData = `[]`; + }); try { - expensesList = JSON.parse(await fs.readFile(pathToDb)); + expensesList = JSON.parse(readedData); if (!Array.isArray(expensesList)) { - expensesList = JSON.stringify([dataObject]); + expensesList = JSON.stringify([dataObject], null, 2); } else { const copyList = [...expensesList, dataObject]; - expensesList = JSON.stringify(copyList); + expensesList = JSON.stringify(copyList, null, 2); } + } catch (err) { + expensesList = JSON.stringify([dataObject], null, 2); + } + try { await fs.writeFile(pathToDb, expensesList); - } catch (err) { + } catch (_er) { res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('Something went wrong');