Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 140 additions & 2 deletions src/createServer.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,146 @@
'use strict';

const http = require('http');
const path = require('path');
const zlib = require('zlib');
const fs = require('fs');
const { IncomingForm } = require('formidable');
const { pipeline } = require('stream');

const compressionTypes = {
gzip: {
createStream: zlib.createGzip,
extension: '.gz',
},
deflate: {
createStream: zlib.createDeflate,
extension: '.dfl',
},
br: {
createStream: zlib.createBrotliCompress,
extension: '.br',
},
};

function sendHtml(response) {
const filePath = path.join(__dirname, 'index.html');

const stream = fs.createReadStream(filePath);

stream.pipe(response);
}

function sendCss(response) {
const filePath = path.join(__dirname, 'styles', 'style.css');

response.setHeader('Content-Type', 'text/css');

fs.createReadStream(filePath).pipe(response);
}

function createServer() {
/* Write your code here */
// Return instance of http.Server class
return http.createServer((request, response) => {
const { method, url } = request;

if (method === 'GET' && url === '/') {
sendHtml(response);

return;
}

if (method === 'GET' && url === '/styles/style.css') {
sendCss(response);

return;
}

if (method === 'GET' && url === '/compress') {
response.writeHead(400, {
'Content-Type': 'text/plain; charset=utf-8',
});
response.end('Bad request');

return;
}

if (method === 'POST' && url === '/compress') {
const form = new IncomingForm({
multiples: false,
keepExtensions: true,
});

form.parse(request, (error, fields, files) => {
if (error) {
response.writeHead(400, {
'Content-Type': 'text/plain; charset=utf-8',
});
response.end('Bad request');

return;
}

const compressionType = Array.isArray(fields.compressionType)
? fields.compressionType[0]
: fields.compressionType;

if (!Object.hasOwn(compressionTypes, compressionType)) {
response.writeHead(400, {
'Content-Type': 'text/plain; charset=utf-8',
});
response.end('Compression type is unsupported');

return;
}

const uploaded = files.file;

if (!uploaded) {
response.writeHead(400, {
'Content-Type': 'text/plain; charset=utf-8',
});
response.end('Request has not file');

return;
}

const file = Array.isArray(uploaded) ? uploaded[0] : uploaded;

const tempPath = file.filepath;

const originalName = file.originalFilename || 'file';
const safeName =
path.basename(originalName) +
compressionTypes[compressionType].extension;

const encodedName = encodeURIComponent(safeName);

response.writeHead(200, {
'Content-Type': 'application/octet-stream',
'Content-Disposition': `attachment; filename=${encodedName}`,
});

pipeline(
fs.createReadStream(tempPath),
compressionTypes[compressionType].createStream(),
response,
(err) => {
fs.unlink(tempPath, () => {});

if (err) {
}
},
);
});

return;
}

response.writeHead(404, {
'Content-Type': 'text/plain; charset=utf-8',
});

response.end('Non found');
});
}

module.exports = {
Expand Down
31 changes: 31 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./styles/style.css" />
<title>Document</title>
</head>
<body>
<main>
<h1>Compress file</h1>
<form class="form" action="/compress" method="post" enctype="multipart/form-data">
<label class="label">
<span>Choose a compression type:</span>
<select
class="selector"
id="compressionType"
name="compressionType"
required
>
<option value="gzip">gzip</option>
<option value="deflate">deflate</option>
<option value="br">brotli</option>
</select>
</label>
<label class="label">Choose file <input type="file" name="file" /></label>
<button type="submit">send</button>
</form>
</main>
</body>
</html>
17 changes: 17 additions & 0 deletions src/styles/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.label {
display: flex;
flex-direction: column;
gap: 6px;

& input{
display: block;
width: fit-content;
margin: 0;
padding: 0;
}
}

.form {
display: flex;
gap: 20px;
}
Loading