In the first part of this blog series, Simple HTTP Server in Java with TCP Network Programming, we discussed the specifications of HTTP requests and responses according to the RFC standards, and we went through setting up your Java development environment. Now, in Part 2, we’ll dive into writing the actual code to implement our simple HTTP server using Java’s powerful networking capabilities.

Sample Http Request and Response

You can read more about request and response specification in previous blog post Simple HTTP Server in Java with TCP Network Programming

Server Implementation: Handling HTTP Requests in Java

Below is the complete code for our simple single-threaded HTTP server implemented in Java. This server listens for incoming connections, handles HTTP requests, and sends responses in a sequential manner. Given its single-threaded nature, it handles one connection at a time, which is suitable for understanding the basic mechanics of HTTP server operations. As you get more comfortable with these concepts, you might consider implementing multithreading to handle multiple client connections simultaneously.

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class SimpleHTTPServer {

    public static void main(String[] args) throws Exception {
        final ServerSocket server = new ServerSocket(8080);
        System.out.println("Listening for connection on port 8080 ....");
        while (true) {
            // spin forever
            Socket socket = server.accept();
            System.out.println("Incoming connection from " + socket.getInetAddress());
            InputStream input = socket.getInputStream();
            OutputStream output = socket.getOutputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));
            PrintWriter writer = new PrintWriter(output, true);

            /*
            As per the HTTP request specification:
                1. The first line is the request line.
                2. From the second line until an empty line is encountered are the headers.
                3. After that, there is an optional body that continues until the end of the stream.
             */
            String requestLine = reader.readLine(); // Read the request line
            List<String> headers = readHeaders(reader); // Read all headers
            //we are not reading body for this tutorial purpose;

            System.out.println("--------Serving Request----------");
            System.out.println();

            System.out.println(requestLine);
            System.out.println(headers);


            String method = requestLine.split(" ")[0];
            String path = requestLine.split(" ")[1];

            // handle the HTTP request
            if (method.equals("GET") && "/hi".equals(path)) {
                   writer.println("HTTP/1.1 200 OK"); // status line
                   writer.println("Content-Type: text/html"); // headers
                   writer.println("x-custom-header: custom-server");
                   writer.println();
                   writer.println("<html><body><h1>Hello World</h1></body></html>");
            } else {
                // send a 404 error
                writer.println("HTTP/1.1 404 Not Found"); // status line
                writer.println("Content-Type: text/html"); // headers
                writer.println("x-custom-header: custom-server");
                writer.println();
                writer.println("<html><body><h1>Only the /hi path is served by this simple HTTP server.</h1></body></html>");
            }
            System.out.println();
            System.out.println("----Request Served-------");
            // close the connection
            socket.close();
        }
    }

    static List<String> readHeaders(BufferedReader reader) throws IOException {
        List<String> headers = new ArrayList<>();
        String line = null;
      //read headers until  an empty line is encountered
        while ((line = reader.readLine()) != null && !line.isEmpty()) {
            headers.add(line);
        }
        return headers;
    }

}


We have read the request line and headers in lines 27 and 28, following the specifications outlined in the inline comments. Subsequently, in lines 38 and 39, we split the request line to extract the method and path. Finally, we send the response in accordance with the specification, as detailed in lines 43 to 47.

Running the Java Server: Console Output

Below, you’ll find the console output demonstrating how our Java server handles incoming HTTP requests when running the code in IntelliJ IDEA. Headers part is cropped.

Response in Browser

Success Response

404 not found response

Conclusion

In this part of the blog series, we have implemented a simple HTTP server that listens on a specified port, accepts client connections, and handles basic GET requests. This server is a foundational step towards building more complex web servers and applications. You can extend this server by adding support for more HTTP methods, handling different content types, or implementing more complex routing and resource management.

Stay tuned for further enhancements and feel free to experiment with adding your own features to this server. The full potential of Java network programming is vast, and this project provides a solid starting point for deeper exploration.

One thought on “Building a Simple HTTP Server in Java with TCP Network Programming”

Leave a Reply

Your email address will not be published. Required fields are marked *