From d9a8cdcacbfcc1684078e0ddc1b3ae707ed42835 Mon Sep 17 00:00:00 2001 From: Vouchyk Date: Tue, 23 Dec 2025 20:15:24 +0000 Subject: [PATCH 1/3] Tasks solution --- src/createServer.js | 74 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index 1cf1dda..a39ac4a 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,10 +1,78 @@ +/* eslint-disable no-console */ 'use strict'; +const { Server } = require('http'); +const fs = require('fs'); +const path = require('path'); + +const ALLOWED_ENDPOINTS = { + addExpense: { + route: '/add-expense', + methods: ['POST'], + }, +}; + function createServer() { /* Write your code here */ // Return instance of http.Server class + const server = new Server(); + + server.on('request', (req, res) => { + const baseUrl = `http://${req.headers.host}`; + const url = new URL(req.url, baseUrl); + + if ( + url.pathname !== ALLOWED_ENDPOINTS.addExpense.route || + !ALLOWED_ENDPOINTS.addExpense.methods.includes(req.method) + ) { + res.statusCode = 404; + res.setHeader('Content-Type', 'text/plain'); + + res.end('Invalid url'); + + return; + } + + const bodyChunks = []; + + req.on('data', (chunk) => { + bodyChunks.push(chunk); + }); + + req.on('end', () => { + const json = Buffer.concat(bodyChunks); + const expense = JSON.parse(json); + + if (!expense?.date || !expense?.title || !expense?.amount) { + res.statusCode = 400; + res.end('Bad user input'); + + return; + } + + const fileStream = fs.createWriteStream( + path.normalize(path.join(__dirname, '../db/expense.json')), + ); + + fileStream.on('error', (error) => { + res.statusCode = 500; + res.setHeader('Content-Type', 'text/plain'); + /* eslint-disable-next-line no-console */ + console.error(error); + res.end('Server error'); + }); + + fileStream.on('finish', () => { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(expense, null, 2)); + }); + + fileStream.end(json); + }); + }); + + return server; } -module.exports = { - createServer, -}; +module.exports = { createServer }; From 7ba080cc368c13a55aad2e92dca893709251e9f9 Mon Sep 17 00:00:00 2001 From: Vouchyk Date: Tue, 23 Dec 2025 21:04:31 +0000 Subject: [PATCH 2/3] Fix misstake --- src/createServer.js | 106 ++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 47 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index a39ac4a..4b757fc 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -5,71 +5,83 @@ const { Server } = require('http'); const fs = require('fs'); const path = require('path'); -const ALLOWED_ENDPOINTS = { - addExpense: { - route: '/add-expense', - methods: ['POST'], - }, -}; +const dbPath = path.resolve(__dirname, '../db/expense.json'); function createServer() { - /* Write your code here */ - // Return instance of http.Server class + // створюємо файл, якщо його немає + if (!fs.existsSync(dbPath)) { + fs.writeFileSync(dbPath, JSON.stringify([]), 'utf8'); + } + const server = new Server(); server.on('request', (req, res) => { - const baseUrl = `http://${req.headers.host}`; - const url = new URL(req.url, baseUrl); - - if ( - url.pathname !== ALLOWED_ENDPOINTS.addExpense.route || - !ALLOWED_ENDPOINTS.addExpense.methods.includes(req.method) - ) { - res.statusCode = 404; - res.setHeader('Content-Type', 'text/plain'); - - res.end('Invalid url'); + // GET /add-expense - HTML форма + if (req.url === '/add-expense' && req.method === 'GET') { + res.writeHead(200, { 'Content-Type': 'text/html' }); + + res.end(` + + + Add Expense + +
+ + + + +
+ + + `); return; } - const bodyChunks = []; + // POST /add-expense - додаємо новий запис + if (req.url === '/add-expense' && req.method === 'POST') { + const bodyChunks = []; - req.on('data', (chunk) => { - bodyChunks.push(chunk); - }); + req.on('data', (chunk) => bodyChunks.push(chunk)); - req.on('end', () => { - const json = Buffer.concat(bodyChunks); - const expense = JSON.parse(json); + req.on('end', () => { + const json = Buffer.concat(bodyChunks); + const expense = JSON.parse(json); - if (!expense?.date || !expense?.title || !expense?.amount) { - res.statusCode = 400; - res.end('Bad user input'); + if (!expense?.date || !expense?.title || !expense?.amount) { + res.statusCode = 400; + res.end('Bad user input'); - return; - } + return; + } - const fileStream = fs.createWriteStream( - path.normalize(path.join(__dirname, '../db/expense.json')), - ); + fs.readFile(dbPath, 'utf8', (err, data) => { + if (err) { + res.writeHead(500, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Read error' })); - fileStream.on('error', (error) => { - res.statusCode = 500; - res.setHeader('Content-Type', 'text/plain'); - /* eslint-disable-next-line no-console */ - console.error(error); - res.end('Server error'); - }); + return; + } + + fs.writeFile(dbPath, JSON.stringify(expense, null, 2), (error) => { + if (error) { + res.writeHead(500, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Write error' })); - fileStream.on('finish', () => { - res.statusCode = 200; - res.setHeader('Content-Type', 'application/json'); - res.end(JSON.stringify(expense, null, 2)); + return; + } + + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify(expense)); + }); + }); }); - fileStream.end(json); - }); + return; + } + + res.writeHead(404, { 'Content-Type': 'text/plain' }); + res.end('Not found'); }); return server; From 102c37b59ef87c241dccb7b8894bff578bb77e12 Mon Sep 17 00:00:00 2001 From: Vouchyk Date: Wed, 24 Dec 2025 10:15:16 +0000 Subject: [PATCH 3/3] Fix all mistake and complete all test --- src/createServer.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/createServer.js b/src/createServer.js index 4b757fc..b7a025a 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -46,7 +46,16 @@ function createServer() { req.on('end', () => { const json = Buffer.concat(bodyChunks); - const expense = JSON.parse(json); + let expense; + + try { + expense = JSON.parse(json.toString()); + } catch { + res.writeHead(400, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Invalid JSON' })); + + return; + } if (!expense?.date || !expense?.title || !expense?.amount) { res.statusCode = 400; @@ -72,6 +81,7 @@ function createServer() { } res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify(expense)); }); });