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
118 changes: 116 additions & 2 deletions src/createServer.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,122 @@
'use strict';

const { Server } = require('http');
const fs = require('fs');
const path = require('path');
const formidable = require('formidable');
const zlib = require('zlib');

function createServer() {
/* Write your code here */
// Return instance of http.Server class
const server = new Server((req, res) => {
const method = req.method;
const url = req.url;

if (method === 'GET' && url === '/') {
const filePath = path.join(__dirname, 'public', 'index.html');

fs.readFile(filePath, (err, data) => {
if (err) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Internal Server Error');

return;
}

res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(data);
});
} else if (method === 'GET' && url === '/compress') {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('GET method is not allowed for /compress');
} else if (method === 'POST' && url === '/compress') {
const form = new formidable.IncomingForm({ multiples: false });

form.parse(req, (err, fields, files) => {
if (err) {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('Invalid form data');

return;
}

const compressionType = fields.compressionType;
const uploadedFile = files.file;

if (
!uploadedFile ||
!(uploadedFile.filepath || uploadedFile.path) ||
!compressionType
) {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('Missing file or compression type');

return;
}

const filePath = uploadedFile.filepath || uploadedFile.path;

let compressStream;
let extension;

switch (compressionType) {
case 'gzip':
compressStream = zlib.createGzip();
extension = '.gz';
break;
case 'deflate':
compressStream = zlib.createDeflate();
extension = '.dfl';
break;
case 'br':
compressStream = zlib.createBrotliCompress();
extension = '.br';
break;
default:
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('Unsupported compression type');

return;
}

const originalName = uploadedFile.originalFilename || 'file.txt';
const compressedName = originalName + extension;

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

const readStream = fs.createReadStream(filePath);

readStream.on('error', (error) => {
// eslint-disable-next-line no-console
console.error('ReadStream error:', error);

if (!res.headersSent) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
}
res.end('Server error reading file');
});

compressStream.on('error', (error) => {
// eslint-disable-next-line no-console
console.error('CompressStream error:', error);

if (!res.headersSent) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
}
res.end('Server error during compression');
});

readStream.pipe(compressStream).pipe(res);
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});

return server;
}

module.exports = {
Expand Down
23 changes: 23 additions & 0 deletions src/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Compression App</title>
</head>
<body>
<h1>Upload and Compress a File</h1>
<form action="/compress" method="post" enctype="multipart/form-data">
<label for="file_input">Select file:</label>
<input type="file" id="file_input" name="file" required />

<label for="compression_type">Compression type:</label>
<select id="compression_type" name="compressionType" required>
<option value="gzip">GZIP</option>
<option value="deflate">Deflate</option>
<option value="br">Brotli</option>
</select>

<button type="submit">Compress</button>
</form>
</body>
</html>
Loading