private HtmlRequest readRequest(Socket socket) throws IOException {

    BufferedReader requestBufferedReader =
        new BufferedReader(new InputStreamReader(socket.getInputStream()));
    StringBuilder requestStringBuilder = new StringBuilder();
    try {
      String line = requestBufferedReader.readLine();

      while (!line.isEmpty()) {
        requestStringBuilder.append(line + NEWLINE);
        line = requestBufferedReader.readLine();
      }

    } catch (IOException e) {
      System.out.println("An error occured while reading from the socket: " + e.toString());
    }
    if (requestStringBuilder.toString().isEmpty()) {
      return null;
    }
    HtmlRequest htmlRequest = new HtmlRequest(requestStringBuilder.toString());
    if (htmlRequest.type.equals("POST") || htmlRequest.type.equals("TRACE")) {
      htmlRequest.getParametersFromBody(requestBufferedReader);
    }
    return htmlRequest;
  }
  private boolean checkIfRequestedFileLegal(HtmlRequest htmlRequest) throws IOException {

    String requestedFileStr = htmlRequest.requestedFile;

    // Check if it is default
    if (requestedFileStr.equals("/")) {
      htmlRequest.requestedFile = "/" + defaultPage.toString();
      requestedFileStr = htmlRequest.requestedFile;
    }
    String requestedFileFullPath = rootDirectory.getCanonicalPath() + requestedFileStr;
    File requestedFile = new File(requestedFileFullPath);

    // Checking that the requested file path is under the root directory
    if (!requestedFile.getAbsolutePath().startsWith(rootDirectory.getCanonicalPath())) {
      return false;
    }

    // Checking if it is a directory
    if (requestedFile.isDirectory()) {
      return false;
    }

    // Check if the file exists
    if (!requestedFile.exists()) {
      return false;
    }

    return true;
  }
  private void processRequest() throws Exception {
    while (true) {

      Socket socket = socketRequestsQueue.take();

      DataOutputStream socketOutputStream = new DataOutputStream(socket.getOutputStream());

      HtmlRequest htmlRequest = readRequest(socket);

      // If the request is empty than the socket was closed on the other side
      if (htmlRequest.equals(null)) {

        try {
          socket.close();
        } catch (Exception e) {
          System.out.println("Error on trying to close socket on empty request: " + e.toString());
        }
        continue;
      }

      HtmlResponse responseToClient;

      if (!htmlRequest.isLegalRequest) {
        // The request format is illegal
        responseToClient = respond400(htmlRequest);
      } else if (!legalRequestType(htmlRequest)) {
        // The request method is unimplemented
        responseToClient = respond501(htmlRequest);
      } else if (directRequestToResultPages(htmlRequest)) {
        responseToClient = respond403(htmlRequest);
      } else {
        if (!htmlRequest.type.equals("TRACE") && !htmlRequest.type.equals("POST")) {
          boolean isFileLegal = false;
          try {
            isFileLegal = checkIfRequestedFileLegal(htmlRequest);
          } catch (IOException e) {
            responseToClient = respond500(htmlRequest);
          }
          if (!isFileLegal) {
            responseToClient = respond404(htmlRequest);
          } else {
            responseToClient = respond200(htmlRequest);
          }
        } else {
          responseToClient = respond200(htmlRequest);
        }
      }

      try {
        // Send the status line.
        socketOutputStream.writeBytes(responseToClient.getStatusLine());

        // Send the content type line.
        socketOutputStream.writeBytes(responseToClient.getContentType());

        // Send content length.
        if (!htmlRequest.isChunked) {
          socketOutputStream.writeBytes(responseToClient.getContentLengthLine());
        }

        if (htmlRequest.isChunked) {
          socketOutputStream.writeBytes(responseToClient.getTransferEncoding());
        }
        // Send a blank line to indicate the end of the header lines.
        socketOutputStream.writeBytes(CRLF);

      } catch (Exception e) {
        System.out.println("Writing the header caused an error" + e.toString());
      }

      // Send the content of the HTTP.
      if (!htmlRequest.type.equals("HEAD")) {
        sendEntityBodyToClient(socketOutputStream, responseToClient, htmlRequest.isChunked);
      }

      // Close streams and socket.
      try {
        socketOutputStream.close();
        socket.close();
      } catch (Exception e) {
        System.out.println("closing the socket caused an error");
      }
    }
  }