Skip to content

finished#345

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

finished#345
SaXoNG wants to merge 3 commits intomate-academy:masterfrom
SaXoNG:develop

Conversation

@SaXoNG
Copy link
Copy Markdown

@SaXoNG SaXoNG commented Feb 13, 2026

No description provided.

Copy link
Copy Markdown

@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

I am requesting changes because the current server implementation in src/createServer.js does not fully meet several core requirements and has security-relevant flaws.

Critical issues that must be fixed:

  1. Incorrect /file and /file/ handling (around the logic where you normalize the pathname): /file/ is currently not reliably mapped to public/index.html, and the normalization can leave you with '/' instead of index.html. Per the spec, both /file and /file/ must return public/index.html. A practical fix is to explicitly check pathname === '/file' || pathname === '/file/' and, in those cases, serve index.html.
  2. Overly permissive route check (where you use pathname.startsWith('/file')): this allows paths like /fileX, which are not valid according to the requirement that only /file, /file/, and paths starting with /file/ should be served. Update this to something like pathname === '/file' || pathname === '/file/' || pathname.startsWith('/file/') so that only valid routes are processed.
  3. Path traversal and escaping public (in the path.join/fs.readFile section): directly joining a segment that may start with '/' or contain .. allows access outside public, breaking the “Return only files from a folder public” requirement. You should strip any leading / from the requested subpath, then use path.resolve(publicDir, requestedPath) and verify that the resolved path starts with the publicDir path; if it doesn’t, return a 404.
  4. Directory handling and validation before reading: currently you call fs.readFile without checking whether the resolved path is a directory or an invalid location. After resolving the path and confirming it’s inside public, if it resolves to a directory (or to '/' after normalization), you should serve public/index.html; if anything fails validation, respond with 404 as required.
  5. Hint message for non-/file paths: when the pathname does not match the allowed /file patterns, the requirement asks for a clear hint about how to load files. Instead of a generic or ambiguous message, return something explicit like Use /file/<path> to load files, and only use this branch for truly invalid routes (after tightening the prefix check above).

Minor improvements (not blockers): you always respond with text/plain, which is functional but not ideal for HTML/CSS; consider a simple content-type mapping if you want to polish the solution. Overall, your structure and error handling are on the right track; once you tighten the route checks, correctly map /file and /file/, and secure the path resolution against traversal, your implementation will align well with the task requirements.


✨ 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

