Skip to content
Open
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
47 changes: 41 additions & 6 deletions src/createServer.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,45 @@
'use strict';

function createServer() {
/* Write your code here */
// Return instance of http.Server class
}
const http = require('http');
const path = require('path');
const fsp = require('fs/promises');

module.exports = {
createServer,
const createServer = () => {
return http.createServer(async (req, res) => {
const url = new URL(req.url || '', `http://${req.headers.host}`);
const regexPattern = /^\/file(?:\/|$)/;
const isValidURL = regexPattern.test(url.pathname);

res.setHeader('Content-Type', 'text/plain');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The code sets Content-Type to text/plain for every response. For better behavior set MIME types according to the file extension (e.g. text/html for .html) or at minimum set text/html for index.html responses.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Setting Content-Type to text/plain for all responses prevents correct rendering of HTML/CSS and breaks binary responses. Determine the file extension after resolving realPath and set an appropriate Content-Type (e.g. .htmltext/html; charset=utf-8, .csstext/css; charset=utf-8, otherwise application/octet-stream). Set the header right before sending the file.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Content-Type is always set to text/plain. To correctly serve different file types, this header should be set dynamically based on the file's extension. For example, a .html file should have text/html, and a .css file should have text/css.


if (!isValidURL) {
res.statusCode = 400;
res.end('Invalid URL. Correct request is: "/file/<PATH_TO_THE_FILE>".');

return;
}

const requestedPath =
url.pathname.replace(regexPattern, '') || 'index.html';

const publicDir = path.resolve('public');
const realPath = path.resolve(publicDir, requestedPath);

if (path.relative(publicDir, realPath).slice(0, 2) === '..') {
res.statusCode = 404;
res.end('Not Found');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

After sending the response here, you need to add return;. Without it, the function continues to the try...catch block below and will attempt to send a second response for the same request, causing a server error.

}

try {
const file = await fsp.readFile(realPath, 'utf-8');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reading files with 'utf-8' will corrupt binary files (images, etc.). If you may serve binary files, read without an encoding (Buffer) and set Content-Type appropriately based on extension.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Calling fsp.readFile(realPath, 'utf-8') forces UTF-8 text encoding and breaks binary files. Read files as raw buffers (await fsp.readFile(realPath)) and then res.end(file) (a Buffer). Combined with proper Content-Type, this lets you serve images and other binary assets correctly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Specifying the 'utf-8' encoding here will cause problems with non-text files (like images), as it will corrupt their data. You should read the file as a raw Buffer by removing the encoding argument, which res.end() can handle correctly.


res.statusCode = 200;
res.end(file);
} catch (error) {
res.statusCode = 404;
res.end('Not Found');
Comment on lines +38 to +40
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

When readFile throws, you always return 404. It's correct to return 404 for ENOENT (missing files), but consider distinguishing other errors (e.g. permission errors → 500) for clearer responses and easier debugging. Not strictly required, but helpful.

}
});
};

module.exports = { createServer };