HTTP Server (#DF4) JavaScript

I’m stuck on Content-Encoding header

I’ve tried testing locally and it works.

Here are my logs:

remote: [http-compression-1] Sent bytes: "GET /echo/orange HTTP/1.1\r\nHost: localhost:4221\r\nAccept-Encoding: invalid-encoding\r\n\r\n"
remote: [http-compression-1] Failed to read response:
remote: [http-compression-1] Received: "" (no content received)
remote: [http-compression-1]            ^ error
remote: [http-compression-1] Error: Expected: HTTP-version, Received: ""
remote: [http-compression-1] Test failed
remote: [http-compression-1] Terminating program
remote: [http-compression-1] Program terminated successfully

And here’s a snippet of my code:

const net = require("net");

const fs = require("fs");
const path = require("path");
/* The code snippet you provided is setting up a directory variable `DIRECTORY` based on command-line
arguments. Here's a breakdown of what it does: */
let DIRECTORY = __dirname;
process.argv.forEach((val, index) => {
  if (val === "--directory" && process.argv[index + 1]) {
    DIRECTORY = process.argv[index + 1];
  }
});

const server = net.createServer({ keepAlive: true }, (socket) => {
  console.log("🚀 ~ Your Server Started!");
  socket.on("data", (data) => {
    const request = data.toString().split("\r\n");
    const [response, gzip] = handleRequest(request);
    socket.write(response);
    !!gzip && socket.write(gzip);
  });

  socket.on("close", () => {
    socket.end();
    server.close();
  });
});

const handleRequest = (request) => {
  const [method, urlPath] = request[0].split(" ");
  const pathParts = urlPath.split("/");
  const encoding = request.find((header) => header.startsWith("Accept-Encoding"));
  const validMethods = ["GET", "POST"];

  if (!validMethods.includes(method)) {
    return [createResponse(405, "Method Not Allowed"), null];
  }

  if (urlPath === "/") {
    return [createResponse(200, "OK"), null];
  }

  if (urlPath.startsWith("/files/") && pathParts.length > 2) {
    const fileName = pathParts[2];
    const filePath = path.join(DIRECTORY, fileName);

    if (method === "GET") {
      try {
        const fileContent = fs.readFileSync(filePath, { encoding: "utf8" });
        return [createResponse(200, "OK", "application/octet-stream", fileContent), null];
      } catch (error) {
        return [createResponse(404, "Not Found"), null];
      }
    }

    if (method === "POST") {
      const fileContent = request[request.length - 1];
      try {
        fs.writeFileSync(filePath, fileContent, { encoding: "utf8" });
        return [createResponse(201, "Created", "text/plain", fileContent), null];
      } catch (error) {
        return [createResponse(500, "Internal Server Error"), null];
      }
    }
  }

  if (urlPath === "/user-agent") {
    const userAgent = request.find((header) => header.startsWith("User-Agent")).split(": ")[1];
    return [createResponse(200, "OK", "text/plain", userAgent), null];
  }

  if (encoding && pathParts.length === 3 && method === "GET") {
    const subPath = pathParts[2];
    if (encoding.includes("gzip")) {
      // const gzip = require("zlib").gzipSync(subPath).toString("base64");
      return [
        createResponse(200, "OK", "text/plain", subPath, "gzip"),
        // gzip,
      ];
    } else {
      console.log("🚀 ~ subPath:", subPath);
      return [createResponse(200, "OK", "text/plain", subPath), null];
    }
  }

  if (pathParts.length > 2) {
    const subPath = pathParts[2];
    return [createResponse(200, "OK", "text/plain", subPath), null];
  }

  return [createResponse(404, "Not Found"), null];
};

const createResponse = (
  statusCode,
  statusText = "OK",
  contentType = "text/plain",
  content = "",
  contentEncoding = "",
  contentLength = 0
) => {
  const response = [];
  response.push(`HTTP/1.1 ${statusCode} ${statusText}`);
  contentEncoding && response.push(`Content-Encoding: ${contentEncoding}`);
  response.push(`Content-Type: ${contentType}`);
  if (contentLength) {
    response.push(`Content-Length: ${contentLength}\r\n\r\n`);
  } else {
    response.push(`Content-Length: ${content.length}\r\n`);
    response.push(content);
  }
  return response.join("\r\n");
};

server.listen(4221, "127.0.0.1");

@RomaLetodiani does the first request work, and only the second one fails? If that’s the case, I think this might be the culprit:

When a client socket closes, calling server.close() will end the server too early - it won’t be able to handle other clients.

1 Like

@RomaLetodiani Going to mark this as closed for now, please let us know if you still need help!

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.

Note: I’ve updated the title of this post to include the stage ID (#DF4). You can learn about the stages rename here: Upcoming change: Stages overhaul.