🎓 A1Learner
🔍
0 of 30 lessons completed

Java HTTP Server

An HTTP server is a program that answers requests sent to paths on its network address. The HttpServer class ships with the JDK and runs a small server inside a Java program.

One context answers one path

The handler prints its Served line before it writes the body, and status 200 means the request succeeded. A latch counted down by the handler tells the main code when the one request is done.

import com.sun.net.httpserver.HttpServer;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;

public class Main {
  public static void main(String[] args) throws Exception {
    HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
    try {
      CountDownLatch done = new CountDownLatch(1);
      server.createContext("/hello", exchange -> {
        try {
          System.out.println("Served /hello");
          byte[] body = "Hello from the server".getBytes();
          exchange.sendResponseHeaders(200, body.length);
          OutputStream out = exchange.getResponseBody();
          try {
            out.write(body);
          } finally {
            out.close();
          }
        } finally {
          done.countDown();
        }
      });
      server.start();
      System.out.println("PORT " + server.getAddress().getPort());
      done.await();
    } finally {
      server.stop(0);
    }
  }
}

Two contexts answer two paths

Each context carries its own handler and its own body text. The latch counts two requests, so the program stops after both paths have been served.

import com.sun.net.httpserver.HttpServer;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;

public class Main {
  public static void main(String[] args) throws Exception {
    HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
    try {
      CountDownLatch done = new CountDownLatch(2);
      server.createContext("/hello", exchange -> {
        try {
          System.out.println("Served /hello");
          byte[] body = "Hello from the server".getBytes();
          exchange.sendResponseHeaders(200, body.length);
          OutputStream out = exchange.getResponseBody();
          try {
            out.write(body);
          } finally {
            out.close();
          }
        } finally {
          done.countDown();
        }
      });
      server.createContext("/bye", exchange -> {
        try {
          System.out.println("Served /bye");
          byte[] body = "Goodbye".getBytes();
          exchange.sendResponseHeaders(200, body.length);
          OutputStream out = exchange.getResponseBody();
          try {
            out.write(body);
          } finally {
            out.close();
          }
        } finally {
          done.countDown();
        }
      });
      server.start();
      System.out.println("PORT " + server.getAddress().getPort());
      done.await();
    } finally {
      server.stop(0);
    }
  }
}

Example

import com.sun.net.httpserver.HttpServer;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {
  public static void main(String[] args) throws Exception {
    HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
    try {
      CountDownLatch done = new CountDownLatch(3);
      AtomicInteger hits = new AtomicInteger(0);
      server.createContext("/hello", exchange -> {
        try {
          System.out.println("Served /hello");
          byte[] body = "Hello from the server".getBytes();
          exchange.sendResponseHeaders(200, body.length);
          OutputStream out = exchange.getResponseBody();
          try {
            out.write(body);
          } finally {
            out.close();
          }
        } finally {
          done.countDown();
        }
      });
      server.createContext("/count", exchange -> {
        try {
          System.out.println("Served /count");
          byte[] body = ("Hits: " + hits.incrementAndGet()).getBytes();
          exchange.sendResponseHeaders(200, body.length);
          OutputStream out = exchange.getResponseBody();
          try {
            out.write(body);
          } finally {
            out.close();
          }
        } finally {
          done.countDown();
        }
      });
      server.start();
      System.out.println("PORT " + server.getAddress().getPort());
      done.await();
    } finally {
      server.stop(0);
    }
  }
}

Key points

  • A context pairs one path, like /hello, with one handler.
  • A handler is the code that builds the response for one request.
  • A response carries a status code and a body.
  • Status 200 means the request succeeded.
  • Handlers can read and change state held by the server program, like a hit counter.
  • The stop method closes the server and lets the program end.

In this example, the /hello handler answers with the fixed greeting body. The /count handler adds one to the shared counter on each visit before it writes that count into the body, and the finally block stops the server after the latch counts three requests.

Note

HttpServer needs no extra library, because it is part of the JDK.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does a context do on an HttpServer?