// Return instance of http.Server class
const server = http.createServer((req, res) => {
const { pathname } = new URL(req.url, `http://${req.headers.host}`);
const normalizedPathWay = pathname.replace('/file', '') || 'index.html';
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 normalization on this line doesn't reliably map '/file/' to 'index.html' and may leave a leading '/' (e.g. '/file/' -> '/'). Also replace('/file', '') will replace any occurrence, not just the leading segment. This breaks the requirement that /file/ and /file return public/index.html. Consider explicitly handling pathname === '/file' and pathname === '/file/' (map them to 'index.html'), or use a regex such as pathname.replace(/^\/file(?=\/|$)/, '') and then treat a resulting '/' or empty string as '/index.html'.

const server = http.createServer((req, res) => {
const { pathname } = new URL(req.url, `http://${req.headers.host}`);
const normalizedPathWay = pathname.replace('/file', '') || 'index.html';
const pathToFile = path.join(__dirname, '..', 'public', normalizedPathWay);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Joining using a segment that may start with '/' or contain .. can produce absolute paths or allow path traversal (access outside public). Remove any leading slash from the normalized segment before joining (e.g. strip leading '/') and then normalize and validate the final path. After resolving, ensure the resolved pathToFile starts with the public directory path to enforce the requirement "Return only files from a folder public".


res.setHeader('content-type', 'text/plain');

if (!pathname.startsWith('/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.

Checking pathname.startsWith('/file') is too permissive: it will accept paths like '/fileX' which should not be considered valid. Per requirements you should allow /file, /file/, and any path that starts with /file/. Use an explicit condition such as pathname === '/file' || pathname === '/file/' || pathname.startsWith('/file/').

Comment on lines +16 to +17
res.statusCode = 400;
res.end('Routes not starting with /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 response message and status here are unclear for the user hint requirement. The task requires returning a message with a hint how to load files when the pathname does not start with /file/. Return a clearer hint (for example: Use /file/<path> to load files, or Use /file/ to load files) and keep the status consistent with your API design. Also ensure this branch is only taken for truly invalid routes (see previous comment about startsWith).

return;
}

fs.readFile(pathToFile, 'utf-8', (err, 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.

Reading the file without validating pathToFile allows serving files outside public (path traversal) and will not correctly handle directory requests (e.g. when normalized value is '/' or points to a directory). Before fs.readFile, validate the resolved path is within the public directory and, if the path resolves to a directory, serve public/index.html. If validation fails, return 404 per requirements.

Copy link
Copy Markdown

@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

I am requesting changes because there is still a critical security/requirements issue with the path containment logic in src/createServer.js. Around the check that uses resolvedPath.startsWith(publicDir) (look near where you decide whether to serve the file or return 404), this approach can incorrectly treat some sibling paths as inside public, which violates the requirement that there must be no access to files outside the public directory ([CHECKLIST ITEM #2], [#3], [#9], [#10]). To fix this robustly, either:

  • Compute const rel = path.relative(publicDir, resolvedPath) and return 404 when rel.startsWith('..') or path.isAbsolute(rel), or
  • Require resolvedPath === publicDir || resolvedPath.startsWith(publicDir + path.sep) before serving the file, otherwise return 404.
    This change is required because without it a crafted request could escape the public folder while still being served by your server, breaking the core constraint of the exercise. Everything else about your routing and 404 handling for missing files looks solid, so once you harden this containment check your solution should fully meet the task requirements. Keep up the good work—this is a subtle, real-world security edge case and fixing it will significantly strengthen your implementation.

✨ 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 +42 to +44
const resolvedPath = path.resolve(publicDir, subPath);

if (!resolvedPath.startsWith(publicDir)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Security issue: the containment check uses resolvedPath.startsWith(publicDir) which can produce false positives (for example if a sibling path begins with the same prefix). This can allow access outside public, violating checklist items #2/#3/#9/#10. Use a robust test instead — for example:

  • Compute const rel = path.relative(publicDir, resolvedPath) and reject when rel.startsWith('..') or path.isAbsolute(rel); or
  • Require resolvedPath === publicDir || resolvedPath.startsWith(publicDir + path.sep).

Make this change so any path resolving outside public returns 404.

Copy link
Copy Markdown

@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

I am approving your solution as an educational override so you can keep progressing while you refine your server implementation.

You’ve done a solid job setting up the basic HTTP server, parsing the URL, and wiring fs.readFile to serve files under public, which shows good understanding of the core flow. The main issues to address next are: (1) when relativeFilePath is empty (requests to /file or /file/), your code currently returns a 'File Not Found' message instead of serving public/index.html — you can fix this by treating an empty path as 'index.html' before reading the file (around the branch where you check for an empty path). (2) You are building file paths with string concatenation like public/${relativeFilePath}; this allows path traversal (e.g. /file/../secret), so you should import path and use path.resolve plus a path.relative containment check to ensure the resolved path stays inside the public directory before calling fs.readFile. (3) The route guard using pathname.startsWith('/file') is too permissive and will accept /fileABC; instead, explicitly allow only '/file', '/file/', or paths starting with '/file/' and return the hint message when the pathname does not match these patterns.

As smaller improvements, your pathname.includes('//') check is okay as a light sanity check, but don’t rely on it for security once you have proper path.resolve containment in place, and make sure missing files consistently return a 404 status instead of a 200. Overall, you’re very close to a robust solution — your structure is good, and tightening these routing and security details will bring your implementation fully in line with the requirements.


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

Footnotes

  1. Rate AI review example

Comment on lines +27 to +31
if (!relativeFilePath) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('File Not Found');

return;
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 relativeFilePath is empty (requests to /file or /file/) the handler returns 'File Not Found'. The spec requires /file and /file/ to return public/index.html. Change this branch to serve public/index.html (or default relativeFilePath to 'index.html' earlier) instead of returning this error.

return;
}

fs.readFile(`public/${relativeFilePath}`, (err, data) => {
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 public/${relativeFilePath} directly allows path traversal (for example /file/../secret). Import and use path to resolve and validate the filesystem path: compute publicDir = path.resolve(__dirname, '..', 'public'), resolvedPath = path.resolve(publicDir, relativeFilePath || 'index.html'), then verify containment using either const rel = path.relative(publicDir, resolvedPath) and return 404 when rel.startsWith('..') || path.isAbsolute(rel), or require resolvedPath === publicDir || resolvedPath.startsWith(publicDir + path.sep). Only then call fs.readFile(resolvedPath, ...). Also add const path = require('path') at the top.

Comment on lines +18 to +22
if (!pathname.startsWith('/file')) {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('Should be /file/*');

return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This check !pathname.startsWith('/file') is too permissive: it treats /fileABC as a valid route. Instead accept exactly /file, /file/ or paths that start with /file/ (e.g. if (!(pathname === '/file' || pathname === '/file/' || pathname.startsWith('/file/')))). The spec requires the handler to detect when pathname does not start with /file/ and return a hint message.

Comment on lines +11 to +15
if (pathname.includes('//')) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('File Not Found');

return;
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 pathname.includes('//') check is not sufficient protection against crafted paths (e.g. .. segments). It's fine to keep as a simple sanity check, but do not rely on it for security — the path.resolve + path.relative containment check is required to guarantee no access outside public.

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