diff --git a/.github/workflows/test.yml-template b/.github/workflows/test.yml-template
new file mode 100644
index 0000000..bb13dfc
--- /dev/null
+++ b/.github/workflows/test.yml-template
@@ -0,0 +1,23 @@
+name: Test
+
+on:
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ node-version: [20.x]
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v1
+ with:
+ node-version: ${{ matrix.node-version }}
+ - run: npm install
+ - run: npm test
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..597008b
--- /dev/null
+++ b/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+ Document
+
+
+
+
+
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index d0b3b95..7fe4887 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,10 +9,13 @@
"version": "1.0.0",
"hasInstallScript": true,
"license": "GPL-3.0",
+ "dependencies": {
+ "busboy": "^1.6.0"
+ },
"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",
@@ -1487,10 +1490,11 @@
}
},
"node_modules/@mate-academy/scripts": {
- "version": "1.8.6",
- "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.8.6.tgz",
- "integrity": "sha512-b4om/whj4G9emyi84ORE3FRZzCRwRIesr8tJHXa8EvJdOaAPDpzcJ8A0sFfMsWH9NUOVmOwkBtOXDu5eZZ00Ig==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-2.1.3.tgz",
+ "integrity": "sha512-a07wHTj/1QUK2Aac5zHad+sGw4rIvcNl5lJmJpAD7OxeSbnCdyI6RXUHwXhjF5MaVo9YHrJ0xVahyERS2IIyBQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@octokit/rest": "^17.11.2",
"@types/get-port": "^4.2.0",
@@ -2739,6 +2743,17 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
"node_modules/call-bind": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
@@ -8040,6 +8055,14 @@
"node": ">=8"
}
},
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/string-length": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
diff --git a/package.json b/package.json
index 1d03d64..9f3cce9 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",
@@ -30,5 +30,8 @@
},
"mateAcademy": {
"projectType": "javascript"
+ },
+ "dependencies": {
+ "busboy": "^1.6.0"
}
}
diff --git a/src/createServer.js b/src/createServer.js
index 1cf1dda..4dd5682 100644
--- a/src/createServer.js
+++ b/src/createServer.js
@@ -1,10 +1,137 @@
'use strict';
+const fs = require('fs');
+const path = require('path');
+const http = require('http');
+const zlib = require('zlib');
+const busboy = require('busboy');
+const { PassThrough } = require('stream');
+
function createServer() {
- /* Write your code here */
- // Return instance of http.Server class
+ const server = new http.Server();
+
+ server.on('request', (req, res) => {
+ if (req.url === '/' && req.method === 'GET') {
+ const filePath = path.resolve(__dirname, 'index.html');
+ const stream = fs.createReadStream(filePath);
+
+ stream.on('error', () => {
+ res.statusCode = 500;
+
+ return res.end('Cannot read index.html');
+ });
+
+ res.writeHead(200, { 'Content-Type': 'text/html' });
+
+ return stream.pipe(res);
+ }
+
+ if (req.url !== '/compress') {
+ res.statusCode = 404;
+
+ return res.end('Not Found');
+ }
+
+ if (req.method !== 'POST') {
+ res.statusCode = 400;
+
+ return res.end('Only POST allowed!');
+ }
+
+ let bb;
+
+ try {
+ bb = busboy({ headers: req.headers });
+ } catch (err) {
+ res.statusCode = 400;
+
+ return res.end('Invalid Content-Type');
+ }
+
+ let filename = '';
+ let compressionType = '';
+ let filesStream = null;
+ let gotFile = false;
+
+ const startCompression = () => {
+ if (!gotFile || !compressionType || !filesStream || res.headersSent) {
+ return;
+ }
+
+ let compressStream;
+ let contentType = 'application/octet-stream';
+
+ if (compressionType === 'gzip') {
+ compressStream = zlib.createGzip();
+ contentType = 'application/gzip';
+ } else if (compressionType === 'deflate') {
+ compressStream = zlib.createDeflate();
+ contentType = 'application/zlib';
+ } else if (compressionType === 'br') {
+ compressStream = zlib.createBrotliCompress();
+ contentType = 'application/brotli';
+ } else {
+ res.statusCode = 400;
+
+ return res.end('Unsupported compression type');
+ }
+
+ res.writeHead(200, {
+ 'Content-Type': contentType,
+ 'Content-Disposition': `attachment; filename=${filename}.${compressionType}`,
+ });
+
+ filesStream.pipe(compressStream).pipe(res);
+ };
+
+ bb.on('field', (name, val) => {
+ if (name === 'compressionType') {
+ compressionType = val;
+ startCompression();
+ }
+ });
+
+ bb.on('file', (fieldname, stream, info) => {
+ if (fieldname === 'file') {
+ gotFile = true;
+ filename = info.filename;
+
+ const pass = new PassThrough();
+
+ stream.pipe(pass);
+ filesStream = pass;
+
+ startCompression();
+
+ stream.on('error', () => {
+ if (!res.writableEnded) {
+ res.statusCode = 500;
+ res.end('File stream error');
+ }
+ });
+ } else {
+ stream.resume();
+ }
+ });
+
+ bb.on('close', () => {
+ if (!res.headersSent) {
+ res.statusCode = 400;
+ res.end('Invalid Form');
+ }
+ });
+
+ bb.on('error', () => {
+ if (!res.writableEnded) {
+ res.statusCode = 400;
+ res.end('Busboy error');
+ }
+ });
+
+ req.pipe(bb);
+ });
+
+ return server;
}
-module.exports = {
- createServer,
-};
+module.exports = { createServer };
diff --git a/src/file.txt b/src/file.txt
new file mode 100644
index 0000000..d2203f9
--- /dev/null
+++ b/src/file.txt
@@ -0,0 +1 @@
+sdfsdfsdsdf
\ No newline at end of file
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 0000000..ff44117
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ Document
+
+
+
+
+
\ No newline at end of file