import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsServer; import java.io.FileInputStream; import java.net.InetSocketAddress; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpOption; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.security.KeyStore; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; /** * JEP 517 (Java 26): HTTP/3 for the HTTP Client API. The sandbox cannot reach a real HTTP/3 server (no UDP egress), * so this shows the half that is checkable everywhere: a client that PREFERS HTTP/3 talking to a server that does not * speak it (the JDK's own HttpsServer, HTTP/1.1) quietly falls back, and says so in response.version(). * args: keystore path, password * Chapter: docs/11-recap-26.md */ public class Http3Fallback { public static void main(String[] args) throws Exception { KeyStore ks = KeyStore.getInstance("PKCS12"); try (var in = new FileInputStream(args[0])) { ks.load(in, args[1].toCharArray()); } KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, args[1].toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ks); SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); HttpsServer server = HttpsServer.create(new InetSocketAddress("127.0.0.1", 0), 0); server.setHttpsConfigurator(new HttpsConfigurator(ctx)); server.createContext("/", ex -> { byte[] b = "hello".getBytes(); ex.sendResponseHeaders(200, b.length); ex.getResponseBody().write(b); ex.close(); }); server.start(); int port = server.getAddress().getPort(); try (HttpClient client = HttpClient.newBuilder().sslContext(ctx).version(HttpClient.Version.HTTP_3).build()) { HttpRequest req = HttpRequest.newBuilder(URI.create("https://localhost:" + port + "/")).GET().build(); HttpResponse r = client.send(req, HttpResponse.BodyHandlers.ofString()); System.out.println("client asked for : " + client.version()); System.out.println("server answered : " + r.version() + " " + r.statusCode() + " " + r.body()); HttpRequest strict = HttpRequest.newBuilder(URI.create("https://localhost:" + port + "/")).GET() .setOption(HttpOption.H3_DISCOVERY, HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY).build(); try { client.send(strict, HttpResponse.BodyHandlers.ofString()); System.out.println("HTTP_3_URI_ONLY : unexpectedly succeeded"); } catch (Exception e) { System.out.println("HTTP_3_URI_ONLY : " + e.getClass().getName() + ": " + e.getMessage()); } } finally { server.stop(0); } } }