diff --git a/index.html b/index.html
new file mode 100644
index 0000000..57ce827
--- /dev/null
+++ b/index.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Document
+
+
+
+
+
diff --git a/package.json b/package.json
index 1d03d64..8e6392d 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
"devDependencies": {
"@faker-js/faker": "^8.4.1",
"@mate-academy/eslint-config": "latest",
- "@mate-academy/scripts": "^1.8.6",
+ "@mate-academy/scripts": "^2.1.3",
"axios": "^1.7.2",
"eslint": "^8.57.0",
"eslint-plugin-jest": "^28.6.0",
diff --git a/src/createServer.js b/src/createServer.js
index 1cf1dda..8fba7a5 100644
--- a/src/createServer.js
+++ b/src/createServer.js
@@ -1,8 +1,115 @@
+/* eslint-disable no-console */
'use strict';
+const http = require('node:http');
+const fs = require('node:fs');
+const path = require('node:path');
+const mime = require('mime-types');
+const zlib = require('node:zlib');
+const { formidable } = require('formidable');
+
function createServer() {
- /* Write your code here */
- // Return instance of http.Server class
+ return http.createServer((req, res) => {
+ const url = new URL(req.url || '', `http://${req.headers.host}`);
+ const requestPath = url.pathname.slice(1) || 'index.html';
+ const realPath = requestPath;
+
+ const compressionMap = {
+ gzip: {
+ extension: 'gz',
+ createStream: () => zlib.createGzip(),
+ },
+ deflate: {
+ extension: 'dfl',
+ createStream: () => zlib.createDeflate(),
+ },
+ br: {
+ extension: 'br',
+ createStream: () => zlib.createBrotliCompress(),
+ },
+ };
+
+ if (url.pathname === '/compress' && req.method === 'POST') {
+ const form = formidable({ multiples: false });
+
+ form.parse(req, (err, fields, files) => {
+ if (err) {
+ res.statusCode = 400;
+ res.end('Invalid form');
+
+ return;
+ }
+
+ const compressionType = Array.isArray(fields.compressionType)
+ ? fields.compressionType[0]
+ : fields.compressionType;
+
+ const file = Array.isArray(files.file) ? files.file[0] : files.file;
+
+ if (!file || !compressionType) {
+ res.statusCode = 400;
+ res.end('Invalid form');
+
+ return;
+ }
+
+ const compressionConfig = compressionMap[compressionType];
+
+ if (!compressionConfig) {
+ res.statusCode = 400;
+ res.end('Unsupported compression type');
+
+ return;
+ }
+
+ const readStream = fs.createReadStream(file.filepath);
+ const compressStream = compressionConfig.createStream();
+ const outputFileName = `${file.originalFilename}.${compressionConfig.extension}`;
+
+ res.statusCode = 200;
+
+ res.setHeader(
+ 'Content-Disposition',
+ `attachment; filename=${outputFileName}`,
+ );
+
+ readStream.on('error', () => {
+ res.statusCode = 500;
+ res.end('Server error');
+ });
+
+ compressStream.on('error', () => {
+ res.statusCode = 500;
+ res.end('Server error');
+ });
+
+ readStream.pipe(compressStream).pipe(res);
+ });
+
+ return;
+ }
+
+ if (url.pathname === '/compress' && req.method === 'GET') {
+ res.statusCode = 400;
+ res.end('Wrong URL');
+
+ return;
+ }
+
+ if (url.pathname === '/' && req.method === 'GET') {
+ const fileStream = fs.createReadStream(realPath);
+ const mimeType = mime.contentType(path.extname(realPath)) || 'text/plain';
+
+ res.statusCode = 200;
+ res.setHeader('Content-Type', mimeType);
+ fileStream.pipe(res);
+
+ return;
+ }
+
+ res.statusCode = 404;
+ res.end('Not Found');
+ });
}
module.exports = {
diff --git a/tests/createServer.test.js b/tests/createServer.test.js
index b53ef15..27b2977 100644
--- a/tests/createServer.test.js
+++ b/tests/createServer.test.js
@@ -29,12 +29,15 @@ function stringToStream(str) {
const compressionTypes = {
gzip: {
decompress: util.promisify(zlib.gunzip),
+ extension: 'gz',
},
deflate: {
decompress: util.promisify(zlib.inflate),
+ extension: 'dfl',
},
br: {
decompress: util.promisify(zlib.brotliDecompress),
+ extension: 'br',
},
};
@@ -96,7 +99,7 @@ describe('createServer', () => {
});
Object.entries(compressionTypes).forEach(
- ([compressionType, { decompress }]) => {
+ ([compressionType, { decompress, extension }]) => {
describe(`compression type "${compressionType}"`, () => {
it('should respond with 200 status code', () => {
expect.assertions(1);
@@ -124,7 +127,7 @@ describe('createServer', () => {
headers: formData.getHeaders(),
})
.then((res) => {
- const expectedHeader = `attachment; filename=${filename}.${compressionType}`;
+ const expectedHeader = `attachment; filename=${filename}.${extension}`;
expect(res.headers['content-disposition']).toBe(
expectedHeader,