Skip to content

node_compression-app_TetSh#204

Open
TetiankaSh wants to merge 3 commits intomate-academy:masterfrom
TetiankaSh:develop
Open

node_compression-app_TetSh#204
TetiankaSh wants to merge 3 commits intomate-academy:masterfrom
TetiankaSh:develop

Conversation

@TetiankaSh
Copy link

No description provided.

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Great work setting up the server, implementing the required routes, and handling the error conditions! The overall structure is solid. However, this submission requires changes because it doesn't meet the core requirement of using streams for file processing.

The current implementation buffers the entire file into memory before compressing it. The goal is to process the data in chunks as it arrives. Here are the key areas to revise:

  1. Use Streaming for File Processing: Instead of waiting for the request's 'end' event to process a single large buffer, you should process the incoming request stream directly.
  2. Use zlib Streams: Please replace the synchronous zlib methods (like gzipSync) with their streaming counterparts (e.g., zlib.createGzip()). The correct approach is to pipe the file stream from the request through the appropriate zlib compression stream and then into the response stream.

Also, please update the file extensions to match the requirements: .gz for gzip and .dfl for deflate.

You're very close, and I'm confident you can make these adjustments!


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Important

Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.

Tip

If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.

Caution

Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.

Footnotes

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

Comment on lines 39 to 44
const body = [];

req.on('data', (chunk) => body.push(chunk));

req.on('end', () => {
const buffer = Buffer.concat(body);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation buffers the entire request body into memory before processing it. A core requirement of the task is to use streams, which involves processing data in chunks as it arrives without loading the entire file into memory. You should look into processing the request stream as it comes in rather than waiting for the 'end' event to process a single large buffer.

Comment on lines 80 to 82
gzip: { method: zlib.gzipSync, ext: 'gzip' },
deflate: { method: zlib.deflateSync, ext: 'deflate' },
br: { method: zlib.brotliCompressSync, ext: 'br' },

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The task requires using streams, but synchronous zlib methods are used here. The zlib module provides stream-based APIs (e.g., zlib.createGzip(), zlib.createDeflate()) that should be used instead. The file content stream should be piped through one of these compression streams to the response.

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Great job refactoring to use streams and pipeline! You're very close to a complete solution. However, changes are needed because the server isn't correctly handling the multipart/form-data request from the browser. There are two main issues to address: 1. Incorrect Data Stream for Compression: You are currently piping the entire req object to the compressor. A multipart/form-data request includes headers and boundaries along with the file data. You need to parse this request to isolate only the file's content stream and pipe that into the compression stream. Compressing the raw req results in a corrupted output file. 2. Hardcoded Filename and Missing Form Data: The output filename is hardcoded (e.g., file.gz). A core requirement is to name the output file based on the original (e.g., my-document.txt.gz). The original filename, as well as the compressionType from the form, can be extracted by parsing the multipart request. Once you correctly parse the incoming request to get the file stream and metadata, the rest of your logic should work perfectly. Keep up the great work!


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Important

Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.

Tip

If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.

Caution

Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.

Footnotes

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

Comment on lines 39 to 43
const urlParams = new URL(url, `http://${req.headers.host}`);
const compressionType =
urlParams.searchParams.get('compressionType') ||
req.headers['x-compression-type'] ||
'gzip';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the form is submitted, the compressionType is sent in the request body, not in the URL. This logic won't be able to retrieve the selected value from the form. You'll need to parse the multipart/form-data body to get this value along with the file.


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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the requirements, the output filename should be based on the original uploaded file's name (e.g., original.txt.gz). Currently, it's hardcoded to file.<ext>. The original filename can be extracted from the Content-Disposition header of the file part within the multipart/form-data request.

'Content-Disposition': `attachment; filename="file.${config.ext}"`,
});

pipeline(req, config.create(), res, (err) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent job using pipeline to stream the data! This correctly addresses the main feedback from the last review. However, the req object represents the entire incoming HTTP request stream, including multipart boundaries and other form data. You need to first parse this multipart/form-data stream to isolate only the file's content and then pipe that into the compressor. Piping req directly will compress the entire raw request, which is not the intended behavior.

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Great job parsing the multipart form data to get the filename and compression type! I'm approving this submission as an educational step to help you move forward, but there are a few critical stream-handling issues to address.

Your current approach buffers the entire file in memory and stops processing data chunks too early, which can cause out-of-memory errors and result in corrupted files. The server also hangs on invalid form submissions (like a missing file) instead of sending the required 400 error. Lastly, the output filename is using the full compression type (e.g., gzip) instead of the correct extension (e.g., .gz), which you have available in config.ext.

The key is to process the request stream chunk-by-chunk, find the boundary where the file data begins, and then pipe only the file content as it arrives into your compression stream. You're very close to a robust solution!


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Footnotes

  1. Rate AI review example

let bodyBuffer = Buffer.alloc(0);
let isStreamingStarted = false;

req.on('data', (chunk) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation has a few issues. First, by buffering the entire request with Buffer.concat, it defeats the purpose of using streams for potentially large files, risking out-of-memory errors. Second, the isStreamingStarted check on the next line will cause your server to ignore all subsequent data chunks after the file headers are found, leading to truncated and corrupted files. The file's content needs to be piped from the request stream to the compression stream as it arrives.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The task requires using the correct file extension for the compressed file (e.g., .gz for gzip). This line is using the full compression type name (gzip) instead of the extension. You have the correct extension available in config.ext which you defined on lines 65-67.

}
});
}
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server needs to handle cases where the form submission is invalid (e.g., no file is uploaded) and respond with a 400 status code as required. Currently, if the filePartHeaderMatch and typeMatch are never found, the request will hang until it times out. Consider adding a req.on('end', ...) event listener to check if streaming has started. If not, it means the form was invalid and you should send the 400 error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants