From 96489bf50da338a4e2d1f81473af213d2a2d9e38 Mon Sep 17 00:00:00 2001 From: Maksym Bobryk Date: Sun, 2 Nov 2025 01:26:00 +0200 Subject: [PATCH] Solution --- src/createServer.js | 148 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 2 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index 1cf1dda..03a0da0 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,8 +1,152 @@ +/* eslint-disable no-console */ +/* eslint-disable no-useless-return */ 'use strict'; +const { IncomingForm } = require('formidable'); +const { Server } = require('http'); +const fs = require('fs'); +const zlib = require('zlib'); + +const ALLOWED_ENDPOINTS = { + Compress: { + route: '/compress', + allowedMethods: ['POST'], + }, + Base: { + route: '/', + alloweMethods: ['GET'], + }, +}; + +const ALLOWED_COMPRESSION_ALGS = { + gzip: 'gzip', + deflate: 'deflate', + br: 'br', +}; + +function processResponse(options) { + const { res, statusCode, contentType, message } = options; + + res.statusCode = statusCode; + res.setHeader('Content-Type', contentType); + res.end(message); + + return res; +} + function createServer() { - /* Write your code here */ - // Return instance of http.Server class + const server = new Server(); + + server.on('request', (req, res) => { + const url = new URL(req.url, `http://${req.headers.host}`); + const pathname = url.pathname; + + if ( + pathname === ALLOWED_ENDPOINTS.Base.route && + ALLOWED_ENDPOINTS.Base.alloweMethods.includes(req.method) + ) { + return processResponse({ + res, + statusCode: 200, + contentType: 'text/plain', + message: 'Server is healthy', + }); + } + + if (pathname !== ALLOWED_ENDPOINTS.Compress.route) { + return processResponse({ + res, + statusCode: 404, + contentType: 'text/plain', + message: 'Endpoint does not exist', + }); + } + + if ( + pathname === ALLOWED_ENDPOINTS.Compress.route && + !ALLOWED_ENDPOINTS.Compress.allowedMethods.includes(req.method) + ) { + return processResponse({ + res, + statusCode: 400, + contentType: 'text/plain', + message: `Endpoint does not support ${req.method}`, + }); + } + + const form = new IncomingForm({}); + + form.parse(req, (err, fields, files) => { + if (err || !fields.compressionType || !files.file) { + return processResponse({ + res, + statusCode: 400, + contentType: 'text/plain', + message: 'Invalid form data', + }); + } + + const compressionAlg = fields.compressionType?.[0]; + const file = files.file?.[0]; + + const fileName = file.originalFilename; + const filePath = file.filepath; + const mimeType = file.mimetype; + + const fileStream = fs.createReadStream(filePath); + + let compressionStream; + + switch (compressionAlg) { + case ALLOWED_COMPRESSION_ALGS.gzip: { + compressionStream = zlib.createGzip(); + break; + } + + case ALLOWED_COMPRESSION_ALGS.deflate: { + compressionStream = zlib.createDeflate(); + break; + } + + case ALLOWED_COMPRESSION_ALGS.br: { + compressionStream = zlib.createBrotliCompress(); + break; + } + + default: { + return processResponse({ + res, + statusCode: 400, + contentType: 'text/plain', + message: 'Unsupported compression type', + }); + } + } + + const fileNameCompressed = `${fileName}.${compressionAlg}`; + + res.statusCode = 200; + + res.setHeader('Content-Type', mimeType); + + res.setHeader( + 'Content-Disposition', + `attachment; filename=${fileNameCompressed}`, + ); + + fileStream + .on('error', () => { + console.error('Server error'); + }) + .pipe(compressionStream) + .on('error', () => { + console.error('Compress failed'); + }) + .pipe(res); + }); + }); + + return server; } module.exports = {