JEP draft: HTTP over Unix Domain Sockets

OwnerMichael McMahon
TypeFeature
ScopeJDK
StatusDraft
Componentcore-libs / java.net
Discussionnet dash dev at openjdk dot org
EffortS
DurationM
Reviewed byAlan Bateman
Created2026/02/12 15:35
Updated2026/04/01 13:17
Issue8377806

Summary

Add Unix domain (AF_UNIX) socket support to the java.net.http API, HTTP server API and the jwebserver command line tool in the JDK.

Goals

Non-Goals

Motivation

Unix domain sockets are used for inter-process communication (IPC) on the same host. They are similar to TCP/IP sockets in most respects, except that they are addressed by file system path names rather than Internet Protocol (IP) addresses and port numbers. For local HTTP access with both client and server on the same system, Unix domain sockets are both more secure and more efficient than TCP/IP loopback connections.

Unix domain sockets have long been a feature of most Unix platforms, and have been supported in Windows since Windows 10 and Windows Server 2019.

It would greatly benefit applications deployed in containers if the HTTP client and server APIs in a local IPC environment could use Unix domain sockets, due to their greater security and performance in these local environments.

Description

APIs will be enhanced in the java.net.http and jdk.httpserver modules to specify:

These parameters will be entirely independent of request URIs including any domain name specified in a request URI.

The command line arguments for the jwebserver tool will be extended to allow binding to a Unix domain socket address.

HTTP Client changes

In the java.net.http module, java.net.http.HttpOption interface will be extended with the ALT_TRANSPORT_ADDRESS class, which has a type parameter of type java.net.SocketAddress but which initially only supports UnixDomainSocketAddress. Users will be able to pass the target Unix domain socket address using HttpRequest.Builder::setOption:

Using HttpRequest::setOption will allow the Unix domain socket address to be provided entirely independent of request URIs, including any domain name specified in a request URI.

HTTP/3 will not be supported over Unix domain sockets. If the preferred version is set to HTTP/3 using HttpClient.Builder::version and HttpRequest.Builder::version methods, the request will be downgraded to HTTP/2 or HTTP/1.1. Similarly, the HttpOption.H3_DISCOVERY option, if present, will be ignored.

The typical usage for client Unix domain sockets (unlike TCP/IP sockets) is that their local addresses remain unbound. This approach will be adapted in HttpClient too. Binding the client connections to specific local Unix domain socket addresses will not supported.

HTTP Server changes

In the jdk.httpserver module, create and bind methods of com.sun.net.HttpServer and com.sun.net.HttpsServer classes that accept java.net.InetSocketAddress will take java.net.SocketAddress instead. This will effectively enable users to be able to provide both java.net.InetSocketAddress and java.net.UnixDomainSocketAddress while creating or binding HttpServer or HttpsServer instances:

The file path pointed by the Unix domain socket will be created while binding the server, and will be removed on server termination. If the file already exists, the socket bind, and consequently the server start will fail.

The following new methods will be added (or modified) for the HTTP server Unix domain socket support:

Example of a HTTP client and server in two different Docker containers

Setting up a volume to be shared by the two containers

# creates a shareable volume called myvol
docker volume create myvol

# Runs a (shell) image with a JDK installed, in a container, with "myvol" mounted on /mnt. 
    
# Run this command twice to create the client and server containers
docker run --mount 'type=volume,destination=/mnt,src=myvol' -it jdk_28 sh

HTTP server

The following snippet shows a server running in the server container, binding to a Unix domain socket in the shared volume at /mnt/server.sock

public class Server {
    void main() throws IOException {
        var path = Path.of("/mnt/server.sock");
        Files.deleteIfExists(path);
        var addr = UnixDomainSocketAddress.of(path);
        var server = HttpServer.create(addr, 5);
        server.createContext("/",
            (ex) -> {
                var str = "Hello world!";
                ex.sendResponseHeaders(200, str.length());
                ex.getResponseBody().write(str.getBytes(StandardCharsets.ISO_8859_1));
                ex.close();
            });
        server.start();
        System.out.printf("Listening at: %s\n", server.getSocketAddress().toString());
    }
}

HTTP client

The following is an example HTTP client running in the client container, which connects to the server bound to the socket /mnt/server.sock in the shared volume

public class Client {
    void main() throws IOException, InterruptedException {
        try (var client = HttpClient.newHttpClient()) {
            var request = HttpRequest.newBuilder()
                .uri(URI.create("https://foo.com/uri"))
                .setOption(
                        HttpOption.ALT_TRANSPORT_ADDRESS,
                        UnixDomainSocketAddress.of("/mnt/server.sock"))
                .GET()
                .build();
            HttpResponse<String> response = client.send(
                    request, HttpResponse.BodyHandlers.ofString());
            // ...
        }
    }
}

Alternatives

One high level design question was whether to configure the use of Unix domain sockets as something tied to URL structure (such as the use of special schemes, or special reserved host names, or paths) or to use a side configuration mechanism independent of any URL that might be used by applications.

A survey of existing libraries and frameworks quickly showed that none of them achieve this by imposing a particular structure on URLs and the universally accepted way is to use specific APIs for configuring this.

Risks and Assumptions

One possible risk is that subtle behavior differences between TCP and Unix domain sockets impacts the operation of the HTTP protocol. If this occurs, it may need to be accounted for in the apidoc.

There is a discussion of these differences in the following article

Dependencies

This builds on the work of JEP 380: "Unix domain socket channels" which implemented Unix domain sockets in NIO socket channels.