From 9a181f281f842ed5fe1a1c3dffb075f0aa8ecbbc Mon Sep 17 00:00:00 2001 From: Violeta Georgieva <696661+violetagg@users.noreply.github.com> Date: Fri, 4 Apr 2025 13:56:45 +0300 Subject: [PATCH 1/8] Depend on Netty v4.2.1.Final-SNAPSHOT Signed-off-by: Violeta Georgieva <696661+violetagg@users.noreply.github.com> --- ...hots.yml => check_netty_4_1_snapshots.yml} | 4 +- .../workflows/check_netty_4_2_snapshots.yml | 39 +++++++++++++++++++ build.gradle | 4 +- docs/antora.yml | 2 +- docs/modules/ROOT/pages/getting-started.adoc | 2 +- gradle/javadoc.gradle | 6 ++- reactor-netty-core/build.gradle | 2 +- reactor-netty-http/build.gradle | 4 +- 8 files changed, 54 insertions(+), 9 deletions(-) rename .github/workflows/{check_netty_snapshots.yml => check_netty_4_1_snapshots.yml} (93%) create mode 100644 .github/workflows/check_netty_4_2_snapshots.yml diff --git a/.github/workflows/check_netty_snapshots.yml b/.github/workflows/check_netty_4_1_snapshots.yml similarity index 93% rename from .github/workflows/check_netty_snapshots.yml rename to .github/workflows/check_netty_4_1_snapshots.yml index ab3a77f734..56ee2929e3 100644 --- a/.github/workflows/check_netty_snapshots.yml +++ b/.github/workflows/check_netty_4_1_snapshots.yml @@ -1,4 +1,4 @@ -name: Check Netty SNAPSHOTS +name: Check Reactor Netty 1.2.x with Netty 4.1 SNAPSHOTS on: schedule: @@ -23,6 +23,8 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + ref: '1.2.x' - name: Set up JDK 1.8 uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 with: diff --git a/.github/workflows/check_netty_4_2_snapshots.yml b/.github/workflows/check_netty_4_2_snapshots.yml new file mode 100644 index 0000000000..7de5a078c1 --- /dev/null +++ b/.github/workflows/check_netty_4_2_snapshots.yml @@ -0,0 +1,39 @@ +name: Check Reactor Netty 1.3.x with Netty 4.2 SNAPSHOTS + +on: + schedule: + - cron: "0 14 * * *" +permissions: read-all +jobs: + build: + + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-22.04, macos-13, windows-2022] + transport: [native, nio] + exclude: + # excludes native on Windows (there's none) + - os: windows-2022 + transport: native + # macOS - https://github.com/netty/netty/issues/9689 + - os: macos-13 + transport: native + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - name: Set up JDK 1.8 + uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + with: + distribution: 'temurin' + java-version: '8' + - name: Set up JDK 17 + uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + with: + distribution: 'graalvm' + java-version: '17.0.12' + - name: Build with Gradle + run: ./gradlew clean check -x :reactor-netty-core:java17Test --no-daemon -PforceTransport=${{ matrix.transport }} -PforceNettyVersion='4.2.1.Final-SNAPSHOT' + - name: GraalVM smoke tests + run: ./gradlew :reactor-netty-graalvm-smoke-tests:nativeTest --no-daemon -PforceTransport=${{ matrix.transport }} -PforceNettyVersion='4.2.1.Final-SNAPSHOT' diff --git a/build.gradle b/build.gradle index 545fe192d1..d9f8749a41 100644 --- a/build.gradle +++ b/build.gradle @@ -109,7 +109,7 @@ ext { logbackVersion = '1.2.13' // Netty - nettyDefaultVersion = '4.1.121.Final' + nettyDefaultVersion = '4.2.2.Final-SNAPSHOT' if (!project.hasProperty("forceNettyVersion")) { nettyVersion = nettyDefaultVersion } @@ -149,7 +149,7 @@ ext { // javadoc: warning - Error fetching URL: https://www.reactive-streams.org/reactive-streams-1.0.4-javadoc/ "https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/", "https://projectreactor.io/docs/core/release/api/", - "https://netty.io/4.1/api/", + "https://netty.io/4.2/api/", "https://projectreactor.io/docs/netty/release/api/", "https://javadoc.io/doc/io.netty.incubator/netty-incubator-codec-classes-quic/latest/"] as String[] } diff --git a/docs/antora.yml b/docs/antora.yml index 900cd88ee9..603c96d987 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -24,7 +24,7 @@ asciidoc: core-source-link: '{reactor-netty-github-repo}/reactor-netty-core/src/main/java' http-source-link: '{reactor-netty-github-repo}/reactor-netty-http/src/main/java' javadoc: 'https://projectreactor.io/docs/netty/{project-version}/api' - nettyjavadoc: 'https://netty.io/4.1/api' + nettyjavadoc: 'https://netty.io/4.2/api' author: - Stephane Maldini - Violeta Georgieva diff --git a/docs/modules/ROOT/pages/getting-started.adoc b/docs/modules/ROOT/pages/getting-started.adoc index 969fe4d5a0..c874b3acb9 100644 --- a/docs/modules/ROOT/pages/getting-started.adoc +++ b/docs/modules/ROOT/pages/getting-started.adoc @@ -24,7 +24,7 @@ It has transitive dependencies on: * Reactive Streams v1.0.4 * Reactor Core v3.x -* Netty v4.1.x +* Netty v4.2.x [[getting-started-understanding-bom]] == Understanding the BOM and versioning scheme diff --git a/gradle/javadoc.gradle b/gradle/javadoc.gradle index 462eb7c588..6b32a181a4 100644 --- a/gradle/javadoc.gradle +++ b/gradle/javadoc.gradle @@ -18,6 +18,10 @@ if (project.name == 'reactor-netty-examples' || project.name == 'reactor-netty-g } project.tasks.withType(Javadoc) { + javadocTool = javaToolchains.javadocToolFor { + languageVersion = JavaLanguageVersion.of(17) + } + dependsOn jar group = "Reactor Netty Javadoc" @@ -29,13 +33,13 @@ project.tasks.withType(Javadoc) { failOnError = true options { + source = "1.8" addStringOption('Xdoclint:none', '-quiet') addStringOption('charSet', 'UTF-8') memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED author = true header = "${project.name}" overview = "$rootDir/docs/api/overview.html" - stylesheetFile = file("$rootDir/docs/api/stylesheet.css") links(rootProject.ext.javadocLinks) } diff --git a/reactor-netty-core/build.gradle b/reactor-netty-core/build.gradle index 9aa08d7b03..ebb75d1ce9 100644 --- a/reactor-netty-core/build.gradle +++ b/reactor-netty-core/build.gradle @@ -33,7 +33,7 @@ ext { "Export-Package" : "reactor.netty*;version=$osgiVersion;-noimport:=true", "Import-Package": [ "!javax.annotation", - "io.netty.channel.kqueue;resolution:=optional;version=\"[4.1,5)\"", + "io.netty.channel.kqueue;resolution:=optional;version=\"[4.2,5)\"", "io.netty.incubator.channel.uring;resolution:=optional", "io.micrometer.*;resolution:=optional", "*" diff --git a/reactor-netty-http/build.gradle b/reactor-netty-http/build.gradle index 2d42926145..31daf51c8e 100644 --- a/reactor-netty-http/build.gradle +++ b/reactor-netty-http/build.gradle @@ -27,8 +27,8 @@ ext { "Export-Package" : "reactor.netty.http*;version=$osgiVersion;-noimport:=true", "Import-Package": [ "!javax.annotation", - "io.netty.channel.kqueue;resolution:=optional;version=\"[4.1,5)\"", - "io.netty.handler.codec.haproxy;resolution:=optional;version=\"[4.1,5)\"", + "io.netty.channel.kqueue;resolution:=optional;version=\"[4.2,5)\"", + "io.netty.handler.codec.haproxy;resolution:=optional;version=\"[4.2,5)\"", "io.netty.incubator.channel.uring;resolution:=optional", "io.netty.incubator.codec.http3;resolution:=optional", "io.micrometer.*;resolution:=optional", From cb7ccadfe5bd9f644f7f2811d7e91b176b504b3c Mon Sep 17 00:00:00 2001 From: Violeta Georgieva <696661+violetagg@users.noreply.github.com> Date: Fri, 25 Apr 2025 14:33:13 +0300 Subject: [PATCH 2/8] Bump BouncyCastle to version 1.80 Signed-off-by: Violeta Georgieva <696661+violetagg@users.noreply.github.com> --- build.gradle | 2 +- reactor-netty-core/build.gradle | 2 +- reactor-netty-http/build.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index d9f8749a41..695b7ad383 100644 --- a/build.gradle +++ b/build.gradle @@ -138,7 +138,7 @@ ext { reflectionsVersion = '0.10.2' errorproneCoreVersion = '2.10.0' errorproneGuavaVersion = '30.0-jre' - bouncycastleVersion = '1.70' + bouncycastleVersion = '1.80' // Antora antoraPluginVersion = '1.0.0' diff --git a/reactor-netty-core/build.gradle b/reactor-netty-core/build.gradle index ebb75d1ce9..98c225b807 100644 --- a/reactor-netty-core/build.gradle +++ b/reactor-netty-core/build.gradle @@ -147,7 +147,7 @@ dependencies { if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { // Necessary for generating SelfSignedCertificate on Java version >= 15 - testRuntimeOnly "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion" + testRuntimeOnly "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion" } testFixturesApi("ch.qos.logback:logback-classic:$logbackVersion") diff --git a/reactor-netty-http/build.gradle b/reactor-netty-http/build.gradle index 31daf51c8e..171442095d 100644 --- a/reactor-netty-http/build.gradle +++ b/reactor-netty-http/build.gradle @@ -177,7 +177,7 @@ dependencies { if (project.hasProperty("testToolchain")) { if (testToolchain == "17") { // Necessary for generating SelfSignedCertificate on Java version >= 15 - testRuntimeOnly "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion" + testRuntimeOnly "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion" } } From 786527fa4612b47da7d2a06ab1946bd4bd127397 Mon Sep 17 00:00:00 2001 From: Violeta Georgieva <696661+violetagg@users.noreply.github.com> Date: Fri, 25 Apr 2025 14:34:13 +0300 Subject: [PATCH 3/8] Use ChannelOption#RECVBUF_ALLOCATOR instead of deprecated ChannelOption#RCVBUF_ALLOCATOR Signed-off-by: Violeta Georgieva <696661+violetagg@users.noreply.github.com> --- .../src/test/java/reactor/netty/tcp/TcpServerTests.java | 2 +- .../test/java/reactor/netty/http/server/HttpServerTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java index 03f2b0022a..95a11fe43f 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java +++ b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java @@ -484,7 +484,7 @@ private void assertSendFile(Function fn) throws Ex Connection client2 = TcpClient.create() .port(context.port()) - .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(64, 1024, 65536)) + .option(ChannelOption.RECVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(64, 1024, 65536)) .handle((in, out) -> { in.receive() .asString(StandardCharsets.UTF_8) diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java index 13d30fce05..6854e34783 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java @@ -2448,7 +2448,7 @@ void testSniSupportHandshakeTimeout() { Sinks.One error = Sinks.one(); disposableServer = createServer() - .childOption(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(64)) + .childOption(ChannelOption.RECVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(64)) .secure(spec -> spec.sslContext(defaultSslContextBuilder) .handshakeTimeout(Duration.ofMillis(1)) .addSniMapping("*.test.com", domainSpec -> domainSpec.sslContext(defaultSslContextBuilder))) From 0fd84bc44e946cd291a0d2107caf80ffd5fff62b Mon Sep 17 00:00:00 2001 From: Violeta Georgieva <696661+violetagg@users.noreply.github.com> Date: Fri, 25 Apr 2025 14:34:44 +0300 Subject: [PATCH 4/8] Adapt to IoEventLoopGroup Signed-off-by: Violeta Georgieva <696661+violetagg@users.noreply.github.com> --- .../src/main/java/reactor/netty/ReactorNetty.java | 7 ++++++- .../reactor/netty/resources/DefaultLoopEpoll.java | 12 +++++++++--- .../reactor/netty/resources/DefaultLoopKQueue.java | 12 +++++++++--- .../netty/resources/DefaultLoopResources.java | 11 ++++++----- .../netty/resources/DefaultLoopResourcesTest.java | 7 ++++--- .../DefaultPooledConnectionProviderTest.java | 11 ++++++----- .../PooledConnectionProviderCustomMetricsTest.java | 5 +++-- .../test/java/reactor/netty/tcp/TcpClientTests.java | 7 ++++--- .../reactor/netty/transport/ClientTransportTest.java | 7 ++++--- .../test/java/reactor/netty/udp/UdpClientTest.java | 7 ++++--- .../reactor/netty/http/client/HttpClientTest.java | 5 +++-- 11 files changed, 58 insertions(+), 33 deletions(-) diff --git a/reactor-netty-core/src/main/java/reactor/netty/ReactorNetty.java b/reactor-netty-core/src/main/java/reactor/netty/ReactorNetty.java index 2fcaeec7be..34cc64b807 100644 --- a/reactor-netty-core/src/main/java/reactor/netty/ReactorNetty.java +++ b/reactor-netty-core/src/main/java/reactor/netty/ReactorNetty.java @@ -41,7 +41,10 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelPipeline; +import io.netty.channel.EventLoop; +import io.netty.channel.IoEventLoop; import io.netty.channel.nio.NioEventLoop; +import io.netty.channel.nio.NioIoHandle; import io.netty.handler.ssl.SslHandler; import io.netty.handler.stream.ChunkedWriteHandler; import io.netty.handler.timeout.IdleState; @@ -449,15 +452,17 @@ static void addHandlerAfterReactorCodecs(Connection context, String } } + @SuppressWarnings("deprecation") static boolean mustChunkFileTransfer(Connection c, Path file) { // if channel multiplexing a parent channel as an http2 stream if (c.channel().parent() != null && c.channel().parent().pipeline().get(NettyPipeline.H2MultiplexHandler) != null) { return true; } ChannelPipeline p = c.channel().pipeline(); + EventLoop eventLoop = c.channel().eventLoop(); return p.get(SslHandler.class) != null || p.get(NettyPipeline.CompressionHandler) != null || - (!(c.channel().eventLoop() instanceof NioEventLoop) && + (((eventLoop instanceof IoEventLoop && !((IoEventLoop) eventLoop).isCompatible(NioIoHandle.class)) || !(eventLoop instanceof NioEventLoop)) && !"file".equals(file.toUri().getScheme())); } diff --git a/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopEpoll.java b/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopEpoll.java index bac23d7656..e8b742abfe 100644 --- a/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopEpoll.java +++ b/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopEpoll.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2022 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2011-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,15 @@ import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; +import io.netty.channel.IoEventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; import io.netty.channel.epoll.Epoll; import io.netty.channel.epoll.EpollDatagramChannel; import io.netty.channel.epoll.EpollDomainDatagramChannel; import io.netty.channel.epoll.EpollDomainSocketChannel; import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollIoHandle; +import io.netty.channel.epoll.EpollIoHandler; import io.netty.channel.epoll.EpollServerDomainSocketChannel; import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.epoll.EpollSocketChannel; @@ -90,15 +94,17 @@ public String getName() { @Override public EventLoopGroup newEventLoopGroup(int threads, ThreadFactory factory) { - return new EpollEventLoopGroup(threads, factory); + return new MultiThreadIoEventLoopGroup(threads, factory, EpollIoHandler.newFactory()); } @Override + @SuppressWarnings("deprecation") public boolean supportGroup(EventLoopGroup group) { if (group instanceof ColocatedEventLoopGroup) { group = ((ColocatedEventLoopGroup) group).get(); } - return group instanceof EpollEventLoopGroup; + return (group instanceof IoEventLoopGroup && ((IoEventLoopGroup) group).isCompatible(EpollIoHandle.class)) || + group instanceof EpollEventLoopGroup; } static final Logger log = Loggers.getLogger(DefaultLoopEpoll.class); diff --git a/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopKQueue.java b/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopKQueue.java index a445c1a49e..686171a808 100644 --- a/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopKQueue.java +++ b/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopKQueue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2022 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2018-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,15 @@ import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; +import io.netty.channel.IoEventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; import io.netty.channel.kqueue.KQueue; import io.netty.channel.kqueue.KQueueDatagramChannel; import io.netty.channel.kqueue.KQueueDomainDatagramChannel; import io.netty.channel.kqueue.KQueueDomainSocketChannel; import io.netty.channel.kqueue.KQueueEventLoopGroup; +import io.netty.channel.kqueue.KQueueIoHandle; +import io.netty.channel.kqueue.KQueueIoHandler; import io.netty.channel.kqueue.KQueueServerDomainSocketChannel; import io.netty.channel.kqueue.KQueueServerSocketChannel; import io.netty.channel.kqueue.KQueueSocketChannel; @@ -89,15 +93,17 @@ public String getName() { @Override public EventLoopGroup newEventLoopGroup(int threads, ThreadFactory factory) { - return new KQueueEventLoopGroup(threads, factory); + return new MultiThreadIoEventLoopGroup(threads, factory, KQueueIoHandler.newFactory()); } @Override + @SuppressWarnings("deprecation") public boolean supportGroup(EventLoopGroup group) { if (group instanceof ColocatedEventLoopGroup) { group = ((ColocatedEventLoopGroup) group).get(); } - return group instanceof KQueueEventLoopGroup; + return (group instanceof IoEventLoopGroup && ((IoEventLoopGroup) group).isCompatible(KQueueIoHandle.class)) || + group instanceof KQueueEventLoopGroup; } static final Logger log = Loggers.getLogger(DefaultLoopKQueue.class); diff --git a/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopResources.java b/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopResources.java index f320cb0893..58fe16fd10 100644 --- a/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopResources.java +++ b/reactor-netty-core/src/main/java/reactor/netty/resources/DefaultLoopResources.java @@ -23,7 +23,8 @@ import java.util.concurrent.atomic.AtomicReference; import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; +import io.netty.channel.nio.NioIoHandler; import io.netty.util.concurrent.FastThreadLocalThread; import io.netty.util.concurrent.Future; import org.jspecify.annotations.Nullable; @@ -196,8 +197,8 @@ EventLoopGroup cacheNioSelectLoops() { EventLoopGroup eventLoopGroup = serverSelectLoops.get(); if (null == eventLoopGroup) { - EventLoopGroup newEventLoopGroup = new NioEventLoopGroup(selectCount, - threadFactory(this, "select-nio")); + EventLoopGroup newEventLoopGroup = new MultiThreadIoEventLoopGroup(selectCount, + threadFactory(this, "select-nio"), NioIoHandler.newFactory()); if (!serverSelectLoops.compareAndSet(null, newEventLoopGroup)) { //"FutureReturnValueIgnored" this is deliberate newEventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS); @@ -211,8 +212,8 @@ EventLoopGroup cacheNioSelectLoops() { EventLoopGroup cacheNioServerLoops() { EventLoopGroup eventLoopGroup = serverLoops.get(); if (null == eventLoopGroup) { - EventLoopGroup newEventLoopGroup = new NioEventLoopGroup(workerCount, - threadFactory(this, "nio")); + EventLoopGroup newEventLoopGroup = new MultiThreadIoEventLoopGroup(workerCount, + threadFactory(this, "nio"), NioIoHandler.newFactory()); if (!serverLoops.compareAndSet(null, newEventLoopGroup)) { //"FutureReturnValueIgnored" this is deliberate newEventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS); diff --git a/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultLoopResourcesTest.java b/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultLoopResourcesTest.java index 53f3cb7d15..4f5c008b71 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultLoopResourcesTest.java +++ b/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultLoopResourcesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2022 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2017-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +20,10 @@ import java.util.concurrent.atomic.AtomicReference; import io.netty.channel.EventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; import io.netty.channel.epoll.Epoll; import io.netty.channel.kqueue.KQueue; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.nio.NioIoHandler; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.condition.OS; @@ -123,7 +124,7 @@ void testClientTransportWarmupNio() throws Exception { private void testClientTransportWarmup(boolean preferNative) throws Exception { final DefaultLoopResources loop1 = (DefaultLoopResources) LoopResources.create("testClientTransportWarmup", 1, true); - final EventLoopGroup loop2 = new NioEventLoopGroup(1); + final EventLoopGroup loop2 = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()); try { TcpClient tcpClient = TcpClient.create() .resolver(spec -> spec.runOn(loop2)) diff --git a/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultPooledConnectionProviderTest.java b/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultPooledConnectionProviderTest.java index d54ab09582..a90740dabf 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultPooledConnectionProviderTest.java +++ b/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultPooledConnectionProviderTest.java @@ -41,7 +41,8 @@ import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; +import io.netty.channel.nio.NioIoHandler; import io.netty.handler.logging.LoggingHandler; import io.netty.resolver.AddressResolver; import io.netty.resolver.AddressResolverGroup; @@ -145,7 +146,7 @@ void fixedPoolTwoAcquire() throws Exception { final ScheduledExecutorService service = Executors.newScheduledThreadPool(2); int echoServerPort = SocketUtils.findAvailableTcpPort(); TcpClientTests.EchoServer echoServer = new TcpClientTests.EchoServer(echoServerPort); - EventLoopGroup group = new NioEventLoopGroup(2); + EventLoopGroup group = new MultiThreadIoEventLoopGroup(2, NioIoHandler.newFactory()); java.util.concurrent.Future f1 = null; java.util.concurrent.Future f2 = null; @@ -393,7 +394,7 @@ else if (signal.getThrowable() instanceof PoolAcquirePendingLimitException && @Test @SuppressWarnings("unchecked") void testRetryConnect() throws Exception { - EventLoopGroup group = new NioEventLoopGroup(1); + EventLoopGroup group = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()); InetSocketAddress address = AddressUtils.createUnresolved("localhost", 12122); AddressResolverGroup resolverGroup = Mockito.mock(AddressResolverGroup.class); @@ -438,7 +439,7 @@ void testRetryConnect() throws Exception { @Test void testDisposeInactivePoolsInBackground() throws Exception { - EventLoopGroup group = new NioEventLoopGroup(1); + EventLoopGroup group = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()); InetSocketAddress address = AddressUtils.createUnresolved("example.com", 80); ConnectionProvider.Builder builder = ConnectionProvider.builder("testDisposeInactivePoolsInBackground") @@ -554,7 +555,7 @@ void testIssue3316() throws ExecutionException, InterruptedException { DefaultPooledConnectionProvider provider = (DefaultPooledConnectionProvider) ConnectionProvider.create("testIssue3316", 400); - EventLoopGroup group = new NioEventLoopGroup(); + EventLoopGroup group = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory()); try { Flux.range(0, 400) .flatMap(i -> diff --git a/reactor-netty-core/src/test/java/reactor/netty/resources/PooledConnectionProviderCustomMetricsTest.java b/reactor-netty-core/src/test/java/reactor/netty/resources/PooledConnectionProviderCustomMetricsTest.java index 55ba7b1510..e1a3eea0f6 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/resources/PooledConnectionProviderCustomMetricsTest.java +++ b/reactor-netty-core/src/test/java/reactor/netty/resources/PooledConnectionProviderCustomMetricsTest.java @@ -27,7 +27,8 @@ import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; +import io.netty.channel.nio.NioIoHandler; import io.netty.handler.logging.LoggingHandler; import io.netty.resolver.AddressResolverGroup; import io.netty.resolver.DefaultAddressResolverGroup; @@ -59,7 +60,7 @@ class PooledConnectionProviderCustomMetricsTest { @BeforeEach void setUp() { remoteAddress = () -> InetSocketAddress.createUnresolved("localhost", 0); - group = new NioEventLoopGroup(2); + group = new MultiThreadIoEventLoopGroup(2, NioIoHandler.newFactory()); } @AfterEach diff --git a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpClientTests.java b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpClientTests.java index 66e16c6407..53fd2266cf 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpClientTests.java +++ b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpClientTests.java @@ -50,7 +50,8 @@ import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; +import io.netty.channel.nio.NioIoHandler; import io.netty.channel.unix.DomainSocketAddress; import io.netty.handler.codec.LineBasedFrameDecoder; import io.netty.resolver.AddressResolverGroup; @@ -1216,7 +1217,7 @@ void testBootstrap() { TcpClient.create() .bootstrap(b -> b.attr(AttributeKey.valueOf("testBootstrap"), "testBootstrap") - .group(new NioEventLoopGroup()) + .group(new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory())) .option(ChannelOption.valueOf("testBootstrap"), "testBootstrap") .remoteAddress(server.address()) .resolver(DefaultAddressResolverGroup.INSTANCE) @@ -1284,7 +1285,7 @@ void testAddressSupplier() { @Test void testDefaultResolverWithCustomEventLoop() throws Exception { LoopResources loop1 = LoopResources.create("test", 1, true); - EventLoopGroup loop2 = new NioEventLoopGroup(1); + EventLoopGroup loop2 = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()); TcpClient client = TcpClient.create(); TcpClient newClient = null; try { diff --git a/reactor-netty-core/src/test/java/reactor/netty/transport/ClientTransportTest.java b/reactor-netty-core/src/test/java/reactor/netty/transport/ClientTransportTest.java index f392be99d3..eb66c954a6 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/transport/ClientTransportTest.java +++ b/reactor-netty-core/src/test/java/reactor/netty/transport/ClientTransportTest.java @@ -17,8 +17,9 @@ import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.nio.NioIoHandler; import io.netty.handler.logging.LoggingHandler; import io.netty.resolver.AddressResolverGroup; import io.netty.resolver.HostsFileEntriesProvider; @@ -90,7 +91,7 @@ void testDisposeTimeoutLongOverflow() { @Test void testDefaultResolverWithCustomEventLoop() throws Exception { final LoopResources loop1 = LoopResources.create("test", 1, true); - final EventLoopGroup loop2 = new NioEventLoopGroup(1); + final EventLoopGroup loop2 = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()); final ConnectionProvider provider = ConnectionProvider.create("test"); final TestClientTransportConfig config = new TestClientTransportConfig(provider, Collections.emptyMap(), () -> null); @@ -276,7 +277,7 @@ void testCustomHostsFileEntriesResolver() throws Exception { @SuppressWarnings("unchecked") private void doTestHostsFileEntriesResolver(boolean customResolver) throws Exception { LoopResources loop1 = LoopResources.create("test", 1, true); - EventLoopGroup loop2 = new NioEventLoopGroup(1); + EventLoopGroup loop2 = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()); ConnectionProvider provider = ConnectionProvider.create("test"); TestClientTransportConfig config = new TestClientTransportConfig(provider, Collections.emptyMap(), () -> null); diff --git a/reactor-netty-core/src/test/java/reactor/netty/udp/UdpClientTest.java b/reactor-netty-core/src/test/java/reactor/netty/udp/UdpClientTest.java index 04ce121217..578aff8db5 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/udp/UdpClientTest.java +++ b/reactor-netty-core/src/test/java/reactor/netty/udp/UdpClientTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2023 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2017-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,8 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; +import io.netty.channel.nio.NioIoHandler; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.unix.DomainDatagramPacket; import io.netty.channel.unix.DomainSocketAddress; @@ -119,7 +120,7 @@ void smokeTest() throws Exception { @Test void testIssue192() throws Exception { LoopResources resources = LoopResources.create("testIssue192"); - EventLoopGroup loop = new NioEventLoopGroup(1); + EventLoopGroup loop = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()); UdpServer server = UdpServer.create() .runOn(resources); UdpClient client = UdpClient.create() diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpClientTest.java b/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpClientTest.java index 5115b37c83..da37e42a3c 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpClientTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpClientTest.java @@ -68,9 +68,10 @@ import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelId; import io.netty.channel.EventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.nio.NioIoHandler; import io.netty.channel.unix.DomainSocketAddress; import io.netty.handler.codec.compression.Brotli; import io.netty.handler.codec.http.DefaultFullHttpResponse; @@ -3247,7 +3248,7 @@ void testIssue1547() throws Exception { .handle((req, res) -> res.sendString(Mono.just("testIssue1547"))) .bindNow(); - EventLoopGroup loop = new NioEventLoopGroup(1); + EventLoopGroup loop = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()); AtomicReference>> resolvers = new AtomicReference<>(new ArrayList<>()); AtomicReference>> resolversInternal = new AtomicReference<>(new ArrayList<>()); try { From 4bd5bb9ff1bcec8ab3fe3b8231f1b749a8dd3699 Mon Sep 17 00:00:00 2001 From: Violeta Georgieva <696661+violetagg@users.noreply.github.com> Date: Fri, 25 Apr 2025 14:36:38 +0300 Subject: [PATCH 5/8] Adapt to SocketProtocolFamily Signed-off-by: Violeta Georgieva <696661+violetagg@users.noreply.github.com> --- .../java/reactor/netty/udp/UdpClient.java | 23 +++++++++++++++++++ .../reactor/netty/udp/UdpClientConfig.java | 18 ++++++++++++++- .../java/reactor/netty/udp/UdpServer.java | 23 +++++++++++++++++++ .../reactor/netty/udp/UdpServerConfig.java | 18 ++++++++++++++- .../reactor/netty/udp/UdpServerTests.java | 6 ++--- 5 files changed, 83 insertions(+), 5 deletions(-) diff --git a/reactor-netty-core/src/main/java/reactor/netty/udp/UdpClient.java b/reactor-netty-core/src/main/java/reactor/netty/udp/UdpClient.java index 8000560fae..a5a2f6c996 100644 --- a/reactor-netty-core/src/main/java/reactor/netty/udp/UdpClient.java +++ b/reactor-netty-core/src/main/java/reactor/netty/udp/UdpClient.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.InternetProtocolFamily; +import io.netty.channel.socket.SocketProtocolFamily; import io.netty.handler.logging.LogLevel; import io.netty.util.AttributeKey; import org.jspecify.annotations.Nullable; @@ -190,6 +191,7 @@ public final UdpClient runOn(LoopResources loopResources, boolean preferNative) Objects.requireNonNull(loopResources, "loopResources"); UdpClient dup = super.runOn(loopResources, preferNative); dup.configuration().family = null; + dup.configuration().socketFamily = null; return dup; } @@ -199,12 +201,33 @@ public final UdpClient runOn(LoopResources loopResources, boolean preferNative) * @param loopResources a new loop resources * @param family a specific {@link InternetProtocolFamily} to run with * @return a new {@link UdpClient} reference + * @deprecated as of 1.3.0. Prefer {@link #runOn(LoopResources, SocketProtocolFamily)}. + * This method will be removed in version 1.4.0. */ + @Deprecated public final UdpClient runOn(LoopResources loopResources, InternetProtocolFamily family) { Objects.requireNonNull(loopResources, "loopResources"); Objects.requireNonNull(family, "family"); UdpClient dup = super.runOn(loopResources, false); dup.configuration().family = family; + dup.configuration().socketFamily = family.toSocketProtocolFamily(); + return dup; + } + + /** + * Run IO loops on a supplied {@link EventLoopGroup} from the {@link LoopResources} container. + * + * @param loopResources a new loop resources + * @param family a specific {@link SocketProtocolFamily} to run with + * @return a new {@link UdpClient} reference + * @since 1.3.0 + */ + public final UdpClient runOn(LoopResources loopResources, SocketProtocolFamily family) { + Objects.requireNonNull(loopResources, "loopResources"); + Objects.requireNonNull(family, "family"); + UdpClient dup = super.runOn(loopResources, false); + dup.configuration().family = null; + dup.configuration().socketFamily = family; return dup; } diff --git a/reactor-netty-core/src/main/java/reactor/netty/udp/UdpClientConfig.java b/reactor-netty-core/src/main/java/reactor/netty/udp/UdpClientConfig.java index b824d791f1..add72fbd50 100644 --- a/reactor-netty-core/src/main/java/reactor/netty/udp/UdpClientConfig.java +++ b/reactor-netty-core/src/main/java/reactor/netty/udp/UdpClientConfig.java @@ -21,6 +21,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.InternetProtocolFamily; +import io.netty.channel.socket.SocketProtocolFamily; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.unix.DomainDatagramChannel; import io.netty.handler.logging.LogLevel; @@ -57,15 +58,29 @@ public final ChannelOperations.OnSetup channelOperationsProvider() { * Return the configured {@link InternetProtocolFamily} to run with or null. * * @return the configured {@link InternetProtocolFamily} to run with or null + * @deprecated as of 1.3.0. Prefer {@link #socketFamily()}. This method will be removed in version 1.4.0. */ + @Deprecated public final @Nullable InternetProtocolFamily family() { return family; } + /** + * Return the configured {@link SocketProtocolFamily} to run with or null. + * + * @return the configured {@link SocketProtocolFamily} to run with or null + * @since 1.3.0 + */ + public final @Nullable SocketProtocolFamily socketFamily() { + return socketFamily; + } + // Protected/Package private write API + @SuppressWarnings("deprecation") @Nullable InternetProtocolFamily family; + @Nullable SocketProtocolFamily socketFamily; UdpClientConfig(ConnectionProvider connectionProvider, Map, ?> options, Supplier remoteAddress) { @@ -75,6 +90,7 @@ public final ChannelOperations.OnSetup channelOperationsProvider() { UdpClientConfig(UdpClientConfig parent) { super(parent); this.family = parent.family; + this.socketFamily = parent.socketFamily; } @Override @@ -88,7 +104,7 @@ protected ChannelFactory connectionFactory(EventLoopGroup elg return super.connectionFactory(elg, isDomainSocket); } else { - return () -> new NioDatagramChannel(family()); + return () -> new NioDatagramChannel(socketFamily()); } } diff --git a/reactor-netty-core/src/main/java/reactor/netty/udp/UdpServer.java b/reactor-netty-core/src/main/java/reactor/netty/udp/UdpServer.java index 166d667c05..82e18643b3 100644 --- a/reactor-netty-core/src/main/java/reactor/netty/udp/UdpServer.java +++ b/reactor-netty-core/src/main/java/reactor/netty/udp/UdpServer.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.InternetProtocolFamily; +import io.netty.channel.socket.SocketProtocolFamily; import io.netty.handler.logging.LogLevel; import io.netty.util.AttributeKey; import org.jspecify.annotations.Nullable; @@ -250,6 +251,7 @@ public final UdpServer runOn(LoopResources loopResources, boolean preferNative) Objects.requireNonNull(loopResources, "loopResources"); UdpServer dup = super.runOn(loopResources, preferNative); dup.configuration().family = null; + dup.configuration().socketFamily = null; return dup; } @@ -259,12 +261,33 @@ public final UdpServer runOn(LoopResources loopResources, boolean preferNative) * @param loopResources a new loop resources * @param family a specific {@link InternetProtocolFamily} to run with * @return a new {@link UdpServer} reference + * @deprecated as of 1.3.0. Prefer {@link #runOn(LoopResources, SocketProtocolFamily)}. + * This method will be removed in version 1.4.0. */ + @Deprecated public final UdpServer runOn(LoopResources loopResources, InternetProtocolFamily family) { Objects.requireNonNull(loopResources, "loopResources"); Objects.requireNonNull(family, "family"); UdpServer dup = super.runOn(loopResources, false); dup.configuration().family = family; + dup.configuration().socketFamily = family.toSocketProtocolFamily(); + return dup; + } + + /** + * Run IO loops on a supplied {@link EventLoopGroup} from the {@link LoopResources} container. + * + * @param loopResources a new loop resources + * @param family a specific {@link SocketProtocolFamily} to run with + * @return a new {@link UdpServer} reference + * @since 1.3.0 + */ + public final UdpServer runOn(LoopResources loopResources, SocketProtocolFamily family) { + Objects.requireNonNull(loopResources, "loopResources"); + Objects.requireNonNull(family, "family"); + UdpServer dup = super.runOn(loopResources, false); + dup.configuration().family = null; + dup.configuration().socketFamily = family; return dup; } diff --git a/reactor-netty-core/src/main/java/reactor/netty/udp/UdpServerConfig.java b/reactor-netty-core/src/main/java/reactor/netty/udp/UdpServerConfig.java index ce2065389e..f1dd66f6d3 100644 --- a/reactor-netty-core/src/main/java/reactor/netty/udp/UdpServerConfig.java +++ b/reactor-netty-core/src/main/java/reactor/netty/udp/UdpServerConfig.java @@ -22,6 +22,7 @@ import io.netty.channel.group.ChannelGroup; import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.InternetProtocolFamily; +import io.netty.channel.socket.SocketProtocolFamily; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.unix.DomainDatagramChannel; import io.netty.handler.logging.LogLevel; @@ -87,18 +88,32 @@ public ChannelOperations.OnSetup channelOperationsProvider() { * Return the configured {@link InternetProtocolFamily} to run with or null. * * @return the configured {@link InternetProtocolFamily} to run with or null + * @deprecated as of 1.3.0. Prefer {@link #socketFamily()}. This method will be removed in version 1.4.0. */ + @Deprecated public final @Nullable InternetProtocolFamily family() { return family; } + /** + * Return the configured {@link SocketProtocolFamily} to run with or null. + * + * @return the configured {@link SocketProtocolFamily} to run with or null + * @since 1.3.0 + */ + public final @Nullable SocketProtocolFamily socketFamily() { + return socketFamily; + } + // Protected/Package private write API @Nullable Consumer doOnBind; @Nullable Consumer doOnBound; @Nullable Consumer doOnUnbound; + @SuppressWarnings("deprecation") @Nullable InternetProtocolFamily family; + @Nullable SocketProtocolFamily socketFamily; UdpServerConfig(Map, ?> options, Supplier bindAddress) { super(options, bindAddress); @@ -110,6 +125,7 @@ public ChannelOperations.OnSetup channelOperationsProvider() { this.doOnBound = parent.doOnBound; this.doOnUnbound = parent.doOnUnbound; this.family = parent.family; + this.socketFamily = parent.socketFamily; } @Override @@ -123,7 +139,7 @@ protected ChannelFactory connectionFactory(EventLoopGroup elg return super.connectionFactory(elg, isDomainSocket); } else { - return () -> new NioDatagramChannel(family()); + return () -> new NioDatagramChannel(socketFamily()); } } diff --git a/reactor-netty-core/src/test/java/reactor/netty/udp/UdpServerTests.java b/reactor-netty-core/src/test/java/reactor/netty/udp/UdpServerTests.java index dd869cfeda..67c3cc3587 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/udp/UdpServerTests.java +++ b/reactor-netty-core/src/test/java/reactor/netty/udp/UdpServerTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2023 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2011-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ import java.util.concurrent.atomic.AtomicReference; import io.netty.channel.ChannelOption; -import io.netty.channel.socket.InternetProtocolFamily; +import io.netty.channel.socket.SocketProtocolFamily; import io.netty.channel.unix.DomainSocketAddress; import io.netty.util.NetUtil; import org.junit.jupiter.api.AfterEach; @@ -153,7 +153,7 @@ void supportsUdpMulticast() throws Exception { UdpServer.create() .option(ChannelOption.SO_REUSEADDR, true) .bindAddress(() -> new InetSocketAddress(port)) - .runOn(resources, InternetProtocolFamily.IPv4) + .runOn(resources, SocketProtocolFamily.INET) .handle((in, out) -> { Flux.generate(s -> { // Suppressed "JdkObsolete", usage of Enumeration is deliberate From 764bf620b9be1c2629d1b6603197c57f9e3a3267 Mon Sep 17 00:00:00 2001 From: Violeta Georgieva <696661+violetagg@users.noreply.github.com> Date: Fri, 25 Apr 2025 15:07:01 +0300 Subject: [PATCH 6/8] IO_Uring is now part of Netty Signed-off-by: Violeta Georgieva <696661+violetagg@users.noreply.github.com> --- .github/workflows/check_graalvm.yml | 14 ++- .github/workflows/check_transport.yml | 10 +- build.gradle | 1 + reactor-netty-core/build.gradle | 12 +- .../netty/resources/DefaultLoopIOUring.java | 109 ++++++++++++++++++ .../resources/DefaultLoopResourcesTest.java | 10 ++ .../reactor/netty/tcp/TcpServerTests.java | 2 + .../java/reactor/netty/udp/UdpClientTest.java | 4 + .../build.gradle | 6 +- .../java/reactor/netty/http/HttpTests.java | 5 + reactor-netty-http/build.gradle | 9 +- .../netty/http/HttpMetricsHandlerTests.java | 4 + .../netty/http/client/HttpRedirectTest.java | 2 + .../netty/http/server/HttpServerTests.java | 2 + reactor-netty/build.gradle | 1 + 15 files changed, 176 insertions(+), 15 deletions(-) create mode 100644 reactor-netty-core/src/main/java17/reactor/netty/resources/DefaultLoopIOUring.java diff --git a/.github/workflows/check_graalvm.yml b/.github/workflows/check_graalvm.yml index d90a765477..cbcbd39f90 100644 --- a/.github/workflows/check_graalvm.yml +++ b/.github/workflows/check_graalvm.yml @@ -11,11 +11,15 @@ jobs: fail-fast: false matrix: os: [ubuntu-22.04, macos-13, windows-2022] - transport: [native, nio] + transport: [native, nio, io_uring] exclude: # excludes native on Windows (there's none) - os: windows-2022 transport: native + - os: windows-2022 + transport: io_uring + - os: macos-13 + transport: io_uring steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 @@ -29,5 +33,9 @@ jobs: with: distribution: 'graalvm' java-version: '17.0.12' - - name: Build with Gradle - run: ./gradlew :reactor-netty-graalvm-smoke-tests:nativeTest --no-daemon -PforceTransport=${{ matrix.transport }} \ No newline at end of file + - name: Build and test with Gradle + if: ${{ ! startsWith(matrix.transport, 'io_uring') }} + run: ./gradlew :reactor-netty-graalvm-smoke-tests:nativeTest --no-daemon -PforceTransport=${{ matrix.transport }} + - name: Build and test IO_Uring on Java 17 + if: ${{ startsWith(matrix.transport, 'io_uring') }} + run: ./gradlew :reactor-netty-graalvm-smoke-tests:nativeTest -PtestToolchain=17 --no-daemon -PforceTransport=${{ matrix.transport }} diff --git a/.github/workflows/check_transport.yml b/.github/workflows/check_transport.yml index 6357d32160..4f4bf867ea 100644 --- a/.github/workflows/check_transport.yml +++ b/.github/workflows/check_transport.yml @@ -44,11 +44,15 @@ jobs: fail-fast: false matrix: os: [ubuntu-22.04, macos-13, windows-2019] - transport: [native, nio] + transport: [native, nio, io_uring] exclude: # excludes native on Windows (there's none) - os: windows-2019 transport: native + - os: windows-2019 + transport: io_uring + - os: macos-13 + transport: io_uring steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: gradle/actions/wrapper-validation@06832c7b30a0129d7fb559bcc6e43d26f6374244 @@ -63,7 +67,11 @@ jobs: distribution: 'temurin' java-version: '8' - name: Build and test with Java 8 + if: ${{ ! startsWith(matrix.transport, 'io_uring') }} run: ./gradlew clean check -x :reactor-netty-core:java17Test --no-daemon -x spotlessCheck -PforceTransport=${{ matrix.transport }} + - name: Build and test IO_Uring on Java 17 + if: ${{ startsWith(matrix.transport, 'io_uring') }} + run: ./gradlew clean check -x :reactor-netty-core:test -PtestToolchain=17 --no-daemon -x spotlessCheck -PforceTransport=${{ matrix.transport }} - name: Build and test UDS with NIO on Java 17 if: ${{ ! startsWith(matrix.os, 'windows') }} run: ./gradlew reactor-netty-http:test --tests reactor.netty.http.server.HttpServerTests.testHttpServerWithDomainSockets_HTTP11Post -PtestToolchain=17 --no-daemon -x spotlessCheck -PforceTransport=nio diff --git a/build.gradle b/build.gradle index 695b7ad383..232a4ed640 100644 --- a/build.gradle +++ b/build.gradle @@ -203,6 +203,7 @@ subprojects { apply from: "${rootDir}/gradle/setup.gradle" apply from: "${rootDir}/gradle/javadoc.gradle" apply from: "${rootDir}/gradle/errorprone.gradle" + apply from: "${rootDir}/gradle/toolchains.gradle" java { diff --git a/reactor-netty-core/build.gradle b/reactor-netty-core/build.gradle index 98c225b807..0a304051ca 100644 --- a/reactor-netty-core/build.gradle +++ b/reactor-netty-core/build.gradle @@ -34,6 +34,7 @@ ext { "Import-Package": [ "!javax.annotation", "io.netty.channel.kqueue;resolution:=optional;version=\"[4.2,5)\"", + "io.netty.channel.uring;resolution:=optional;version=\"[4.2,5)\"", "io.netty.incubator.channel.uring;resolution:=optional", "io.micrometer.*;resolution:=optional", "*" @@ -53,6 +54,7 @@ sourceSets { } configurations { + java17CompileOnly.extendsFrom(compileOnly) java17Implementation.extendsFrom(implementation) shaded contextPropagationTestImplementation.extendsFrom(implementation) @@ -85,9 +87,10 @@ dependencies { compileOnly "io.netty:netty-transport-native-epoll:$nettyVersion" compileOnly "io.netty:netty-transport-native-kqueue:$nettyVersion" compileOnly "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion" + compileOnly "io.netty:netty-transport-native-io_uring:$nettyVersion" testImplementation "io.netty:netty-transport-native-epoll:$nettyVersion" testImplementation "io.netty:netty-transport-native-kqueue:$nettyVersion" - testImplementation "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion" + testImplementation "io.netty:netty-transport-native-io_uring:$nettyVersion" //now we explicitly add correctly qualified native, or do nothing if we want to test NIO if (forceTransport == "native") { if (osdetector.os == "osx") { @@ -98,10 +101,10 @@ dependencies { } } else if (forceTransport == "io_uring" && osdetector.os == "linux") { - testImplementation "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion$os_suffix" + testImplementation "io.netty:netty-transport-native-io_uring:$nettyVersion$os_suffix" } else if (forceTransport != "nio") { - throw new InvalidUserDataException("invalid -PforceTranport option " + forceTransport + ", should be native|nio") + throw new InvalidUserDataException("invalid -PforceTransport option " + forceTransport + ", should be native|nio|io_uring") } } else { @@ -109,8 +112,9 @@ dependencies { api "io.netty:netty-transport-native-epoll:$nettyVersion:linux-x86_64" compileOnly "io.netty:netty-transport-native-kqueue:$nettyVersion" compileOnly "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion" + compileOnly "io.netty:netty-transport-native-io_uring:$nettyVersion" testImplementation "io.netty:netty-transport-native-kqueue:$nettyVersion" - testImplementation "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion" + testImplementation "io.netty:netty-transport-native-io_uring:$nettyVersion" } //Metrics diff --git a/reactor-netty-core/src/main/java17/reactor/netty/resources/DefaultLoopIOUring.java b/reactor-netty-core/src/main/java17/reactor/netty/resources/DefaultLoopIOUring.java new file mode 100644 index 0000000000..9ac400c82d --- /dev/null +++ b/reactor-netty-core/src/main/java17/reactor/netty/resources/DefaultLoopIOUring.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2020-2025 VMware, Inc. or its affiliates, All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package reactor.netty.resources; + +import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.IoEventLoopGroup; +import io.netty.channel.MultiThreadIoEventLoopGroup; +import io.netty.channel.socket.DatagramChannel; +import io.netty.channel.socket.ServerSocketChannel; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.uring.IoUring; +import io.netty.channel.uring.IoUringDatagramChannel; +import io.netty.channel.uring.IoUringIoHandle; +import io.netty.channel.uring.IoUringIoHandler; +import io.netty.channel.uring.IoUringServerSocketChannel; +import io.netty.channel.uring.IoUringSocketChannel; +import reactor.util.Logger; +import reactor.util.Loggers; + +import java.util.concurrent.ThreadFactory; + +/** + * {@link DefaultLoop} that uses {@code io_uring} transport. + * + * @author Violeta Georgieva + */ +final class DefaultLoopIOUring implements DefaultLoop { + + @Override + @SuppressWarnings("unchecked") + public CHANNEL getChannel(Class channelClass) { + if (channelClass.equals(SocketChannel.class)) { + return (CHANNEL) new IoUringSocketChannel(); + } + if (channelClass.equals(ServerSocketChannel.class)) { + return (CHANNEL) new IoUringServerSocketChannel(); + } + if (channelClass.equals(DatagramChannel.class)) { + return (CHANNEL) new IoUringDatagramChannel(); + } + throw new IllegalArgumentException("Unsupported channel type: " + channelClass.getSimpleName()); + } + + @Override + @SuppressWarnings("unchecked") + public Class getChannelClass(Class channelClass) { + if (channelClass.equals(SocketChannel.class)) { + return (Class) IoUringSocketChannel.class; + } + if (channelClass.equals(ServerSocketChannel.class)) { + return (Class) IoUringServerSocketChannel.class; + } + if (channelClass.equals(DatagramChannel.class)) { + return (Class) IoUringDatagramChannel.class; + } + throw new IllegalArgumentException("Unsupported channel type: " + channelClass.getSimpleName()); + } + + @Override + public String getName() { + return "io_uring"; + } + + @Override + public EventLoopGroup newEventLoopGroup(int threads, ThreadFactory factory) { + return new MultiThreadIoEventLoopGroup(threads, factory, IoUringIoHandler.newFactory()); + } + + @Override + public boolean supportGroup(EventLoopGroup group) { + if (group instanceof ColocatedEventLoopGroup) { + group = ((ColocatedEventLoopGroup) group).get(); + } + return group instanceof IoEventLoopGroup && ((IoEventLoopGroup) group).isCompatible(IoUringIoHandle.class); + } + + static final Logger log = Loggers.getLogger(DefaultLoopIOUring.class); + + static final boolean isIoUringAvailable; + + static { + boolean ioUringCheck = false; + try { + Class.forName("io.netty.channel.uring.IoUring"); + ioUringCheck = IoUring.isAvailable(); + } + catch (ClassNotFoundException cnfe) { + // noop + } + isIoUringAvailable = ioUringCheck; + if (log.isDebugEnabled()) { + log.debug("Default io_uring support : " + isIoUringAvailable); + } + } +} diff --git a/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultLoopResourcesTest.java b/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultLoopResourcesTest.java index 4f5c008b71..d08d67bd04 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultLoopResourcesTest.java +++ b/reactor-netty-core/src/test/java/reactor/netty/resources/DefaultLoopResourcesTest.java @@ -24,6 +24,7 @@ import io.netty.channel.epoll.Epoll; import io.netty.channel.kqueue.KQueue; import io.netty.channel.nio.NioIoHandler; +import io.netty.channel.uring.IoUring; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.condition.OS; @@ -206,6 +207,15 @@ void testEpollIsAvailable() { assertThat(Epoll.isAvailable()).isTrue(); } + @Test + @EnabledOnOs(OS.LINUX) + void testIoUringIsAvailable() { + boolean isTransportIoUring = "io_uring".equals(System.getProperty("forceTransport")); + boolean isJava17 = System.getProperty("java.version").startsWith("17"); + assumeThat(isTransportIoUring && isJava17).isTrue(); + assertThat(IoUring.isAvailable()).isTrue(); + } + @Test @EnabledOnOs(OS.MAC) void testKQueueIsAvailable() { diff --git a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java index 95a11fe43f..c11206e5d4 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java +++ b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java @@ -1020,6 +1020,8 @@ void testTcpServerWithDomainSocketsWithPort() { @Test void testTcpServerWithDomainSockets() throws Exception { assumeThat(LoopResources.hasNativeSupport()).isTrue(); + //IO_Uring does not support UDS + assumeThat(System.getProperty("forceTransport")).isNotEqualTo("io_uring"); DisposableServer disposableServer = TcpServer.create() .bindAddress(() -> new DomainSocketAddress("/tmp/test.sock")) diff --git a/reactor-netty-core/src/test/java/reactor/netty/udp/UdpClientTest.java b/reactor-netty-core/src/test/java/reactor/netty/udp/UdpClientTest.java index 578aff8db5..b1c3b56238 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/udp/UdpClientTest.java +++ b/reactor-netty-core/src/test/java/reactor/netty/udp/UdpClientTest.java @@ -191,6 +191,8 @@ void testUdpClientWithDomainSocketsNIOTransport() { @Test void testUdpClientWithDomainSocketsConnectionRefused() { assumeThat(LoopResources.hasNativeSupport()).isTrue(); + //IO_Uring does not support UDS + assumeThat(System.getProperty("forceTransport")).isNotEqualTo("io_uring"); UdpClient.create() .remoteAddress(() -> new DomainSocketAddress("/tmp/test.sock")) .connect() @@ -202,6 +204,8 @@ void testUdpClientWithDomainSocketsConnectionRefused() { @Test void domainSocketsSmokeTest() throws Exception { assumeThat(LoopResources.hasNativeSupport()).isTrue(); + //IO_Uring does not support UDS + assumeThat(System.getProperty("forceTransport")).isNotEqualTo("io_uring"); LoopResources resources = LoopResources.create("domainSocketsSmokeTest"); CountDownLatch latch = new CountDownLatch(4); Connection server = null; diff --git a/reactor-netty-graalvm-smoke-tests/build.gradle b/reactor-netty-graalvm-smoke-tests/build.gradle index 8f14cdb6e7..57e76ddfb7 100644 --- a/reactor-netty-graalvm-smoke-tests/build.gradle +++ b/reactor-netty-graalvm-smoke-tests/build.gradle @@ -30,7 +30,7 @@ dependencies { testImplementation "io.netty:netty-transport-native-epoll:$nettyVersion" testImplementation "io.netty:netty-transport-native-kqueue:$nettyVersion" - testImplementation "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion" + testImplementation "io.netty:netty-transport-native-io_uring:$nettyVersion" if (project.hasProperty("forceTransport")) { //now we explicitly add correctly qualified native, or do nothing if we want to test NIO if (forceTransport == "native") { @@ -40,9 +40,9 @@ dependencies { testRuntimeOnly "io.netty:netty-transport-native-epoll:$nettyVersion$os_suffix" } } else if (forceTransport == "io_uring" && osdetector.os == "linux") { - testRuntimeOnly "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion$os_suffix" + testRuntimeOnly "io.netty:netty-transport-native-io_uring:$nettyVersion$os_suffix" } else if (forceTransport != "nio") { - throw new InvalidUserDataException("invalid -PforceTranport option " + forceTransport + ", should be native|nio") + throw new InvalidUserDataException("invalid -PforceTransport option " + forceTransport + ", should be native|nio|io_uring") } } diff --git a/reactor-netty-graalvm-smoke-tests/src/test/java/reactor/netty/http/HttpTests.java b/reactor-netty-graalvm-smoke-tests/src/test/java/reactor/netty/http/HttpTests.java index 179e7b359a..99d0b89590 100644 --- a/reactor-netty-graalvm-smoke-tests/src/test/java/reactor/netty/http/HttpTests.java +++ b/reactor-netty-graalvm-smoke-tests/src/test/java/reactor/netty/http/HttpTests.java @@ -17,6 +17,7 @@ import io.netty.channel.epoll.Epoll; import io.netty.channel.kqueue.KQueue; +import io.netty.channel.uring.IoUring; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -52,9 +53,13 @@ else if ("Mac OS X".equals(osName)) { assertThat(KQueue.isAvailable()).isTrue(); } } + else if ("io_uring".equals(transport) && "Linux".equals(osName)) { + assertThat(IoUring.isAvailable()).isTrue(); + } else { assertThat(Epoll.isAvailable()).isFalse(); assertThat(KQueue.isAvailable()).isFalse(); + assertThat(IoUring.isAvailable()).isFalse(); } disposableServer = diff --git a/reactor-netty-http/build.gradle b/reactor-netty-http/build.gradle index 171442095d..40025b55d7 100644 --- a/reactor-netty-http/build.gradle +++ b/reactor-netty-http/build.gradle @@ -20,8 +20,6 @@ apply plugin: 'me.champeau.gradle.japicmp' apply plugin: 'de.undercouch.download' apply plugin: 'biz.aQute.bnd.builder' -apply from: "${rootDir}/gradle/toolchains.gradle" - ext { bndOptions = [ "Export-Package" : "reactor.netty.http*;version=$osgiVersion;-noimport:=true", @@ -29,6 +27,7 @@ ext { "!javax.annotation", "io.netty.channel.kqueue;resolution:=optional;version=\"[4.2,5)\"", "io.netty.handler.codec.haproxy;resolution:=optional;version=\"[4.2,5)\"", + "io.netty.channel.uring;resolution:=optional;version=\"[4.2,5)\"", "io.netty.incubator.channel.uring;resolution:=optional", "io.netty.incubator.codec.http3;resolution:=optional", "io.micrometer.*;resolution:=optional", @@ -98,6 +97,7 @@ dependencies { compileOnly "io.netty:netty-transport-native-epoll:$nettyVersion" compileOnly "io.netty:netty-transport-native-kqueue:$nettyVersion" compileOnly "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion" + compileOnly "io.netty:netty-transport-native-io_uring:$nettyVersion" //now we explicitly add correctly qualified native, or do nothing if we want to test NIO if (forceTransport == "native") { if (osdetector.os == "osx") { @@ -108,10 +108,10 @@ dependencies { } } else if (forceTransport == "io_uring" && osdetector.os == "linux") { - testRuntimeOnly "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion$os_suffix" + testRuntimeOnly "io.netty:netty-transport-native-io_uring:$nettyVersion$os_suffix" } else if (forceTransport != "nio") { - throw new InvalidUserDataException("invalid -PforceTranport option " + forceTransport + ", should be native|nio") + throw new InvalidUserDataException("invalid -PforceTransport option " + forceTransport + ", should be native|nio|io_uring") } } else { @@ -119,6 +119,7 @@ dependencies { api "io.netty:netty-transport-native-epoll:$nettyVersion:linux-x86_64" compileOnly "io.netty:netty-transport-native-kqueue:$nettyVersion" compileOnly "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion" + compileOnly "io.netty:netty-transport-native-io_uring:$nettyVersion" } //Metrics diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/HttpMetricsHandlerTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/HttpMetricsHandlerTests.java index 7a7e3c9217..5821d3e443 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/HttpMetricsHandlerTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/HttpMetricsHandlerTests.java @@ -986,6 +986,8 @@ void testServerConnectionsRecorderBadUriUDS(HttpProtocol[] serverProtocols, Http @Nullable ProtocolSslContextSpec serverCtx, @Nullable ProtocolSslContextSpec clientCtx) throws Exception { assumeThat(LoopResources.hasNativeSupport()).isTrue(); + //IO_Uring does not support UDS + assumeThat(System.getProperty("forceTransport")).isNotEqualTo("io_uring"); testServerConnectionsRecorderBadUri(serverProtocols, clientProtocols, serverCtx, clientCtx, null, -1, false, client -> client.bindAddress(() -> new DomainSocketAddress("/tmp/test.sockclient")) .remoteAddress(() -> new DomainSocketAddress("/tmp/test.sock")), @@ -998,6 +1000,8 @@ void testServerConnectionsRecorderBadUriUDSContextAware(HttpProtocol[] serverPro @Nullable ProtocolSslContextSpec serverCtx, @Nullable ProtocolSslContextSpec clientCtx) throws Exception { assumeThat(LoopResources.hasNativeSupport()).isTrue(); + //IO_Uring does not support UDS + assumeThat(System.getProperty("forceTransport")).isNotEqualTo("io_uring"); testServerConnectionsRecorderBadUri(serverProtocols, clientProtocols, serverCtx, clientCtx, null, -1, true, client -> client.bindAddress(() -> new DomainSocketAddress("/tmp/test.sockclient")) .remoteAddress(() -> new DomainSocketAddress("/tmp/test.sock")), diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpRedirectTest.java b/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpRedirectTest.java index 4736061874..0cabfe752d 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpRedirectTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpRedirectTest.java @@ -694,6 +694,8 @@ void testHttpServerWithDomainSockets_HTTP2() { private void doTestHttpServerWithDomainSockets(HttpServer server, HttpClient client) { assumeThat(LoopResources.hasNativeSupport()).isTrue(); + //IO_Uring does not support UDS + assumeThat(System.getProperty("forceTransport")).isNotEqualTo("io_uring"); disposableServer = server.bindAddress(() -> new DomainSocketAddress("/tmp/test.sock")) .wiretap(true) diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java index 6854e34783..196d1f8368 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java @@ -2059,6 +2059,8 @@ private void doTestHttpServerWithDomainSockets(HttpServer server, HttpClient cli String expectedScheme, HttpVersion expectedVersion) { boolean isJava17 = System.getProperty("java.version").startsWith("17"); assumeThat(LoopResources.hasNativeSupport() || isJava17).isTrue(); + //IO_Uring does not support UDS + assumeThat(System.getProperty("forceTransport")).isNotEqualTo("io_uring"); disposableServer = server.bindAddress(() -> createDomainSocketAddress(isJava17)) .wiretap(true) diff --git a/reactor-netty/build.gradle b/reactor-netty/build.gradle index b53daf0ef3..2a5d87853b 100644 --- a/reactor-netty/build.gradle +++ b/reactor-netty/build.gradle @@ -27,6 +27,7 @@ dependencies { compileOnly "io.netty:netty-codec-haproxy:$nettyVersion" compileOnly "io.netty:netty-transport-native-kqueue:$nettyVersion" compileOnly "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion" + compileOnly "io.netty:netty-transport-native-io_uring:$nettyVersion" compileOnly "io.netty.incubator:netty-incubator-codec-http3:$nettyHttp3Version" compileOnly "io.projectreactor.addons:reactor-pool:$reactorPoolVersion" } From b5a814d92d5f4090e5ca6480e2125077f7128589 Mon Sep 17 00:00:00 2001 From: Violeta Georgieva <696661+violetagg@users.noreply.github.com> Date: Mon, 28 Apr 2025 19:01:06 +0300 Subject: [PATCH 7/8] [test] Use CertificateBuilder instead of deprecated SelfSignedCertificate Signed-off-by: Violeta Georgieva <696661+violetagg@users.noreply.github.com> --- reactor-netty-core/build.gradle | 1 + .../java/reactor/netty/tcp/TcpServer.java | 23 ++-- .../java/reactor/netty/NettyOutboundTest.java | 17 ++- .../netty/tcp/TcpSecureMetricsTests.java | 16 +-- .../reactor/netty/tcp/TcpServerTests.java | 22 ++-- reactor-netty-examples/build.gradle | 1 + .../examples/http/cors/HttpCorsServer.java | 20 ++-- .../netty/examples/http/echo/EchoServer.java | 17 ++- .../http/helloworld/HelloWorldServer.java | 17 ++- .../examples/http/snoop/HttpSnoopServer.java | 17 ++- .../examples/tcp/discard/DiscardServer.java | 10 +- .../netty/examples/tcp/echo/EchoServer.java | 10 +- .../tcp/securechat/SecureChatServer.java | 14 +-- .../examples/tcp/telnet/TelnetServer.java | 14 +-- reactor-netty-http/build.gradle | 3 + .../reactor/netty/ContextPropagationTest.java | 11 +- .../java/reactor/netty/http/Http3Tests.java | 66 ++++++------ .../reactor/netty/http/server/HttpServer.java | 41 ++++--- .../java/reactor/netty/ByteBufFluxTest.java | 14 +-- .../java/reactor/netty/http/Http2Tests.java | 40 +++---- .../HttpCompressionClientServerTests.java | 7 +- .../netty/http/HttpMetricsHandlerTests.java | 14 +-- .../netty/http/HttpProtocolsTests.java | 9 +- .../HttpResponseStatusCodesHandlingTests.java | 9 +- .../http/client/ConnectionPoolTests.java | 12 +-- ...edConnectionProviderCustomMetricsTest.java | 11 +- .../netty/http/client/HttpClientTest.java | 78 +++++++------- .../netty/http/client/HttpRedirectTest.java | 45 ++++---- .../netty/http/client/WebsocketTest.java | 14 +-- .../observability/ObservabilitySmokeTest.java | 14 +-- .../http/server/ConnectionInfoTests.java | 24 ++--- .../http/server/Http2ConnectionInfoTests.java | 6 +- .../http/server/HttpServerPostFormTests.java | 7 +- .../netty/http/server/HttpServerTests.java | 100 +++++++++--------- .../netty/http/server/HttpsSendFileTests.java | 16 +-- .../server/logging/error/ErrorLogTest.java | 9 +- .../DefaultPooledConnectionProviderTest.java | 24 ++--- ...dConnectionProviderDefaultMetricsTest.java | 16 +-- .../reactor/netty/tcp/SslProviderTests.java | 23 ++-- reactor-netty-incubator-quic/build.gradle | 1 + .../netty/incubator/quic/BaseQuicTests.java | 31 +++--- .../netty/incubator/quic/QuicServerTests.java | 4 +- 42 files changed, 454 insertions(+), 394 deletions(-) diff --git a/reactor-netty-core/build.gradle b/reactor-netty-core/build.gradle index 0a304051ca..203dbab3c3 100644 --- a/reactor-netty-core/build.gradle +++ b/reactor-netty-core/build.gradle @@ -144,6 +144,7 @@ dependencies { testImplementation "io.projectreactor.tools:blockhound-junit-platform:$blockHoundVersion" testImplementation "io.micrometer:micrometer-core:$micrometerVersion" testImplementation "org.reflections:reflections:$reflectionsVersion" + testImplementation "io.netty:netty-pkitesting:$nettyVersion" testRuntimeOnly "org.junit.platform:junit-platform-launcher:$junitPlatformLauncherVersion" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" diff --git a/reactor-netty-core/src/main/java/reactor/netty/tcp/TcpServer.java b/reactor-netty-core/src/main/java/reactor/netty/tcp/TcpServer.java index f55e8161ed..0531550eb3 100644 --- a/reactor-netty-core/src/main/java/reactor/netty/tcp/TcpServer.java +++ b/reactor-netty-core/src/main/java/reactor/netty/tcp/TcpServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2024 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2011-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,6 @@ import io.netty.handler.ssl.JdkSslContext; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.util.SelfSignedCertificate; import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; import reactor.netty.Connection; @@ -183,13 +182,15 @@ public TcpServer runOn(LoopResources loopResources, boolean preferNative) { *
  • {@code 0} second close_notify read timeout
  • * * - * If {@link SelfSignedCertificate} needs to be used, the sample below can be - * used. Note that {@link SelfSignedCertificate} should not be used in production. + * If self-signed certificate needs to be used, the sample below can be + * used (the functionality is provided by io.netty:netty-pkitesting). + * Note that self-signed certificate should not be used in production. *
     	 * {@code
    -	 *     SelfSignedCertificate cert = new SelfSignedCertificate();
    +	 *     X509Bundle cert =
    +	 *             new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned();
     	 *     TcpSslContextSpec tcpSslContextSpec =
    -	 *             TcpSslContextSpec.forServer(cert.certificate(), cert.privateKey());
    +	 *             TcpSslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem());
     	 *     secure(sslContextSpec -> sslContextSpec.sslContext(tcpSslContextSpec));
     	 * }
     	 * 
    @@ -209,13 +210,15 @@ public TcpServer secure(Consumer sslProvider /** * Applies an SSL configuration via the passed {@link SslProvider}. * - * If {@link SelfSignedCertificate} needs to be used, the sample below can be - * used. Note that {@link SelfSignedCertificate} should not be used in production. + * If self-signed certificate needs to be used, the sample below can be + * used (the functionality is provided by io.netty:netty-pkitesting). + * Note that self-signed certificate should not be used in production. *
     	 * {@code
    -	 *     SelfSignedCertificate cert = new SelfSignedCertificate();
    +	 *     X509Bundle cert =
    +	 *             new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned();
     	 *     TcpSslContextSpec tcpSslContextSpec =
    -	 *             TcpSslContextSpec.forServer(cert.certificate(), cert.privateKey());
    +	 *             TcpSslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem());
     	 *     secure(sslContextSpec -> sslContextSpec.sslContext(tcpSslContextSpec));
     	 * }
     	 * 
    diff --git a/reactor-netty-core/src/test/java/reactor/netty/NettyOutboundTest.java b/reactor-netty-core/src/test/java/reactor/netty/NettyOutboundTest.java index c976f230f2..bc70005f6a 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/NettyOutboundTest.java +++ b/reactor-netty-core/src/test/java/reactor/netty/NettyOutboundTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2024 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2017-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -31,7 +30,6 @@ import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Predicate; -import javax.net.ssl.SSLException; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; @@ -45,9 +43,10 @@ import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.util.SelfSignedCertificate; import io.netty.handler.stream.ChunkedNioFile; import io.netty.handler.stream.ChunkedWriteHandler; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil; import org.junit.jupiter.api.BeforeAll; @@ -59,11 +58,11 @@ class NettyOutboundTest { - static SelfSignedCertificate ssc; + static X509Bundle ssc; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @Test @@ -148,8 +147,8 @@ public NettyOutbound withConnection(Consumer withConnection) } @Test - void sendFileWithTlsUsesChunkedFile() throws URISyntaxException, SSLException { - SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + void sendFileWithTlsUsesChunkedFile() throws Exception { + SslContext sslCtx = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); final SslHandler sslHandler = sslCtx.newHandler(ByteBufAllocator.DEFAULT); List> messageWritten = new ArrayList<>(2); diff --git a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpSecureMetricsTests.java b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpSecureMetricsTests.java index 5f55ac7591..bd2cb57484 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpSecureMetricsTests.java +++ b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpSecureMetricsTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2024 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2019-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,14 +19,14 @@ import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslProvider; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeAll; import reactor.core.publisher.Mono; import javax.net.ssl.SSLException; import java.net.InetSocketAddress; -import java.security.cert.CertificateException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -47,22 +47,22 @@ */ class TcpSecureMetricsTests extends TcpMetricsTests { - static SelfSignedCertificate ssc; + static X509Bundle ssc; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @Override protected TcpServer customizeServerOptions(TcpServer tcpServer) { try { - SslContext ctx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) + SslContext ctx = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .sslProvider(SslProvider.JDK) .build(); return tcpServer.secure(ssl -> ssl.sslContext(ctx)).wiretap(true); } - catch (SSLException e) { + catch (Exception e) { throw new RuntimeException(e); } } diff --git a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java index c11206e5d4..7d2c277e0d 100644 --- a/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java +++ b/reactor-netty-core/src/test/java/reactor/netty/tcp/TcpServerTests.java @@ -28,7 +28,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -60,7 +59,8 @@ import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslProvider; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.util.NetUtil; import io.netty.util.concurrent.DefaultEventExecutor; import io.netty.util.concurrent.EventExecutor; @@ -106,12 +106,12 @@ class TcpServerTests { final Logger log = Loggers.getLogger(TcpServerTests.class); - static SelfSignedCertificate ssc; + static X509Bundle ssc; static final EventExecutor executor = new DefaultEventExecutor(); @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @AfterAll @@ -124,7 +124,7 @@ static void cleanup() throws Exception { void tcpServerHandlesJsonPojosOverSsl() throws Exception { final CountDownLatch latch = new CountDownLatch(2); - SslContext serverOptions = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) + SslContext serverOptions = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .sslProvider(SslProvider.JDK) .build(); SslContext clientOptions = SslContextBuilder.forClient() @@ -332,7 +332,7 @@ void gettingOptionsDuplicates() { @Test void sendFileSecure() throws Exception { Path largeFile = Paths.get(getClass().getResource("/largeFile.txt").toURI()); - SslContext sslServer = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + SslContext sslServer = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); SslContext sslClient = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build(); DisposableServer context = @@ -1134,13 +1134,13 @@ void testDisposeTimeoutLongOverflow() { @Test @SuppressWarnings("deprecation") void testSniSupport() throws Exception { - SelfSignedCertificate defaultCert = new SelfSignedCertificate("default"); + X509Bundle defaultCert = new CertificateBuilder().subject("CN=default").setIsCertificateAuthority(true).buildSelfSigned(); TcpSslContextSpec defaultTcpSslContextSpec = - TcpSslContextSpec.forServer(defaultCert.certificate(), defaultCert.privateKey()); + TcpSslContextSpec.forServer(defaultCert.toTempCertChainPem(), defaultCert.toTempPrivateKeyPem()); - SelfSignedCertificate testCert = new SelfSignedCertificate("test.com"); + X509Bundle testCert = new CertificateBuilder().subject("CN=test.com").setIsCertificateAuthority(true).buildSelfSigned(); TcpSslContextSpec testTcpSslContextSpec = - TcpSslContextSpec.forServer(testCert.certificate(), testCert.privateKey()); + TcpSslContextSpec.forServer(testCert.toTempCertChainPem(), testCert.toTempPrivateKeyPem()); TcpSslContextSpec clientTcpSslContextSpec = TcpSslContextSpec.forClient() diff --git a/reactor-netty-examples/build.gradle b/reactor-netty-examples/build.gradle index 837a2b4f63..bca9a45561 100644 --- a/reactor-netty-examples/build.gradle +++ b/reactor-netty-examples/build.gradle @@ -27,6 +27,7 @@ dependencies { api "io.netty:netty-transport-native-epoll:$nettyVersion:linux-x86_64" api "io.netty.incubator:netty-incubator-codec-http3:$nettyHttp3Version" + api "io.netty:netty-pkitesting:$nettyVersion" runtimeOnly "ch.qos.logback:logback-classic:$logbackVersion" runtimeOnly "io.netty:netty-tcnative-boringssl-static:$boringSslVersion$os_suffix" diff --git a/reactor-netty-examples/src/main/java/reactor/netty/examples/http/cors/HttpCorsServer.java b/reactor-netty-examples/src/main/java/reactor/netty/examples/http/cors/HttpCorsServer.java index 01d536e399..8a4ade4c59 100644 --- a/reactor-netty-examples/src/main/java/reactor/netty/examples/http/cors/HttpCorsServer.java +++ b/reactor-netty-examples/src/main/java/reactor/netty/examples/http/cors/HttpCorsServer.java @@ -19,10 +19,10 @@ import io.netty.handler.codec.http.cors.CorsConfig; import io.netty.handler.codec.http.cors.CorsConfigBuilder; import io.netty.handler.codec.http.cors.CorsHandler; -import io.netty.handler.ssl.util.SelfSignedCertificate; -import java.security.cert.CertificateException; import java.time.Duration; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import reactor.netty.Connection; import reactor.netty.NettyOutbound; import reactor.netty.NettyPipeline; @@ -48,7 +48,7 @@ public class HttpCorsServer { static final boolean HTTP2 = System.getProperty("http2") != null; static final boolean HTTP3 = System.getProperty("http3") != null; - public static void main(String... args) throws CertificateException { + public static void main(String... args) throws Exception { HttpServer server = HttpServer.create() .port(PORT) @@ -58,15 +58,21 @@ public static void main(String... args) throws CertificateException { .route(routes -> routes.route(r -> true, HttpCorsServer::okResponse)); if (SECURE) { - SelfSignedCertificate ssc = new SelfSignedCertificate("localhost"); + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); if (HTTP2) { - server = server.secure(spec -> spec.sslContext(Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + Http2SslContextSpec http2SslContextSpec = + Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + server = server.secure(spec -> spec.sslContext(http2SslContextSpec)); } else if (HTTP3) { - server = server.secure(spec -> spec.sslContext(Http3SslContextSpec.forServer(ssc.key(), null, ssc.cert()))); + Http3SslContextSpec http3SslContextSpec = + Http3SslContextSpec.forServer(ssc.toTempPrivateKeyPem(), null, ssc.toTempCertChainPem()); + server = server.secure(spec -> spec.sslContext(http3SslContextSpec)); } else { - server = server.secure(spec -> spec.sslContext(Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + Http11SslContextSpec http11SslContextSpec = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + server = server.secure(spec -> spec.sslContext(http11SslContextSpec)); } } diff --git a/reactor-netty-examples/src/main/java/reactor/netty/examples/http/echo/EchoServer.java b/reactor-netty-examples/src/main/java/reactor/netty/examples/http/echo/EchoServer.java index cf664783e2..1d191ab223 100644 --- a/reactor-netty-examples/src/main/java/reactor/netty/examples/http/echo/EchoServer.java +++ b/reactor-netty-examples/src/main/java/reactor/netty/examples/http/echo/EchoServer.java @@ -15,7 +15,8 @@ */ package reactor.netty.examples.http.echo; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import reactor.netty.http.Http11SslContextSpec; import reactor.netty.http.Http2SslContextSpec; import reactor.netty.http.Http3SslContextSpec; @@ -52,15 +53,21 @@ public static void main(String[] args) throws Exception { .send(req.receive().retain()))); if (SECURE) { - SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); if (HTTP2) { - server = server.secure(spec -> spec.sslContext(Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + Http2SslContextSpec http2SslContextSpec = + Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + server = server.secure(spec -> spec.sslContext(http2SslContextSpec)); } else if (HTTP3) { - server = server.secure(spec -> spec.sslContext(Http3SslContextSpec.forServer(ssc.key(), null, ssc.cert()))); + Http3SslContextSpec http3SslContextSpec = + Http3SslContextSpec.forServer(ssc.toTempPrivateKeyPem(), null, ssc.toTempCertChainPem()); + server = server.secure(spec -> spec.sslContext(http3SslContextSpec)); } else { - server = server.secure(spec -> spec.sslContext(Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + Http11SslContextSpec http11SslContextSpec = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + server = server.secure(spec -> spec.sslContext(http11SslContextSpec)); } } diff --git a/reactor-netty-examples/src/main/java/reactor/netty/examples/http/helloworld/HelloWorldServer.java b/reactor-netty-examples/src/main/java/reactor/netty/examples/http/helloworld/HelloWorldServer.java index c4e4f163f2..9d1f2d4174 100644 --- a/reactor-netty-examples/src/main/java/reactor/netty/examples/http/helloworld/HelloWorldServer.java +++ b/reactor-netty-examples/src/main/java/reactor/netty/examples/http/helloworld/HelloWorldServer.java @@ -15,7 +15,8 @@ */ package reactor.netty.examples.http.helloworld; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import reactor.core.publisher.Mono; import reactor.netty.http.Http11SslContextSpec; import reactor.netty.http.Http2SslContextSpec; @@ -53,15 +54,21 @@ public static void main(String[] args) throws Exception { .sendString(Mono.just("Hello World!")))); if (SECURE) { - SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); if (HTTP2) { - server = server.secure(spec -> spec.sslContext(Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + Http2SslContextSpec http2SslContextSpec = + Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + server = server.secure(spec -> spec.sslContext(http2SslContextSpec)); } else if (HTTP3) { - server = server.secure(spec -> spec.sslContext(Http3SslContextSpec.forServer(ssc.key(), null, ssc.cert()))); + Http3SslContextSpec http3SslContextSpec = + Http3SslContextSpec.forServer(ssc.toTempPrivateKeyPem(), null, ssc.toTempCertChainPem()); + server = server.secure(spec -> spec.sslContext(http3SslContextSpec)); } else { - server = server.secure(spec -> spec.sslContext(Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + Http11SslContextSpec http11SslContextSpec = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + server = server.secure(spec -> spec.sslContext(http11SslContextSpec)); } } diff --git a/reactor-netty-examples/src/main/java/reactor/netty/examples/http/snoop/HttpSnoopServer.java b/reactor-netty-examples/src/main/java/reactor/netty/examples/http/snoop/HttpSnoopServer.java index 4851263b11..6c4e854659 100644 --- a/reactor-netty-examples/src/main/java/reactor/netty/examples/http/snoop/HttpSnoopServer.java +++ b/reactor-netty-examples/src/main/java/reactor/netty/examples/http/snoop/HttpSnoopServer.java @@ -19,7 +19,8 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.QueryStringDecoder; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import reactor.core.publisher.Mono; import reactor.netty.NettyOutbound; import reactor.netty.http.Http11SslContextSpec; @@ -56,15 +57,21 @@ public static void main(String[] args) throws Exception { .compress(COMPRESS); if (SECURE) { - SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); if (HTTP2) { - server = server.secure(spec -> spec.sslContext(Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + Http2SslContextSpec http2SslContextSpec = + Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + server = server.secure(spec -> spec.sslContext(http2SslContextSpec)); } else if (HTTP3) { - server = server.secure(spec -> spec.sslContext(Http3SslContextSpec.forServer(ssc.key(), null, ssc.cert()))); + Http3SslContextSpec http3SslContextSpec = + Http3SslContextSpec.forServer(ssc.toTempPrivateKeyPem(), null, ssc.toTempCertChainPem()); + server = server.secure(spec -> spec.sslContext(http3SslContextSpec)); } else { - server = server.secure(spec -> spec.sslContext(Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + Http11SslContextSpec http11SslContextSpec = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + server = server.secure(spec -> spec.sslContext(http11SslContextSpec)); } } diff --git a/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/discard/DiscardServer.java b/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/discard/DiscardServer.java index 991160d948..baf9ffd8c3 100644 --- a/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/discard/DiscardServer.java +++ b/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/discard/DiscardServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2020-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,8 @@ */ package reactor.netty.examples.tcp.discard; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import reactor.netty.tcp.TcpServer; import reactor.netty.tcp.TcpSslContextSpec; @@ -42,9 +43,10 @@ public static void main(String[] args) throws Exception { }); if (SECURE) { - SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + TcpSslContextSpec tcpSslContextSpec = TcpSslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); server = server.secure( - spec -> spec.sslContext(TcpSslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + spec -> spec.sslContext(tcpSslContextSpec)); } server.bindNow() diff --git a/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/echo/EchoServer.java b/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/echo/EchoServer.java index ea49e48a24..20d251601a 100644 --- a/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/echo/EchoServer.java +++ b/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/echo/EchoServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2020-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,8 @@ */ package reactor.netty.examples.tcp.echo; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import reactor.netty.tcp.TcpServer; import reactor.netty.tcp.TcpSslContextSpec; @@ -38,9 +39,10 @@ public static void main(String[] args) throws Exception { .handle((in, out) -> out.send(in.receive().retain())); if (SECURE) { - SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + TcpSslContextSpec tcpSslContextSpec = TcpSslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); server = server.secure( - spec -> spec.sslContext(TcpSslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + spec -> spec.sslContext(tcpSslContextSpec)); } server.bindNow() diff --git a/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/securechat/SecureChatServer.java b/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/securechat/SecureChatServer.java index 4a929b7614..e29b1c05c2 100644 --- a/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/securechat/SecureChatServer.java +++ b/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/securechat/SecureChatServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2023-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,6 @@ package reactor.netty.examples.tcp.securechat; import java.net.InetAddress; -import java.net.UnknownHostException; -import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -28,7 +26,8 @@ import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.netty.Connection; @@ -40,11 +39,12 @@ public class SecureChatServer { private static final int PORT = Integer.parseInt(System.getProperty("port", "8992")); private static final boolean WIRETAP = System.getProperty("wiretap") != null; - public static void main(String[] args) throws UnknownHostException, CertificateException { + public static void main(String[] args) throws Exception { ConcurrentHashMap conns = new ConcurrentHashMap<>(); String hostname = InetAddress.getLocalHost().getHostName(); - SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + TcpSslContextSpec tcpSslContextSpec = TcpSslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); TcpServer.create() .port(PORT) .wiretap(WIRETAP) @@ -90,7 +90,7 @@ public static void main(String[] args) throws UnknownHostException, CertificateE return out.sendString(Flux.concat(welcomeFlux, flux)); }) - .secure(spec -> spec.sslContext(TcpSslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))) + .secure(spec -> spec.sslContext(tcpSslContextSpec)) .bindNow() .onDispose() .block(); diff --git a/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/telnet/TelnetServer.java b/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/telnet/TelnetServer.java index 6acbc104c6..1aa1922cd6 100644 --- a/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/telnet/TelnetServer.java +++ b/reactor-netty-examples/src/main/java/reactor/netty/examples/tcp/telnet/TelnetServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2023-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,14 +17,13 @@ import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import reactor.core.publisher.Flux; import reactor.netty.tcp.TcpServer; import reactor.netty.tcp.TcpSslContextSpec; import java.net.InetAddress; -import java.net.UnknownHostException; -import java.security.cert.CertificateException; import java.util.Date; public class TelnetServer { @@ -33,7 +32,7 @@ public class TelnetServer { static final int PORT = Integer.parseInt(System.getProperty("port", SECURE ? "8992" : "8993")); static final boolean WIRETAP = System.getProperty("wiretap") != null; - public static void main(String[] args) throws CertificateException, UnknownHostException { + public static void main(String[] args) throws Exception { String hostName = InetAddress.getLocalHost().getHostName(); TcpServer server = @@ -69,9 +68,10 @@ else if ("bye".equalsIgnoreCase(text)) { }); if (SECURE) { - SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + TcpSslContextSpec tcpSslContextSpec = TcpSslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); server = server.secure( - spec -> spec.sslContext(TcpSslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + spec -> spec.sslContext(tcpSslContextSpec)); } server.bindNow() diff --git a/reactor-netty-http/build.gradle b/reactor-netty-http/build.gradle index 40025b55d7..fdc751edf5 100644 --- a/reactor-netty-http/build.gradle +++ b/reactor-netty-http/build.gradle @@ -151,6 +151,7 @@ dependencies { exclude module: "context-propagation" } testImplementation "org.reflections:reflections:$reflectionsVersion" + testImplementation "io.netty:netty-pkitesting:$nettyVersion" testRuntimeOnly "org.junit.platform:junit-platform-launcher:$junitPlatformLauncherVersion" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" @@ -195,6 +196,7 @@ dependencies { contextPropagationTestImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion" contextPropagationTestImplementation "ch.qos.logback:logback-classic:$logbackVersion" contextPropagationTestImplementation "io.micrometer:context-propagation:$contextPropagationVersion" + contextPropagationTestImplementation "io.netty:netty-pkitesting:$nettyVersion" contextPropagationTestRuntimeOnly "org.junit.platform:junit-platform-launcher:$junitPlatformLauncherVersion" contextPropagationTestRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" @@ -206,6 +208,7 @@ dependencies { http3TestImplementation "org.assertj:assertj-core:$assertJVersion" http3TestImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" http3TestImplementation "io.netty.incubator:netty-incubator-codec-http3:$nettyHttp3Version" + http3TestImplementation "io.netty:netty-pkitesting:$nettyVersion" http3TestRuntimeOnly "org.junit.platform:junit-platform-launcher:$junitPlatformLauncherVersion" http3TestRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" http3TestRuntimeOnly "ch.qos.logback:logback-classic:$logbackVersion" diff --git a/reactor-netty-http/src/contextPropagationTest/java/reactor/netty/ContextPropagationTest.java b/reactor-netty-http/src/contextPropagationTest/java/reactor/netty/ContextPropagationTest.java index 1479c174a4..8f8a064680 100644 --- a/reactor-netty-http/src/contextPropagationTest/java/reactor/netty/ContextPropagationTest.java +++ b/reactor-netty-http/src/contextPropagationTest/java/reactor/netty/ContextPropagationTest.java @@ -28,7 +28,8 @@ import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http2.Http2StreamChannel; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -56,7 +57,7 @@ class ContextPropagationTest { static final ConnectionProvider provider = ConnectionProvider.create("testContextPropagation", 1); static final ContextRegistry registry = ContextRegistry.getInstance(); - static SelfSignedCertificate ssc; + static X509Bundle ssc; HttpServer baseServer; Http2SslContextSpec serverCtx; @@ -64,7 +65,7 @@ class ContextPropagationTest { @BeforeAll static void createSelfSignedCertificate() throws Exception { - ssc = new SelfSignedCertificate(); + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @AfterAll @@ -74,8 +75,8 @@ static void disposePool() { } @BeforeEach - void setUp() { - serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void setUp() throws Exception { + serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); baseServer = HttpServer.create() .wiretap(true) diff --git a/reactor-netty-http/src/http3Test/java/reactor/netty/http/Http3Tests.java b/reactor-netty-http/src/http3Test/java/reactor/netty/http/Http3Tests.java index 9e7ee35b26..7ef94aa208 100644 --- a/reactor-netty-http/src/http3Test/java/reactor/netty/http/Http3Tests.java +++ b/reactor-netty-http/src/http3Test/java/reactor/netty/http/Http3Tests.java @@ -36,6 +36,8 @@ import io.netty.incubator.codec.http3.Http3HeadersFrame; import io.netty.incubator.codec.quic.InsecureQuicTokenHandler; import io.netty.incubator.codec.quic.QuicChannel; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -69,7 +71,6 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.charset.Charset; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -107,13 +108,13 @@ class Http3Tests { static final String HTTP3_WITHOUT_TLS_SERVER = "Configured HTTP/3 protocol without TLS. " + "Configure TLS via HttpServer#secure"; - static SelfSignedCertificate ssc; + static X509Bundle ssc; @Nullable DisposableServer disposableServer; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @AfterEach @@ -299,7 +300,7 @@ void testAccessLogWithForwardedHeader() throws Exception { } @Test - void testConcurrentRequestsDefaultPool() { + void testConcurrentRequestsDefaultPool() throws Exception { disposableServer = createServer() .handle((req, res) -> res.sendString(Mono.just("testConcurrentRequestsDefaultPool"))) @@ -309,7 +310,7 @@ void testConcurrentRequestsDefaultPool() { } @Test - void testConcurrentRequestsOneConnection() { + void testConcurrentRequestsOneConnection() throws Exception { disposableServer = createServer() .handle((req, res) -> res.sendString(Mono.just("testConcurrentRequestsOneConnection"))) @@ -326,7 +327,7 @@ void testConcurrentRequestsOneConnection() { } @Test - void testConcurrentRequestsCustomPool() { + void testConcurrentRequestsCustomPool() throws Exception { disposableServer = createServer() .handle((req, res) -> res.sendString(Mono.just("testConcurrentRequestsCustomPool"))) @@ -363,7 +364,7 @@ static void doTestConcurrentRequests(HttpClient client) { } @Test - void testGetRequest() { + void testGetRequest() throws Exception { disposableServer = createServer() .handle((req, res) -> res.sendString(Mono.just("Hello"))) @@ -382,7 +383,7 @@ void testGetRequest() { } @Test - void testHttp3ForMemoryLeaks() { + void testHttp3ForMemoryLeaks() throws Exception { disposableServer = createServer() .wiretap(false) @@ -417,7 +418,7 @@ void testHttp3ForMemoryLeaks() { } @Test - void testHttpClientNoSecurityHttp3Fails() { + void testHttpClientNoSecurityHttp3Fails() throws Exception { disposableServer = createServer() .handle((req, res) -> res.sendString(Mono.just("Hello"))) @@ -435,7 +436,7 @@ void testHttpClientNoSecurityHttp3Fails() { } @Test - void testHttpServerNoSecurityHttp3Fails() { + void testHttpServerNoSecurityHttp3Fails() throws Exception { createServer() .noSSL() .handle((req, res) -> res.sendString(Mono.just("Hello"))) @@ -445,31 +446,31 @@ void testHttpServerNoSecurityHttp3Fails() { } @Test - void testIssue3524Flux() { + void testIssue3524Flux() throws Exception { // sends the message and then last http content testRequestBody(sender -> sender.send((req, out) -> out.sendString(Flux.just("te", "st"))), 3); } @Test - void testIssue3524Mono() { + void testIssue3524Mono() throws Exception { // sends "full" request testRequestBody(sender -> sender.send((req, out) -> out.sendString(Mono.just("test"))), 1); } @Test - void testIssue3524MonoEmpty() { + void testIssue3524MonoEmpty() throws Exception { // sends "full" request testRequestBody(sender -> sender.send((req, out) -> Mono.empty()), 0); } @Test - void testIssue3524NoBody() { + void testIssue3524NoBody() throws Exception { // sends "full" request testRequestBody(sender -> sender.send((req, out) -> out), 0); } @Test - void testIssue3524Object() { + void testIssue3524Object() throws Exception { // sends "full" request testRequestBody(sender -> sender.send((req, out) -> out.sendObject(Unpooled.wrappedBuffer("test".getBytes(Charset.defaultCharset())))), 1); } @@ -651,25 +652,26 @@ void testMetrics() throws Exception { } @Test - void testMonoRequestBodySentAsFullRequest_Flux() { + void testMonoRequestBodySentAsFullRequest_Flux() throws Exception { // sends the message and then last http content testRequestBody(sender -> sender.send(ByteBufFlux.fromString(Mono.just("test"))), 2); } @Test - void testMonoRequestBodySentAsFullRequest_Mono() { + void testMonoRequestBodySentAsFullRequest_Mono() throws Exception { // sends "full" request testRequestBody(sender -> sender.send(ByteBufMono.fromString(Mono.just("test"))), 1); } @Test - void testMonoRequestBodySentAsFullRequest_MonoEmpty() { + void testMonoRequestBodySentAsFullRequest_MonoEmpty() throws Exception { // sends "full" request testRequestBody(sender -> sender.send(Mono.empty()), 0); } @SuppressWarnings("FutureReturnValueIgnored") - private void testRequestBody(Function> sendFunction, int expectedMsg) { + private void testRequestBody(Function> sendFunction, int expectedMsg) + throws Exception { disposableServer = createServer().handle((req, res) -> req.receive() .then(res.send())) @@ -722,16 +724,16 @@ else if (msg instanceof Http3DataFrame) { } @Test - void testPostRequest() { + void testPostRequest() throws Exception { doTestPostRequest(false); } @Test - void testPostRequestExternalThread() { + void testPostRequestExternalThread() throws Exception { doTestPostRequest(true); } - void doTestPostRequest(boolean externalThread) { + void doTestPostRequest(boolean externalThread) throws Exception { disposableServer = createServer() .handle((req, res) -> { @@ -757,7 +759,7 @@ void doTestPostRequest(boolean externalThread) { } @Test - void testProtocolVersion() { + void testProtocolVersion() throws Exception { disposableServer = createServer().handle((req, res) -> res.sendString(Mono.just(req.protocol()))) .bindNow(); @@ -818,7 +820,7 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { } @Test - void testTrailerHeadersChunkedResponse() { + void testTrailerHeadersChunkedResponse() throws Exception { disposableServer = createServer() .handle((req, res) -> @@ -830,7 +832,7 @@ void testTrailerHeadersChunkedResponse() { } @Test - void testTrailerHeadersDisallowedNotSent() { + void testTrailerHeadersDisallowedNotSent() throws Exception { disposableServer = createServer() .handle((req, res) -> @@ -844,7 +846,7 @@ void testTrailerHeadersDisallowedNotSent() { } @Test - void testTrailerHeadersFailedChunkedResponse() { + void testTrailerHeadersFailedChunkedResponse() throws Exception { disposableServer = createServer() .handle((req, res) -> @@ -861,7 +863,7 @@ void testTrailerHeadersFailedChunkedResponse() { } @Test - void testTrailerHeadersFullResponse() { + void testTrailerHeadersFullResponse() throws Exception { disposableServer = createServer() .handle((req, res) -> @@ -874,7 +876,7 @@ void testTrailerHeadersFullResponse() { } @Test - void testTrailerHeadersNotSpecifiedUpfront() { + void testTrailerHeadersNotSpecifiedUpfront() throws Exception { disposableServer = createServer() .handle((req, res) -> @@ -899,7 +901,7 @@ private static void doTestTrailerHeaders(HttpClient client, String expectedHeade } @Test - void clientSendsError() { + void clientSendsError() throws Exception { TestHttpMeterRegistrarAdapter metricsRegistrar = new TestHttpMeterRegistrarAdapter(); ConnectionProvider provider = @@ -968,8 +970,8 @@ static HttpClient createClient(@Nullable ConnectionProvider pool, int port) { .maxStreamDataBidirectionalLocal(1000000)); } - static HttpServer createServer() { - Http3SslContextSpec serverCtx = Http3SslContextSpec.forServer(ssc.key(), null, ssc.cert()); + static HttpServer createServer() throws Exception { + Http3SslContextSpec serverCtx = Http3SslContextSpec.forServer(ssc.toTempPrivateKeyPem(), null, ssc.toTempCertChainPem()); return HttpServer.create() .port(0) .wiretap(true) diff --git a/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServer.java b/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServer.java index 85339541cc..685767fe21 100644 --- a/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServer.java +++ b/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServer.java @@ -34,7 +34,6 @@ import io.netty.handler.ssl.JdkSslContext; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.util.SelfSignedCertificate; import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; @@ -1072,13 +1071,15 @@ public final HttpServer route(Consumer routesBuilder) *
  • {@code 3} seconds close_notify flush timeout
  • *
  • {@code 0} second close_notify read timeout
  • * - * If {@link SelfSignedCertificate} needs to be used, the sample below can be - * used. Note that {@link SelfSignedCertificate} should not be used in production. + * If self-signed certificate needs to be used, the sample below can be + * used (the functionality is provided by io.netty:netty-pkitesting). + * Note that self-signed certificate should not be used in production. *
     	 * {@code
    -	 *     SelfSignedCertificate cert = new SelfSignedCertificate();
    +	 *     X509Bundle cert =
    +	 *             new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned();
     	 *     Http11SslContextSpec http11SslContextSpec =
    -	 *             Http11SslContextSpec.forServer(cert.certificate(), cert.privateKey());
    +	 *             Http11SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem());
     	 *     secure(sslContextSpec -> sslContextSpec.sslContext(http11SslContextSpec));
     	 * }
     	 * 
    @@ -1100,13 +1101,15 @@ public final HttpServer secure(Consumer sslP *
  • {@code 0} second close_notify read timeout
  • * *

    - * If {@link SelfSignedCertificate} needs to be used, the sample below can be - * used. Note that {@link SelfSignedCertificate} should not be used in production. + * If self-signed certificate needs to be used, the sample below can be + * used (the functionality is provided by io.netty:netty-pkitesting). + * Note that self-signed certificate should not be used in production. *

     	 * {@code
    -	 *     SelfSignedCertificate cert = new SelfSignedCertificate();
    +	 *     X509Bundle cert =
    +	 *             new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned();
     	 *     Http11SslContextSpec http11SslContextSpec =
    -	 *             Http11SslContextSpec.forServer(cert.certificate(), cert.privateKey());
    +	 *             Http11SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem());
     	 *     secure(sslContextSpec -> sslContextSpec.sslContext(http11SslContextSpec), true);
     	 * }
     	 * 
    @@ -1131,13 +1134,15 @@ public final HttpServer secure(Consumer sslP /** * Applies an SSL configuration via the passed {@link SslProvider}. * - * If {@link SelfSignedCertificate} needs to be used, the sample below can be - * used. Note that {@link SelfSignedCertificate} should not be used in production. + * If self-signed certificate needs to be used, the sample below can be + * used (the functionality is provided by io.netty:netty-pkitesting). + * Note that self-signed certificate should not be used in production. *
     	 * {@code
    -	 *     SelfSignedCertificate cert = new SelfSignedCertificate();
    +	 *     X509Bundle cert =
    +	 *             new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned();
     	 *     Http11SslContextSpec http11SslContextSpec =
    -	 *             Http11SslContextSpec.forServer(cert.certificate(), cert.privateKey());
    +	 *             Http11SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem());
     	 *     secure(sslContextSpec -> sslContextSpec.sslContext(http11SslContextSpec));
     	 * }
     	 * 
    @@ -1153,13 +1158,15 @@ public final HttpServer secure(SslProvider sslProvider) { /** * Applies an SSL configuration via the passed {@link SslProvider}. *

    - * If {@link SelfSignedCertificate} needs to be used, the sample below can be - * used. Note that {@link SelfSignedCertificate} should not be used in production. + * If self-signed certificate needs to be used, the sample below can be + * used (the functionality is provided by io.netty:netty-pkitesting). + * Note that self-signed certificate should not be used in production. *

     	 * {@code
    -	 *     SelfSignedCertificate cert = new SelfSignedCertificate();
    +	 *     X509Bundle cert =
    +	 *             new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned();
     	 *     Http11SslContextSpec http11SslContextSpec =
    -	 *             Http11SslContextSpec.forServer(cert.certificate(), cert.privateKey());
    +	 *             Http11SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem());
     	 *     secure(sslContextSpec -> sslContextSpec.sslContext(http11SslContextSpec), true);
     	 * }
     	 * 
    diff --git a/reactor-netty-http/src/test/java/reactor/netty/ByteBufFluxTest.java b/reactor-netty-http/src/test/java/reactor/netty/ByteBufFluxTest.java index ace1929e41..817859f71a 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/ByteBufFluxTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/ByteBufFluxTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2023 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2017-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,14 +17,14 @@ import java.nio.file.Path; import java.nio.file.Paths; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.concurrent.atomic.AtomicLong; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import reactor.netty.http.client.HttpClient; @@ -39,11 +39,11 @@ */ class ByteBufFluxTest extends BaseHttpTest { - static SelfSignedCertificate ssc; + static X509Bundle ssc; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @Test @@ -60,7 +60,7 @@ private void doTestByteBufFluxFromPath(boolean withSecurity) throws Exception { HttpServer server = createServer(); HttpClient client = createClient(() -> disposableServer.address()); if (withSecurity) { - SslContext sslServer = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + SslContext sslServer = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); SslContext sslClient = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE).build(); server = server.secure(ssl -> ssl.sslContext(sslServer)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/Http2Tests.java b/reactor-netty-http/src/test/java/reactor/netty/http/Http2Tests.java index 7c636e2e7f..891ab0c344 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/Http2Tests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/Http2Tests.java @@ -19,7 +19,8 @@ import io.netty.handler.codec.http2.Http2Connection; import io.netty.handler.codec.http2.Http2FrameCodec; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -43,7 +44,6 @@ import reactor.util.function.Tuple2; import java.nio.charset.Charset; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -76,11 +76,11 @@ class Http2Tests extends BaseHttpTest { "Use the non Clear-Text H2 protocol via HttpClient#protocol or disable TLS " + "via HttpClient#noSSL()"; - static SelfSignedCertificate ssc; + static X509Bundle ssc; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @Test @@ -95,8 +95,8 @@ void testHttpNoSslH2Fails() { @Test @SuppressWarnings("deprecation") - void testHttpSslH2CFails() { - Http2SslContextSpec serverOptions = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testHttpSslH2CFails() throws Exception { + Http2SslContextSpec serverOptions = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); createServer() .protocol(HttpProtocol.H2C) @@ -224,7 +224,7 @@ void doTestMaxActiveStreams(HttpClient baseClient, int maxActiveStreams, int exp @SuppressWarnings("deprecation") void doTestMaxActiveStreams(HttpClient baseClient, int maxActiveStreams, int concurrency, int prefetch, int expectedOnNext, int expectedOnError) throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -287,8 +287,8 @@ else if (signal.getThrowable() instanceof PoolAcquireTimeoutException && @Test @SuppressWarnings("deprecation") - void testHttp2ForMemoryLeaks() { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testHttp2ForMemoryLeaks() throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -497,7 +497,7 @@ private static void doTestIssue1394_ProtocolSchemeNotCompatible(HttpProtocol pro * https://github.com/reactor/reactor-netty/issues/1813 */ @Test - void testTooManyPermitsReturned_DefaultPool() { + void testTooManyPermitsReturned_DefaultPool() throws Exception { testTooManyPermitsReturned(createClient(() -> disposableServer.address())); } @@ -505,7 +505,7 @@ void testTooManyPermitsReturned_DefaultPool() { * https://github.com/reactor/reactor-netty/issues/1813 */ @Test - void testTooManyPermitsReturned_CustomPool() { + void testTooManyPermitsReturned_CustomPool() throws Exception { ConnectionProvider provider = ConnectionProvider.create("testTooManyPermitsReturned_CustomPool", 2); try { testTooManyPermitsReturned(createClient(provider, () -> disposableServer.address())); @@ -517,8 +517,8 @@ void testTooManyPermitsReturned_CustomPool() { } @SuppressWarnings("deprecation") - private void testTooManyPermitsReturned(HttpClient client) { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + private void testTooManyPermitsReturned(HttpClient client) throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -613,8 +613,8 @@ void testMaxStreamsH2C(HttpProtocol[] serverProtocols, HttpProtocol[] clientProt @ParameterizedTest @MethodSource("h2CompatibleCombinations") @SuppressWarnings("deprecation") - void testMaxStreamsH2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testMaxStreamsH2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -671,8 +671,8 @@ void testEmptyDataFrameH2C(HttpProtocol[] serverProtocols, HttpProtocol[] client @ParameterizedTest @MethodSource("h2CompatibleCombinations") @SuppressWarnings("deprecation") - void testEmptyDataFrameH2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testEmptyDataFrameH2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -715,8 +715,8 @@ void h2cClientSendsError(HttpProtocol[] serverProtocols, HttpProtocol[] clientPr @ParameterizedTest @MethodSource("h2CompatibleCombinations") @SuppressWarnings("deprecation") - void h2ClientSendsError(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void h2ClientSendsError(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/HttpCompressionClientServerTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/HttpCompressionClientServerTests.java index 3dd9fb5b99..1287862695 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/HttpCompressionClientServerTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/HttpCompressionClientServerTests.java @@ -44,7 +44,8 @@ import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.LastHttpContent; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -86,8 +87,8 @@ class HttpCompressionClientServerTests extends BaseHttpTest { @SuppressWarnings("deprecation") static Object[][] data() throws Exception { - SelfSignedCertificate cert = new SelfSignedCertificate(); - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(cert.certificate(), cert.privateKey()); + X509Bundle cert = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/HttpMetricsHandlerTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/HttpMetricsHandlerTests.java index 5821d3e443..471300ae16 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/HttpMetricsHandlerTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/HttpMetricsHandlerTests.java @@ -36,8 +36,9 @@ import io.netty.handler.codec.http2.HttpConversionUtil; import io.netty.handler.ssl.SslProvider; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; import io.netty.handler.timeout.ReadTimeoutException; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.util.concurrent.DefaultEventExecutor; import io.netty.util.concurrent.EventExecutor; import org.assertj.core.api.Assertions; @@ -73,7 +74,6 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.Arrays; import java.util.List; @@ -133,7 +133,7 @@ class HttpMetricsHandlerTests extends BaseHttpTest { final Flux body = ByteBufFlux.fromString(Flux.just("Hello", " ", "World", "!")).delayElements(Duration.ofMillis(10)); - static SelfSignedCertificate ssc; + static X509Bundle ssc; static Http11SslContextSpec serverCtx11; static Http2SslContextSpec serverCtx2; static Http11SslContextSpec clientCtx11; @@ -149,12 +149,12 @@ public static void afterClass() throws Exception { } @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { + static void createSelfSignedCertificate() throws Exception { Assertions.setMaxStackTraceElementsDisplayed(100); - ssc = new SelfSignedCertificate(); - serverCtx11 = Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()) + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + serverCtx11 = Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .configure(builder -> builder.sslProvider(SslProvider.JDK)); - serverCtx2 = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()) + serverCtx2 = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .configure(builder -> builder.sslProvider(SslProvider.JDK)); clientCtx11 = Http11SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE) diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/HttpProtocolsTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/HttpProtocolsTests.java index e1f303205f..8a4cbbd3c2 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/HttpProtocolsTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/HttpProtocolsTests.java @@ -46,8 +46,9 @@ import io.netty.handler.codec.http2.Http2StreamChannel; import io.netty.handler.ssl.SslHandshakeCompletionEvent; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.util.concurrent.DefaultPromise; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; @@ -197,12 +198,12 @@ static Object[][] dataCompatibleCombinations_CustomPool() throws Exception { @SuppressWarnings("deprecation") static Object[][] data(boolean onlyCompatible, boolean disablePool, boolean useCustomPool) throws Exception { - SelfSignedCertificate cert = new SelfSignedCertificate(); - Http11SslContextSpec serverCtxHttp11 = Http11SslContextSpec.forServer(cert.certificate(), cert.privateKey()); + X509Bundle cert = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + Http11SslContextSpec serverCtxHttp11 = Http11SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); Http11SslContextSpec clientCtxHttp11 = Http11SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); - Http2SslContextSpec serverCtxHttp2 = Http2SslContextSpec.forServer(cert.certificate(), cert.privateKey()); + Http2SslContextSpec serverCtxHttp2 = Http2SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); Http2SslContextSpec clientCtxHttp2 = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/HttpResponseStatusCodesHandlingTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/HttpResponseStatusCodesHandlingTests.java index 0ecb48afe4..69df23ba9a 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/HttpResponseStatusCodesHandlingTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/HttpResponseStatusCodesHandlingTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2024 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2017-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,8 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -74,11 +75,11 @@ void httpStatusCode404IsHandledByTheClient() { @MethodSource("httpCompatibleCombinations") @SuppressWarnings("deprecation") void noContentStatusCodes(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { - SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); HttpServer server = createServer().protocol(serverProtocols); if (Arrays.asList(serverProtocols).contains(HttpProtocol.H2)) { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); server = server.secure(spec -> spec.sslContext(serverCtx)); } diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/client/ConnectionPoolTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/client/ConnectionPoolTests.java index 1716295c36..a04a8ee6bc 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/client/ConnectionPoolTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/client/ConnectionPoolTests.java @@ -21,7 +21,8 @@ import io.netty.channel.group.DefaultChannelGroup; import io.netty.handler.logging.LogLevel; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.resolver.DefaultAddressResolverGroup; import io.netty.util.AttributeKey; import io.netty.util.concurrent.DefaultEventExecutor; @@ -47,7 +48,6 @@ import reactor.util.function.Tuple2; import java.nio.charset.Charset; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.List; import java.util.concurrent.ExecutionException; @@ -76,7 +76,7 @@ class ConnectionPoolTests extends BaseHttpTest { @BeforeAll @SuppressWarnings("deprecation") - static void prepare() throws CertificateException { + static void prepare() throws Exception { HttpServer server = createServer(); server1 = server.handle((req, res) -> res.sendString(Mono.just("server1-ConnectionPoolTests"))) @@ -85,9 +85,9 @@ static void prepare() throws CertificateException { server2 = server.handle((req, res) -> res.sendString(Mono.just("server2-ConnectionPoolTests"))) .bindNow(); - SelfSignedCertificate cert = new SelfSignedCertificate(); - Http11SslContextSpec http11SslContextSpec = Http11SslContextSpec.forServer(cert.certificate(), cert.privateKey()); - Http2SslContextSpec http2SslContextSpec = Http2SslContextSpec.forServer(cert.certificate(), cert.privateKey()); + X509Bundle cert = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + Http11SslContextSpec http11SslContextSpec = Http11SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); + Http2SslContextSpec http2SslContextSpec = Http2SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); server3 = server.protocol(HttpProtocol.H2, HttpProtocol.HTTP11) .secure(spec -> spec.sslContext(http2SslContextSpec)) diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/client/Http2PooledConnectionProviderCustomMetricsTest.java b/reactor-netty-http/src/test/java/reactor/netty/http/client/Http2PooledConnectionProviderCustomMetricsTest.java index 2f445bfd69..81e8943883 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/client/Http2PooledConnectionProviderCustomMetricsTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/client/Http2PooledConnectionProviderCustomMetricsTest.java @@ -18,7 +18,8 @@ import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -26,9 +27,7 @@ import reactor.netty.BaseHttpTest; import reactor.netty.resources.ConnectionProvider; -import javax.net.ssl.SSLException; import java.net.SocketAddress; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -45,9 +44,9 @@ class Http2PooledConnectionProviderCustomMetricsTest extends BaseHttpTest { static SslContext sslClient; @BeforeAll - static void setUp() throws CertificateException, SSLException { - SelfSignedCertificate ssc = new SelfSignedCertificate(); - sslServer = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + static void setUp() throws Exception { + X509Bundle ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + sslServer = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); sslClient = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) .build(); diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpClientTest.java b/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpClientTest.java index da37e42a3c..6867f8b9ba 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpClientTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpClientTest.java @@ -93,8 +93,9 @@ import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.resolver.AddressResolverGroup; import io.netty.resolver.dns.DnsAddressResolverGroup; import io.netty.util.CharsetUtil; @@ -165,12 +166,12 @@ class HttpClientTest extends BaseHttpTest { static final Logger log = Loggers.getLogger(HttpClientTest.class); - static SelfSignedCertificate ssc; + static X509Bundle ssc; static final EventExecutor executor = new DefaultEventExecutor(); @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @AfterAll @@ -595,8 +596,8 @@ void gettingOptionsDuplicates() { } @Test - void sslExchangeRelativeGet() throws SSLException { - SslContext sslServer = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) + void sslExchangeRelativeGet() throws Exception { + SslContext sslServer = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .build(); SslContext sslClient = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) @@ -631,7 +632,7 @@ void testMaxConnectionPools(boolean withMaxConnectionPools) throws Exception { String loggerName = "reactor.netty.resources.PooledConnectionProvider"; int count = withMaxConnectionPools ? 1 : 0; try (LogTracker logTracker = new LogTracker(loggerName, count, msg)) { - SslContext sslServer = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + SslContext sslServer = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); disposableServer = createServer().secure(ssl -> ssl.sslContext(sslServer)) @@ -677,8 +678,8 @@ private static SslContext createClientSslContext() { } @Test - void sslExchangeAbsoluteGet() throws SSLException { - SslContext sslServer = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + void sslExchangeAbsoluteGet() throws Exception { + SslContext sslServer = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); SslContext sslClient = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE).build(); @@ -699,9 +700,9 @@ void sslExchangeAbsoluteGet() throws SSLException { } @Test - void secureSendFile() throws SSLException, URISyntaxException { + void secureSendFile() throws Exception { Path largeFile = Paths.get(getClass().getResource("/largeFile.txt").toURI()); - SslContext sslServer = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + SslContext sslServer = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); SslContext sslClient = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE).build(); AtomicReference uploaded = new AtomicReference<>(); @@ -1073,9 +1074,9 @@ void testIssue361() { @Test @SuppressWarnings("deprecation") - void testIssue473() { + void testIssue473() throws Exception { Http11SslContextSpec serverSslContextBuilder = - Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); disposableServer = createServer() .secure(spec -> spec.sslContext(serverSslContextBuilder)) @@ -1093,11 +1094,12 @@ void testIssue473() { @Test @SuppressWarnings("deprecation") - void testIssue407_1() { + void testIssue407_1() throws Exception { + Http11SslContextSpec serverCtx = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); disposableServer = createServer() - .secure(spec -> spec.sslContext( - Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))) + .secure(spec -> spec.sslContext(serverCtx)) .handle((req, res) -> res.sendString(Mono.just("test"))) .bindNow(Duration.ofSeconds(30)); @@ -1155,11 +1157,12 @@ void testIssue407_1() { @Test @SuppressWarnings("deprecation") - void testIssue407_2() { + void testIssue407_2() throws Exception { + Http11SslContextSpec serverCtx = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); disposableServer = createServer() - .secure(spec -> spec.sslContext( - Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))) + .secure(spec -> spec.sslContext(serverCtx)) .handle((req, res) -> res.sendString(Mono.just("test"))) .bindNow(Duration.ofSeconds(30)); @@ -1456,7 +1459,7 @@ void testPreferContentLengthWhenPost() { @Test void testExplicitEmptyBodyOnGetWorks() throws Exception { - SslContext sslServer = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) + SslContext sslServer = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .build(); SslContext sslClient = SslContextBuilder.forClient() @@ -2049,56 +2052,56 @@ void testDoOnRequestInvokedBeforeSendingRequest() { } @Test - void testIssue719_TEWithTextNoSSL() { + void testIssue719_TEWithTextNoSSL() throws Exception { doTestIssue719(ByteBufFlux.fromString(Mono.just("test")), h -> h.set("Transfer-Encoding", "chunked"), false); } @Test - void testIssue719_CLWithTextNoSSL() { + void testIssue719_CLWithTextNoSSL() throws Exception { doTestIssue719(ByteBufFlux.fromString(Mono.just("test")), h -> h.set("Content-Length", "4"), false); } @Test - void testIssue719_TENoTextNoSSL() { + void testIssue719_TENoTextNoSSL() throws Exception { doTestIssue719(ByteBufFlux.fromString(Mono.just("")), h -> h.set("Transfer-Encoding", "chunked"), false); } @Test - void testIssue719_CLNoTextNoSSL() { + void testIssue719_CLNoTextNoSSL() throws Exception { doTestIssue719(ByteBufFlux.fromString(Mono.just("")), h -> h.set("Content-Length", "0"), false); } @Test - void testIssue719_TEWithTextWithSSL() { + void testIssue719_TEWithTextWithSSL() throws Exception { doTestIssue719(ByteBufFlux.fromString(Mono.just("test")), h -> h.set("Transfer-Encoding", "chunked"), true); } @Test - void testIssue719_CLWithTextWithSSL() { + void testIssue719_CLWithTextWithSSL() throws Exception { doTestIssue719(ByteBufFlux.fromString(Mono.just("test")), h -> h.set("Content-Length", "4"), true); } @Test - void testIssue719_TENoTextWithSSL() { + void testIssue719_TENoTextWithSSL() throws Exception { doTestIssue719(ByteBufFlux.fromString(Mono.just("")), h -> h.set("Transfer-Encoding", "chunked"), true); } @Test - void testIssue719_CLNoTextWithSSL() { + void testIssue719_CLNoTextWithSSL() throws Exception { doTestIssue719(ByteBufFlux.fromString(Mono.just("")), h -> h.set("Content-Length", "0"), true); } @SuppressWarnings("deprecation") private void doTestIssue719(Publisher clientSend, - Consumer clientSendHeaders, boolean ssl) { + Consumer clientSendHeaders, boolean ssl) throws Exception { HttpServer server = createServer() .handle((req, res) -> req.receive() @@ -2106,8 +2109,9 @@ private void doTestIssue719(Publisher clientSend, .then())); if (ssl) { - server = server.secure(spec -> spec.sslContext( - Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))); + Http11SslContextSpec serverCtx = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + server = server.secure(spec -> spec.sslContext(serverCtx)); } disposableServer = server.bindNow(); @@ -2324,7 +2328,7 @@ void testConnectionLifeTimeFixedPoolHttp1() throws Exception { @Test @SuppressWarnings("deprecation") void testConnectionLifeTimeFixedPoolHttp2_1() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2367,7 +2371,7 @@ void testConnectionLifeTimeElasticPoolHttp1() throws Exception { @Test @SuppressWarnings("deprecation") void testConnectionLifeTimeElasticPoolHttp2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2409,7 +2413,7 @@ void testConnectionNoLifeTimeFixedPoolHttp1() throws Exception { @Test @SuppressWarnings("deprecation") void testConnectionNoLifeTimeFixedPoolHttp2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2448,7 +2452,7 @@ void testConnectionNoLifeTimeElasticPoolHttp1() throws Exception { @Test @SuppressWarnings("deprecation") void testConnectionNoLifeTimeElasticPoolHttp2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2494,8 +2498,8 @@ private ChannelId[] doTestConnectionLifeTime(HttpServer server, HttpClient clien @Test @SuppressWarnings("deprecation") - void testConnectionLifeTimeFixedPoolHttp2_2() { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testConnectionLifeTimeFixedPoolHttp2_2() throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpRedirectTest.java b/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpRedirectTest.java index 0cabfe752d..5c81a71b85 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpRedirectTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/client/HttpRedirectTest.java @@ -17,7 +17,6 @@ import io.netty.channel.unix.DomainSocketAddress; import io.netty.handler.codec.http.HttpResponseStatus; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -37,7 +36,8 @@ import io.netty.handler.codec.http.cookie.DefaultCookie; import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.util.ReferenceCountUtil; import org.apache.commons.lang3.StringUtils; import org.jspecify.annotations.Nullable; @@ -63,11 +63,11 @@ class HttpRedirectTest extends BaseHttpTest { - static SelfSignedCertificate ssc; + static X509Bundle ssc; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @Test @@ -423,24 +423,26 @@ void testFollowRedirectPredicateThrowsException() { @Test @SuppressWarnings("deprecation") - void testIssue843() { + void testIssue843() throws Exception { final int server2Port = SocketUtils.findAvailableTcpPort(); DisposableServer server1 = null; DisposableServer server2 = null; try { + Http11SslContextSpec server1Ctx = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); server1 = createServer() - .secure(spec -> - spec.sslContext(Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))) + .secure(spec -> spec.sslContext(server1Ctx)) .handle((req, res) -> res.sendRedirect("https://localhost:" + server2Port)) .bindNow(); + Http11SslContextSpec server2Ctx = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); server2 = createServer(server2Port) .host("localhost") - .secure(spec -> - spec.sslContext(Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()))) + .secure(spec -> spec.sslContext(server2Ctx)) .handle((req, res) -> res.sendString(Mono.just("test"))) .bindNow(); @@ -476,8 +478,8 @@ void testIssue843() { @Test @SuppressWarnings("deprecation") - void testHttpRequestIfRedirectHttpToHttpsEnabled() { - Http11SslContextSpec sslContext = Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testHttpRequestIfRedirectHttpToHttpsEnabled() throws Exception { + Http11SslContextSpec sslContext = Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); disposableServer = createServer() .host("localhost") @@ -507,13 +509,14 @@ void testHttpRequestIfRedirectHttpToHttpsEnabled() { @Test @SuppressWarnings("deprecation") - void testHttpsRequestIfRedirectHttpToHttpsEnabled() { + void testHttpsRequestIfRedirectHttpToHttpsEnabled() throws Exception { String message = "The client should receive the message"; + Http11SslContextSpec serverCtx = + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); disposableServer = createServer() .host("localhost") - .secure(spec -> - spec.sslContext(Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey())), true) + .secure(spec -> spec.sslContext(serverCtx), true) .handle((request, response) -> response.sendString(Mono.just(message))) .bindNow(); Http11SslContextSpec http11SslContextSpec = @@ -569,13 +572,13 @@ void testRelativeRedirectKeepsScheme() { @Test @SuppressWarnings("deprecation") - void testLastLocationSetToResourceUrlOnRedirect() { + void testLastLocationSetToResourceUrlOnRedirect() throws Exception { final String redirectPath = "/redirect"; final String destinationPath = "/destination"; final String responseContent = "Success"; Http11SslContextSpec serverSslContextSpec = - Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); DisposableServer redirectServer = null; DisposableServer initialServer = null; try { @@ -682,8 +685,8 @@ void testHttpServerWithDomainSockets_HTTP11() { @Test @SuppressWarnings("deprecation") - void testHttpServerWithDomainSockets_HTTP2() { - Http11SslContextSpec serverCtx = Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testHttpServerWithDomainSockets_HTTP2() throws Exception { + Http11SslContextSpec serverCtx = Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http11SslContextSpec clientCtx = Http11SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -719,8 +722,8 @@ private void doTestHttpServerWithDomainSockets(HttpServer server, HttpClient cli @Test @SuppressWarnings("deprecation") - void testHttp2Redirect() { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testHttp2Redirect() throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/client/WebsocketTest.java b/reactor-netty-http/src/test/java/reactor/netty/http/client/WebsocketTest.java index 4ab1ed6aa0..76821eab0b 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/client/WebsocketTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/client/WebsocketTest.java @@ -16,7 +16,6 @@ package reactor.netty.http.client; import java.nio.charset.Charset; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -44,7 +43,8 @@ import io.netty.handler.codec.http.websocketx.WebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.util.CharsetUtil; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeAll; @@ -83,17 +83,17 @@ class WebsocketTest extends BaseHttpTest { static final Logger log = Loggers.getLogger(WebsocketTest.class); - static SelfSignedCertificate ssc; + static X509Bundle ssc; static Http11SslContextSpec serverCtx11; static Http2SslContextSpec serverCtx2; static Http11SslContextSpec clientCtx11; static Http2SslContextSpec clientCtx2; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); - serverCtx11 = Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); - serverCtx2 = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + serverCtx11 = Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); + serverCtx2 = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); clientCtx11 = Http11SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); clientCtx2 = Http2SslContextSpec.forClient() diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/observability/ObservabilitySmokeTest.java b/reactor-netty-http/src/test/java/reactor/netty/http/observability/ObservabilitySmokeTest.java index cf5aad3523..a129c2342c 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/observability/ObservabilitySmokeTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/observability/ObservabilitySmokeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2022-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package reactor.netty.http.observability; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.Deque; import java.util.List; @@ -39,7 +38,8 @@ import io.netty.buffer.Unpooled; import io.netty.handler.codec.http2.Http2StreamChannel; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import reactor.core.publisher.Flux; @@ -60,7 +60,7 @@ class ObservabilitySmokeTest extends SampleTestRunner { static byte[] content; static DisposableServer disposableServer; - static SelfSignedCertificate ssc; + static X509Bundle ssc; static MeterRegistry registry; @@ -69,8 +69,8 @@ class ObservabilitySmokeTest extends SampleTestRunner { } @BeforeAll - static void setUp() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void setUp() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); content = new byte[1024 * 8]; Random rndm = new Random(); rndm.nextBytes(content); @@ -111,7 +111,7 @@ public BiConsumer { - Http2SslContextSpec serverCtxHttp = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtxHttp = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); disposableServer = HttpServer.create() .metrics(true, s -> s.replace("1", "{id}")) diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/server/ConnectionInfoTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/server/ConnectionInfoTests.java index f127c10181..99b1a40301 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/server/ConnectionInfoTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/server/ConnectionInfoTests.java @@ -17,7 +17,6 @@ import java.net.InetSocketAddress; import java.nio.charset.Charset; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeUnit; @@ -26,8 +25,6 @@ import java.util.function.Function; import java.util.stream.Stream; -import javax.net.ssl.SSLException; - import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaders; @@ -36,7 +33,8 @@ import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.assertj.core.api.Assertions; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeAll; @@ -70,7 +68,7 @@ */ class ConnectionInfoTests extends BaseHttpTest { - static SelfSignedCertificate ssc; + static X509Bundle ssc; protected HttpClient customizeClientOptions(HttpClient httpClient) { return httpClient; @@ -81,8 +79,8 @@ protected HttpServer customizeServerOptions(HttpServer httpServer) { } @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } static Stream forwardedProtoOnlyParams() { @@ -514,10 +512,10 @@ void xForwardedForMultipleHostAndPortAndProto(boolean useCustomForwardedHandler) @ParameterizedTest @ValueSource(booleans = {true, false}) - void xForwardedForAndPortOnly(boolean useCustomForwardedHandler) throws SSLException { + void xForwardedForAndPortOnly(boolean useCustomForwardedHandler) throws Exception { SslContext clientSslContext = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE).build(); - SslContext serverSslContext = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + SslContext serverSslContext = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); testClientRequest( clientRequestHeaders -> { @@ -722,10 +720,10 @@ void proxyProtocolAuto() throws InterruptedException { } @Test - void https() throws SSLException { + void https() throws Exception { SslContext clientSslContext = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE).build(); - SslContext serverSslContext = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + SslContext serverSslContext = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); testClientRequest( clientRequestHeaders -> {}, @@ -737,10 +735,10 @@ void https() throws SSLException { // Users may add SslHandler themselves, not by using `httpServer.secure` @Test - void httpsUserAddedSslHandler() throws SSLException { + void httpsUserAddedSslHandler() throws Exception { SslContext clientSslContext = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE).build(); - SslContext serverSslContext = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + SslContext serverSslContext = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); testClientRequest( clientRequestHeaders -> {}, diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/server/Http2ConnectionInfoTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/server/Http2ConnectionInfoTests.java index 97f96f8e31..1ef2619594 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/server/Http2ConnectionInfoTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/server/Http2ConnectionInfoTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2023 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2020-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,11 +46,11 @@ protected HttpClient customizeClientOptions(HttpClient httpClient) { @Override protected HttpServer customizeServerOptions(HttpServer httpServer) { try { - SslContext ctx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + SslContext ctx = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); return httpServer.protocol(HttpProtocol.H2) .secure(ssl -> ssl.sslContext(ctx)); } - catch (SSLException e) { + catch (Exception e) { throw new RuntimeException(e); } } diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerPostFormTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerPostFormTests.java index 48c2a4ecfb..4abe2f6ed3 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerPostFormTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerPostFormTests.java @@ -19,7 +19,8 @@ import io.netty.buffer.Unpooled; import io.netty.handler.codec.http.multipart.HttpData; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.jspecify.annotations.Nullable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -69,8 +70,8 @@ class HttpServerPostFormTests extends BaseHttpTest { @SuppressWarnings("deprecation") static Object[][] data() throws Exception { - SelfSignedCertificate cert = new SelfSignedCertificate(); - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(cert.certificate(), cert.privateKey()); + X509Bundle cert = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java index 196d1f8368..a006a2be99 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java @@ -26,7 +26,6 @@ import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.cert.CertificateException; import java.time.Duration; import java.time.ZonedDateTime; import java.util.ArrayList; @@ -102,7 +101,8 @@ import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.SslHandshakeTimeoutException; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.util.AttributeKey; import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCounted; @@ -178,7 +178,7 @@ */ class HttpServerTests extends BaseHttpTest { - static SelfSignedCertificate ssc; + static X509Bundle ssc; static final EventExecutor executor = new DefaultEventExecutor(); static final Logger log = Loggers.getLogger(HttpServerTests.class); static final String DATA_STRING = String.join("", Collections.nCopies(128, "X")); @@ -267,8 +267,8 @@ public void flush(ChannelHandlerContext ctx) { } @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @AfterAll @@ -1251,7 +1251,7 @@ void testIssue630() { @Test @SuppressWarnings("FutureReturnValueIgnored") void testExpectErrorWhenConnectionClosed() throws Exception { - SslContext serverCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) + SslContext serverCtx = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .build(); AtomicReference error = new AtomicReference<>(); CountDownLatch latch = new CountDownLatch(1); @@ -1841,7 +1841,7 @@ void testGracefulShutdownH2C(HttpProtocol[] serverProtocols, HttpProtocol[] clie @MethodSource("h2CompatibleCombinations") @SuppressWarnings("deprecation") void testGracefulShutdownH2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2031,8 +2031,8 @@ void testHttpServerWithDomainSockets_HTTP11Post() { @Test @SuppressWarnings("deprecation") - void testHttpServerWithDomainSockets_HTTP2Get() { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testHttpServerWithDomainSockets_HTTP2Get() throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2044,8 +2044,8 @@ void testHttpServerWithDomainSockets_HTTP2Get() { @Test @SuppressWarnings("deprecation") - void testHttpServerWithDomainSockets_HTTP2Post() { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testHttpServerWithDomainSockets_HTTP2Post() throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2326,19 +2326,19 @@ void testIssue3473Http2(HttpProtocol[] serverProtocols, HttpProtocol[] clientPro @SuppressWarnings("deprecation") private void doTestSniSupport(Function serverCustomizer, Function clientCustomizer) throws Exception { - SelfSignedCertificate defaultCert = new SelfSignedCertificate("default"); - SelfSignedCertificate testCert = new SelfSignedCertificate("test.com"); + X509Bundle defaultCert = new CertificateBuilder().subject("CN=default").setIsCertificateAuthority(true).buildSelfSigned(); + X509Bundle testCert = new CertificateBuilder().subject("CN=test.com").setIsCertificateAuthority(true).buildSelfSigned(); AtomicReference hostname = new AtomicReference<>(); HttpServer server = serverCustomizer.apply(createServer()); boolean isH2 = (server.configuration()._protocols & HttpServerConfig.h2) == HttpServerConfig.h2; SslProvider.ProtocolSslContextSpec defaultSslContextBuilder = isH2 ? - Http2SslContextSpec.forServer(defaultCert.certificate(), defaultCert.privateKey()) : - Http11SslContextSpec.forServer(defaultCert.certificate(), defaultCert.privateKey()); + Http2SslContextSpec.forServer(defaultCert.toTempCertChainPem(), defaultCert.toTempPrivateKeyPem()) : + Http11SslContextSpec.forServer(defaultCert.toTempCertChainPem(), defaultCert.toTempPrivateKeyPem()); SslProvider.ProtocolSslContextSpec testSslContextBuilder = isH2 ? - Http2SslContextSpec.forServer(testCert.certificate(), testCert.privateKey()) : - Http11SslContextSpec.forServer(testCert.certificate(), testCert.privateKey()); + Http2SslContextSpec.forServer(testCert.toTempCertChainPem(), testCert.toTempPrivateKeyPem()) : + Http11SslContextSpec.forServer(testCert.toTempCertChainPem(), testCert.toTempPrivateKeyPem()); disposableServer = server.secure(spec -> spec.sslContext(defaultSslContextBuilder) @@ -2388,19 +2388,19 @@ void testSniSupportAsyncMappingsHttp2(HttpProtocol[] serverProtocols, HttpProtoc @SuppressWarnings("deprecation") private void doTestSniSupportAsyncMappings(Function serverCustomizer, Function clientCustomizer) throws Exception { - SelfSignedCertificate defaultCert = new SelfSignedCertificate("default"); - SelfSignedCertificate testCert = new SelfSignedCertificate("test.com"); + X509Bundle defaultCert = new CertificateBuilder().subject("CN=default").setIsCertificateAuthority(true).buildSelfSigned(); + X509Bundle testCert = new CertificateBuilder().subject("CN=test.com").setIsCertificateAuthority(true).buildSelfSigned(); AtomicReference hostname = new AtomicReference<>(); HttpServer server = serverCustomizer.apply(createServer()); boolean isH2 = (server.configuration()._protocols & HttpServerConfig.h2) == HttpServerConfig.h2; SslProvider.ProtocolSslContextSpec defaultSslContextBuilder = isH2 ? - Http2SslContextSpec.forServer(defaultCert.certificate(), defaultCert.privateKey()) : - Http11SslContextSpec.forServer(defaultCert.certificate(), defaultCert.privateKey()); + Http2SslContextSpec.forServer(defaultCert.toTempCertChainPem(), defaultCert.toTempPrivateKeyPem()) : + Http11SslContextSpec.forServer(defaultCert.toTempCertChainPem(), defaultCert.toTempPrivateKeyPem()); SslProvider.ProtocolSslContextSpec testSslContextBuilder = isH2 ? - Http2SslContextSpec.forServer(testCert.certificate(), testCert.privateKey()) : - Http11SslContextSpec.forServer(testCert.certificate(), testCert.privateKey()); + Http2SslContextSpec.forServer(testCert.toTempCertChainPem(), testCert.toTempPrivateKeyPem()) : + Http11SslContextSpec.forServer(testCert.toTempCertChainPem(), testCert.toTempPrivateKeyPem()); SslProvider testSslProvider = SslProvider.builder().sslContext(testSslContextBuilder).build(); disposableServer = @@ -2439,9 +2439,9 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { @Test @SuppressWarnings("deprecation") - void testSniSupportHandshakeTimeout() { + void testSniSupportHandshakeTimeout() throws Exception { Http11SslContextSpec defaultSslContextBuilder = - Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http11SslContextSpec clientSslContextBuilder = Http11SslContextSpec.forClient() @@ -2519,7 +2519,7 @@ void testIssue1286_ServerHTTP11AndH2CClientHTTP11AndH2C() throws Exception { @Test @SuppressWarnings("deprecation") void testIssue1286_H2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2532,7 +2532,7 @@ void testIssue1286_H2() throws Exception { @Test @SuppressWarnings("deprecation") void testIssue1286_ServerHTTP11AndH2ClientH2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2545,7 +2545,7 @@ void testIssue1286_ServerHTTP11AndH2ClientH2() throws Exception { @Test @SuppressWarnings("deprecation") void testIssue1286_ServerHTTP11AndH2ClientHTTP11AndH2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2588,7 +2588,7 @@ void testIssue1286ErrorResponse_ServerHTTP11AndH2CClientHTTP11AndH2C() throws Ex @Test @SuppressWarnings("deprecation") void testIssue1286ErrorResponse_H2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2601,7 +2601,7 @@ void testIssue1286ErrorResponse_H2() throws Exception { @Test @SuppressWarnings("deprecation") void testIssue1286ErrorResponse_ServerHTTP11AndH2ClientH2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2614,7 +2614,7 @@ void testIssue1286ErrorResponse_ServerHTTP11AndH2ClientH2() throws Exception { @Test @SuppressWarnings("deprecation") void testIssue1286ErrorResponse_ServerHTTP11AndH2ClientHTTP11AndH2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2657,7 +2657,7 @@ void testIssue1286ConnectionClose_ServerHTTP11AndH2CClientHTTP11AndH2C() throws @Test @SuppressWarnings("deprecation") void testIssue1286ConnectionClose_H2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2670,7 +2670,7 @@ void testIssue1286ConnectionClose_H2() throws Exception { @Test @SuppressWarnings("deprecation") void testIssue1286ConnectionClose_ServerHTTP11AndH2ClientH2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2683,7 +2683,7 @@ void testIssue1286ConnectionClose_ServerHTTP11AndH2ClientH2() throws Exception { @Test @SuppressWarnings("deprecation") void testIssue1286ConnectionClose_ServerHTTP11AndH2ClientHTTP11AndH2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2726,7 +2726,7 @@ void testIssue1286ConnectionCloseErrorResponse_ServerHTTP11AndH2CClientHTTP11And @Test @SuppressWarnings("deprecation") void testIssue1286ConnectionCloseErrorResponse_H2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2739,7 +2739,7 @@ void testIssue1286ConnectionCloseErrorResponse_H2() throws Exception { @Test @SuppressWarnings("deprecation") void testIssue1286ConnectionCloseErrorResponse_ServerHTTP11AndH2ClientH2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2752,7 +2752,7 @@ void testIssue1286ConnectionCloseErrorResponse_ServerHTTP11AndH2ClientH2() throw @Test @SuppressWarnings("deprecation") void testIssue1286ConnectionCloseErrorResponse_ServerHTTP11AndH2ClientHTTP11AndH2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -2935,17 +2935,17 @@ private void doTestIdleTimeout(boolean applyTimeout) throws Exception { } @Test - void testIdleTimeout_DelayFirstRequest_NoSSL() { + void testIdleTimeout_DelayFirstRequest_NoSSL() throws Exception { doTestIdleTimeout_DelayFirstRequest(false); } @Test - void testIdleTimeout_DelayFirstRequest() { + void testIdleTimeout_DelayFirstRequest() throws Exception { doTestIdleTimeout_DelayFirstRequest(true); } @SuppressWarnings("deprecation") - private void doTestIdleTimeout_DelayFirstRequest(boolean withSecurity) { + private void doTestIdleTimeout_DelayFirstRequest(boolean withSecurity) throws Exception { HttpServer server = createServer() .idleTimeout(Duration.ofMillis(200)) @@ -2956,7 +2956,7 @@ private void doTestIdleTimeout_DelayFirstRequest(boolean withSecurity) { .disableRetry(true); if (withSecurity) { - Http11SslContextSpec serverCtx = Http11SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http11SslContextSpec serverCtx = Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http11SslContextSpec clientCtx = Http11SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -3344,7 +3344,7 @@ void testIssue1978H2CWithDelay(HttpProtocol[] serverProtocols, HttpProtocol[] cl @ParameterizedTest @MethodSource("h2CompatibleCombinations") void testIssue1978H2NoDelay(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -3354,7 +3354,7 @@ void testIssue1978H2NoDelay(HttpProtocol[] serverProtocols, HttpProtocol[] clien @ParameterizedTest @MethodSource("h2CompatibleCombinations") void testIssue1978H2WithDelay(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -3425,7 +3425,7 @@ private void doTestIssue1978( */ @Test void test2498_close_notify_after_response_two_clients() throws Exception { - SslContext serverCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) + SslContext serverCtx = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .build(); // Ensure that the server has sent the close_notify, and the client connection is closed after the 1st response. @@ -3490,7 +3490,7 @@ void test2498_close_notify_after_response_two_clients() throws Exception { */ @Test void test2498_close_notify_on_request() throws Exception { - SslContext serverCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) + SslContext serverCtx = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .build(); CountDownLatch latch = new CountDownLatch(1); @@ -3546,7 +3546,7 @@ void test2498_close_notify_on_request() throws Exception { */ @Test void test2498_close_notify_on_connect() throws Exception { - SslContext serverCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) + SslContext serverCtx = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()) .build(); CountDownLatch latch = new CountDownLatch(1); @@ -3716,8 +3716,8 @@ void testHttpServerCancelledOnClientClose() throws InterruptedException { @ParameterizedTest @MethodSource("h2CompatibleCombinations") @SuppressWarnings("deprecation") - void testIssue2760_H2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testIssue2760_H2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -3784,8 +3784,8 @@ private void doTestIssue2760(HttpServer server, HttpClient client) { @ParameterizedTest @MethodSource("h2CompatibleCombinations") @SuppressWarnings("deprecation") - void testIssue2927_H2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testIssue2927_H2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpsSendFileTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpsSendFileTests.java index 5f68d4f4d4..c0a2cad814 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpsSendFileTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/server/HttpsSendFileTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2018-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,32 +15,32 @@ */ package reactor.netty.http.server; -import java.security.cert.CertificateException; import javax.net.ssl.SSLException; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.junit.jupiter.api.BeforeAll; import reactor.netty.http.client.HttpClient; class HttpsSendFileTests extends HttpSendFileTests { - static SelfSignedCertificate ssc; + static X509Bundle ssc; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @Override protected HttpServer customizeServerOptions(HttpServer server) { try { - SslContext ctx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build(); + SslContext ctx = SslContextBuilder.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()).build(); return server.secure(ssl -> ssl.sslContext(ctx)); } - catch (SSLException e) { + catch (Exception e) { throw new RuntimeException(e); } } diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/server/logging/error/ErrorLogTest.java b/reactor-netty-http/src/test/java/reactor/netty/http/server/logging/error/ErrorLogTest.java index 1a2ca14c36..e4f5d64edb 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/server/logging/error/ErrorLogTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/server/logging/error/ErrorLogTest.java @@ -16,7 +16,8 @@ package reactor.netty.http.server.logging.error; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import reactor.core.publisher.Flux; @@ -201,12 +202,12 @@ private static void getHttpClientResponse(HttpClient client, String uri) { @SuppressWarnings("deprecation") static Object[][] httpProtocolsCompatibleCombinations() throws Exception { - SelfSignedCertificate cert = new SelfSignedCertificate(); - Http11SslContextSpec serverCtxHttp11 = Http11SslContextSpec.forServer(cert.certificate(), cert.privateKey()); + X509Bundle cert = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + Http11SslContextSpec serverCtxHttp11 = Http11SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); Http11SslContextSpec clientCtxHttp11 = Http11SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); - Http2SslContextSpec serverCtxHttp2 = Http2SslContextSpec.forServer(cert.certificate(), cert.privateKey()); + Http2SslContextSpec serverCtxHttp2 = Http2SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); Http2SslContextSpec clientCtxHttp2 = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/resources/DefaultPooledConnectionProviderTest.java b/reactor-netty-http/src/test/java/reactor/netty/resources/DefaultPooledConnectionProviderTest.java index 5eb3447b09..86748ea1f0 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/resources/DefaultPooledConnectionProviderTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/resources/DefaultPooledConnectionProviderTest.java @@ -33,7 +33,8 @@ import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslProvider; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.apache.commons.lang3.StringUtils; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterEach; @@ -66,7 +67,6 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.Arrays; import java.util.List; @@ -93,13 +93,13 @@ class DefaultPooledConnectionProviderTest extends BaseHttpTest { - static SelfSignedCertificate ssc; + static X509Bundle ssc; private MeterRegistry registry; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @BeforeEach @@ -117,8 +117,8 @@ void tearDown() { @Test @SuppressWarnings("deprecation") - void testIssue903() { - Http11SslContextSpec serverCtx = Http11SslContextSpec.forServer(ssc.key(), ssc.cert()); + void testIssue903() throws Exception { + Http11SslContextSpec serverCtx = Http11SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); disposableServer = createServer() .secure(s -> s.sslContext(serverCtx)) @@ -335,7 +335,7 @@ public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, @Test @SuppressWarnings("deprecation") void testConnectionIdleWhenNoActiveStreams() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -494,7 +494,7 @@ void testIssue1982H2C(HttpProtocol[] serverProtocols, HttpProtocol[] clientProto @ParameterizedTest @MethodSource("h2CompatibleCombinations") void testIssue1982H2(HttpProtocol[] serverProtocols, HttpProtocol[] clientProtocols) throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -578,7 +578,7 @@ private void doTestIssue1982(HttpProtocol[] serverProtocols, HttpProtocol[] clie @Test @SuppressWarnings("deprecation") void testMinConnections() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -836,8 +836,8 @@ private double getGaugeValue(String gaugeName, String... tags) { @Test @SuppressWarnings({"FutureReturnValueIgnored", "deprecation"}) - void testHttp2PoolAndGoAway() { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + void testHttp2PoolAndGoAway() throws Exception { + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/resources/PooledConnectionProviderDefaultMetricsTest.java b/reactor-netty-http/src/test/java/reactor/netty/resources/PooledConnectionProviderDefaultMetricsTest.java index 145444a8c1..dc122ce0dc 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/resources/PooledConnectionProviderDefaultMetricsTest.java +++ b/reactor-netty-http/src/test/java/reactor/netty/resources/PooledConnectionProviderDefaultMetricsTest.java @@ -23,7 +23,8 @@ import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -40,7 +41,6 @@ import reactor.netty.http.server.HttpServer; import reactor.test.StepVerifier; -import java.security.cert.CertificateException; import java.time.Duration; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ThreadLocalRandom; @@ -77,13 +77,13 @@ */ class PooledConnectionProviderDefaultMetricsTest extends BaseHttpTest { - static SelfSignedCertificate ssc; + static X509Bundle ssc; private MeterRegistry registry; @BeforeAll - static void createSelfSignedCertificate() throws CertificateException { - ssc = new SelfSignedCertificate(); + static void createSelfSignedCertificate() throws Exception { + ssc = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); } @BeforeEach @@ -118,7 +118,7 @@ void testConnectionProviderMetricsDisabledAndHttpClientMetricsEnabledHttp1() thr void testConnectionProviderMetricsDisabledAndHttpClientMetricsEnabledHttp2() throws Exception { // by default, when the max number of pending acquire is not specified, it will bet set to 2 * max-connection // (see PoolFactory from PoolConnectionProvider.java) - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -155,7 +155,7 @@ void testConnectionProviderMetricsEnableAndHttpClientMetricsDisabledHttp1() thro @Test @SuppressWarnings("deprecation") void testConnectionProviderMetricsEnableAndHttpClientMetricsDisabledHttp2() throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); @@ -246,7 +246,7 @@ private void doTest(HttpServer server, HttpClient client, String poolName, boole @ValueSource(longs = {0, 50, 500}) @SuppressWarnings("deprecation") void testConnectionPoolPendingAcquireSize(long disposeTimeoutMillis) throws Exception { - Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.certificate(), ssc.privateKey()); + Http2SslContextSpec serverCtx = Http2SslContextSpec.forServer(ssc.toTempCertChainPem(), ssc.toTempPrivateKeyPem()); Http2SslContextSpec clientCtx = Http2SslContextSpec.forClient() .configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE)); diff --git a/reactor-netty-http/src/test/java/reactor/netty/tcp/SslProviderTests.java b/reactor-netty-http/src/test/java/reactor/netty/tcp/SslProviderTests.java index a60bf9c471..81e5a9062e 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/tcp/SslProviderTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/tcp/SslProviderTests.java @@ -32,7 +32,8 @@ import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import io.netty.util.concurrent.GlobalEventExecutor; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeAll; @@ -59,9 +60,9 @@ * @author Violeta Georgieva */ class SslProviderTests extends BaseHttpTest { - static SelfSignedCertificate cert; - static SelfSignedCertificate localhostCert; - static SelfSignedCertificate anotherCert; + static X509Bundle cert; + static X509Bundle localhostCert; + static X509Bundle anotherCert; private List protocols; private @Nullable SslContext sslContext; @@ -74,22 +75,22 @@ class SslProviderTests extends BaseHttpTest { @BeforeAll static void createSelfSignedCertificate() throws Exception { - cert = new SelfSignedCertificate("default"); - localhostCert = new SelfSignedCertificate("localhost"); - anotherCert = new SelfSignedCertificate("another"); + cert = new CertificateBuilder().subject("CN=default").setIsCertificateAuthority(true).buildSelfSigned(); + localhostCert = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + anotherCert = new CertificateBuilder().subject("CN=another").setIsCertificateAuthority(true).buildSelfSigned(); } @BeforeEach void setUp() throws Exception { - serverSslContextBuilder = Http11SslContextSpec.forServer(cert.certificate(), cert.privateKey()); - serverSslContextBuilderH2 = Http2SslContextSpec.forServer(cert.certificate(), cert.privateKey()); + serverSslContextBuilder = Http11SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); + serverSslContextBuilderH2 = Http2SslContextSpec.forServer(cert.toTempCertChainPem(), cert.toTempPrivateKeyPem()); localhostSslContext = - Http11SslContextSpec.forServer(localhostCert.certificate(), localhostCert.privateKey()) + Http11SslContextSpec.forServer(localhostCert.toTempCertChainPem(), localhostCert.toTempPrivateKeyPem()) .sslContext(); anotherSslContext = - Http11SslContextSpec.forServer(anotherCert.certificate(), anotherCert.privateKey()) + Http11SslContextSpec.forServer(anotherCert.toTempCertChainPem(), anotherCert.toTempPrivateKeyPem()) .sslContext(); clientSslContextBuilder = diff --git a/reactor-netty-incubator-quic/build.gradle b/reactor-netty-incubator-quic/build.gradle index 82e96deed3..cc4c2057b8 100644 --- a/reactor-netty-incubator-quic/build.gradle +++ b/reactor-netty-incubator-quic/build.gradle @@ -45,6 +45,7 @@ dependencies { testImplementation "org.assertj:assertj-core:$assertJVersion" testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" testImplementation "io.projectreactor:reactor-test:$testAddonVersion" + testImplementation "io.netty:netty-pkitesting:$nettyVersion" testRuntimeOnly "org.junit.platform:junit-platform-launcher:$junitPlatformLauncherVersion" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" diff --git a/reactor-netty-incubator-quic/src/test/java/reactor/netty/incubator/quic/BaseQuicTests.java b/reactor-netty-incubator-quic/src/test/java/reactor/netty/incubator/quic/BaseQuicTests.java index a0e13b126c..9fa835438d 100644 --- a/reactor-netty-incubator-quic/src/test/java/reactor/netty/incubator/quic/BaseQuicTests.java +++ b/reactor-netty-incubator-quic/src/test/java/reactor/netty/incubator/quic/BaseQuicTests.java @@ -16,10 +16,11 @@ package reactor.netty.incubator.quic; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; import io.netty.incubator.codec.quic.InsecureQuicTokenHandler; import io.netty.incubator.codec.quic.QuicSslContext; import io.netty.incubator.codec.quic.QuicSslContextBuilder; +import io.netty.pkitesting.CertificateBuilder; +import io.netty.pkitesting.X509Bundle; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterEach; import reactor.netty.Connection; @@ -42,26 +43,26 @@ class BaseQuicTests { static final QuicSslContext clientCtx; static final QuicSslContext serverCtx; - static final SelfSignedCertificate ssc; + static final X509Bundle ssc; static { - SelfSignedCertificate cert; + X509Bundle cert; try { - cert = new SelfSignedCertificate(); + cert = new CertificateBuilder().subject("CN=localhost").setIsCertificateAuthority(true).buildSelfSigned(); + ssc = cert; + + clientCtx = + QuicSslContextBuilder.forClient() + .trustManager(InsecureTrustManagerFactory.INSTANCE) + .applicationProtocols(PROTOCOL) + .build(); + serverCtx = + QuicSslContextBuilder.forServer(ssc.toTempPrivateKeyPem(), null, ssc.toTempCertChainPem()) + .applicationProtocols(PROTOCOL) + .build(); } catch (Exception e) { throw new ExceptionInInitializerError(e); } - ssc = cert; - - clientCtx = - QuicSslContextBuilder.forClient() - .trustManager(InsecureTrustManagerFactory.INSTANCE) - .applicationProtocols(PROTOCOL) - .build(); - serverCtx = - QuicSslContextBuilder.forServer(ssc.privateKey(), null, ssc.certificate()) - .applicationProtocols(PROTOCOL) - .build(); } protected @Nullable QuicConnection client; diff --git a/reactor-netty-incubator-quic/src/test/java/reactor/netty/incubator/quic/QuicServerTests.java b/reactor-netty-incubator-quic/src/test/java/reactor/netty/incubator/quic/QuicServerTests.java index 0098805a7b..6373567410 100644 --- a/reactor-netty-incubator-quic/src/test/java/reactor/netty/incubator/quic/QuicServerTests.java +++ b/reactor-netty-incubator-quic/src/test/java/reactor/netty/incubator/quic/QuicServerTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 VMware, Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2021-2025 VMware, Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -292,7 +292,7 @@ void testSniSupportMatches() throws Exception { private void testSniSupport(Function sslEngineProvider, String expectedAppProtocol, String expectedHostname) throws Exception { QuicSslContext sniServerCtx = - QuicSslContextBuilder.forServer(ssc.privateKey(), null, ssc.certificate()) + QuicSslContextBuilder.forServer(ssc.toTempPrivateKeyPem(), null, ssc.toTempCertChainPem()) .applicationProtocols("http/1.1") .build(); From 731feb65bd0310a82d3ee1601234791c017e9ac8 Mon Sep 17 00:00:00 2001 From: Violeta Georgieva <696661+violetagg@users.noreply.github.com> Date: Wed, 14 May 2025 11:40:08 +0300 Subject: [PATCH 8/8] [test] debug Signed-off-by: Violeta Georgieva <696661+violetagg@users.noreply.github.com> --- .github/workflows/check_transport.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/check_transport.yml b/.github/workflows/check_transport.yml index 4f4bf867ea..2637d9d6c8 100644 --- a/.github/workflows/check_transport.yml +++ b/.github/workflows/check_transport.yml @@ -75,3 +75,9 @@ jobs: - name: Build and test UDS with NIO on Java 17 if: ${{ ! startsWith(matrix.os, 'windows') }} run: ./gradlew reactor-netty-http:test --tests reactor.netty.http.server.HttpServerTests.testHttpServerWithDomainSockets_HTTP11Post -PtestToolchain=17 --no-daemon -x spotlessCheck -PforceTransport=nio + - name: Archive tests output + if: failure() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 + with: + name: tests_output_${{ matrix.os }}_${{ matrix.transport }} + path: reactor-netty-http/build/test-results/test/binary/output.bin