import java.io.*;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.nio.file.*;

class HttpServer implements Runnable {

    private ServerSocket serverSocket;
    private ExecutorService pool;
    private final int port;

    public static void main(String[] args) throws IOException {
        System.out.println("Starting http server...");

        //handle optional argument port
        int port = 80;
        if(args.length == 1) {
            port = Integer.parseInt(args[0]);
        }

        //start main thread that handles incomming connections
        Thread httpServer = new Thread(new HttpServer(port));
        httpServer.start();
    }

    HttpServer(int port) {
        this.port = port;
    }

    public void run() {

        try {
            serverSocket = new ServerSocket(this.port);
            pool = Executors.newCachedThreadPool();

            while(true) {
                //accept incomming connections and pass the socket to the new
                //thread from the thread pool
                Socket socket = serverSocket.accept();
                pool.execute(new Handler(socket));
            }
        } catch(IOException ex) {
        } finally {
        }
    }
}

class Handler implements Runnable {

    private final Socket client;

    Handler(Socket client) {
        this.client = client;
    }

    public void run() {


        try {
            char[] buffer = new char[1024];
            BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(client.getInputStream())
                    );
            BufferedOutputStream output = new BufferedOutputStream(this.client.getOutputStream());

            //read request from client
            int count = bufferedReader.read(buffer, 0, 1024);
            String requestString = new String(buffer, 0, count);

            //get line base input
            String[] lines = requestString.split("\n");

            //return bad request if there is no line
            if(lines.length < 1) {
                output.write("HTTP/1.1 400 Bad Request".getBytes());
                return;
            }

            //split first line to get path and method
            String[] firstLine = lines[0].split("\\s");

            //only handle get requests and HTTP/1.1 requests
            if(firstLine.length != 3 ||
                    firstLine[0].compareTo("GET") != 0 ||
                    firstLine[2].compareTo("HTTP/1.1") != 0
                    ) {
                        output.write("HTTP/1.1 400 Bad Request".getBytes());
                        return;
                    }

            //place your documents here
            String DOCUMENT_ROOT = "./testpage/";

            Path path = Paths.get(DOCUMENT_ROOT + firstLine[1]);

            System.out.println("Requested path: " + path);

            //if directory is requested change path to default document in this
            //path
            if(Files.exists(path) && Files.isDirectory(path)) {
                path = Paths.get(DOCUMENT_ROOT + firstLine[1] + "/index.html");
            }

            if(!Files.exists(path)) {

                //if file does not exist return 404 Not Found
                output.write("HTTP/1.1 404 Not Found\n".getBytes());
                output.write("\n".getBytes());
                //load animated 404.html page from jar file
                BufferedInputStream bufferedInputStream = new BufferedInputStream(
                        getClass()
                            .getResourceAsStream("/404.html")
                        );
                int n;
                byte[] byteBuffer = new byte[1024];

                while((n = bufferedInputStream.read(byteBuffer)) > -1) {
                    output.write(byteBuffer, 0, n);
                }
                output.flush();
                return;
            }

            //return requested file with Content-Length in the header
            output.write("HTTP/1.1 200 OK\n".getBytes());
            output.write(("Content-Length: " + Files.size(path) + "\n").getBytes());
            output.write("\n".getBytes());

            BufferedInputStream bufferedInputStream = new BufferedInputStream(Files.newInputStream(path));
            int n;
            byte[] byteBuffer = new byte[1024];

            while((n = bufferedInputStream.read(byteBuffer)) > -1) {
                output.write(byteBuffer, 0, n);
            }
            output.flush();


        } catch(IOException ex) {
            //do not handle execptions
        } finally {
            if(!this.client.isClosed()) {
                try {
                    this.client.close();
                } catch(IOException ex) {
                }
            }
        }
    }

}

@@ -2670,32 +2670,480 @@
              %7D%0A%0A
+            String pathString = firstLine%5B1%5D;%0A            Boolean showHeader = false;%0A            //check if we should show the request from the client on the page%0A            if(firstLine%5B1%5D.contains(%22?%22)) %7B%0A                String%5B%5D parts = firstLine%5B1%5D.split(%22%5C%5C?%22);%0A                pathString = parts%5B0%5D;%0A                if(parts.length == 2) %7B%0A                    showHeader = parts%5B1%5D.contains(%22header=show%22);%0A                %7D%0A            %7D%0A%0A
             //pl
@@ -3271,80 +3271,18 @@
 T + 
-firstLine%5B1%5D);%0A%0A            System.out.println(%22Requested path: %22 + path
+pathString
 );%0A%0A
@@ -3380,16 +3380,62 @@
  //path%0A
+%0A            System.out.println(pathString);%0A%0A
         
@@ -3539,28 +3539,26 @@
 _ROOT + 
-firstLine%5B1%5D
+pathString
  + %22/ind
@@ -4349,32 +4349,89 @@
 %0A            %7D%0A%0A
+            int contentLength = (int) Files.size(path);%0A%0A
             //re
@@ -4533,32 +4533,142 @@
 %5Cn%22.getBytes());
+%0A%0A            if(showHeader) %7B%0A                contentLength += requestString.getBytes().length;%0A            %7D
 %0A            out
@@ -4699,32 +4699,29 @@
 th: %22 + 
-Files.size(pa
+contentLeng
 th
-)
  + %22%5Cn%22)
@@ -4770,32 +4770,178 @@
 %22.getBytes());%0A%0A
+            //return request header to client%0A            if(showHeader) %7B%0A                output.write(requestString.getBytes());%0A            %7D%0A%0A
             Buff

return request header if requested