[Go to site: main page, start]

http

A zero-dependency HTTP server for Java, powered by virtual threads

Install

Add to your Latte project:

dependency(id: "org.lattejava:http:1.0.0")

Or install with the CLI:

latte install org.lattejava:http:1.0.0

Quick Start

With Java 25 class-less main methods, getting a server running is just a few lines:

import org.lattejava.http.server.HTTPListenerConfiguration;
import org.lattejava.http.server.HTTPServer;

void main() {
  var server = new HTTPServer().withHandler((req, res) -> {
                                  // Handler code goes here
                                })
                               .withListener(new HTTPListenerConfiguration(4242));
  server.start();
}

Here’s the traditional class-based version:

import org.lattejava.http.server.HTTPHandler;
import org.lattejava.http.server.HTTPListenerConfiguration;
import org.lattejava.http.server.HTTPServer;

public class Example {
  public static void main(String... args) {
    HTTPHandler handler = (req, res) -> {
      // Handler code goes here
    };

    HTTPServer server = new HTTPServer().withHandler(handler)
                                        .withListener(new HTTPListenerConfiguration(4242));
    server.start();
    // Use server
    server.close();
  }
}

Since HTTPServer implements java.io.Closeable, you can also use a try-with-resources block:

import org.lattejava.http.server.HTTPHandler;
import org.lattejava.http.server.HTTPListenerConfiguration;
import org.lattejava.http.server.HTTPServer;

public class Example {
  public static void main(String... args) {
    HTTPHandler handler = (req, res) -> {
      // Handler code goes here
    };

    try (HTTPServer server = new HTTPServer().withHandler(handler)
                                             .withListener(new HTTPListenerConfiguration(4242))) {
      server.start();
      // When this block exits, the server will be shutdown
    }
  }
}

Features

  • Virtual threads - Built on Project Loom for simple, high-performance concurrency with blocking I/O
  • Zero dependencies - Pure Java, nothing else
  • TLS support - HTTPS with TLS 1.0-1.3 from PEM certificate and key files
  • Compression - Automatic gzip/deflate based on Accept-Encoding
  • Keep-Alive - Persistent connections with configurable limits
  • Form data - URL-encoded and multipart form parsing with file uploads
  • Cookies - Full request and response cookie support
  • Chunked encoding - Streaming requests and responses with Transfer-Encoding: chunked

Configuration

You can set various options on the server using the with methods:

import java.time.Duration;

import org.lattejava.http.server.HTTPHandler;
import org.lattejava.http.server.HTTPListenerConfiguration;
import org.lattejava.http.server.HTTPServer;

public class Example {
  public static void main(String... args) {
    HTTPHandler handler = (req, res) -> {
      // Handler code goes here
    };

    HTTPServer server = new HTTPServer().withHandler(handler)
                                        .withShutdownDuration(Duration.ofSeconds(10L))
                                        .withListener(new HTTPListenerConfiguration(4242));
    server.start();
    // Use server
    server.close();
  }
}

TLS

The HTTP server implements TLS 1.0-1.3 using the Java SSLEngine. To enable TLS, create an HTTPListenerConfiguration that includes a certificate and private key:

import java.nio.file.Files;
import java.nio.file.Paths;

import org.lattejava.http.server.HTTPHandler;
import org.lattejava.http.server.HTTPListenerConfiguration;
import org.lattejava.http.server.HTTPServer;

public class Example {
  public static void main(String... args) throws Exception {
    String homeDir = System.getProperty("user.home");
    String certificate = Files.readString(Paths.get(homeDir + "/dev/certificates/example.org.pem"));
    String privateKey = Files.readString(Paths.get(homeDir + "/dev/certificates/example.org.key"));

    HTTPHandler handler = (req, res) -> {
      // Handler code goes here
    };

    HTTPServer server = new HTTPServer().withHandler(handler)
                                        .withListener(new HTTPListenerConfiguration(4242, certificate, privateKey));
    server.start();
    // Use server
    server.close();
  }
}

For development, you can use mkcert to create self-signed certificates:

brew install mkcert
mkcert -install
mkdir -p ~/dev/certificates
mkcert -cert-file ~/dev/certificates/example.org.pem -key-file ~/dev/certificates/example.org.key example.org

Performance

A key goal of this project is screaming performance. Here are benchmark results comparing against other Java HTTP servers. All servers implement the same handler that reads the request body and returns a 200.

Baseline (100 concurrent connections)

ServerRequests/secAvg latency (ms)P99 latency (ms)vs java-http
java-http114,4830.861.68100.0%
JDK HttpServer89,8701.082.4478.5%
Jetty111,5001.1711.8997.3%
Netty117,1190.851.75102.3%
Apache Tomcat102,0300.942.4189.1%

Under stress (1,000 concurrent connections)

ServerRequests/secFailures/secAvg latency (ms)P99 latency (ms)vs java-http
java-http114,12008.6811.88100.0%
JDK HttpServer50,87017655.76.1922.6144.5%
Jetty108,43409.2014.8395.0%
Netty115,10508.6110.09100.8%
Apache Tomcat99,16309.8818.7786.8%

Benchmark performed 2026-02-19 on Darwin, arm64, 10 cores, Apple M4, 24GB RAM (MacBook Air). Java: OpenJDK 21.0.10.