Support for HTTP/3 (server side)#20017
Conversation
|
❌ Gradle check result for 696b321: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
❌ Gradle check result for cdec169: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
❌ Gradle check result for f3c98e0: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
❌ Gradle check result for 7a00bdf: null Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
❕ Gradle check result for 4eafd49: UNSTABLE Please review all flaky tests that succeeded after retry and create an issue if one does not already exist to track the flaky failure. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #20017 +/- ##
============================================
+ Coverage 73.28% 73.33% +0.05%
- Complexity 71723 71828 +105
============================================
Files 5785 5792 +7
Lines 328137 328507 +370
Branches 47270 47302 +32
============================================
+ Hits 240465 240912 +447
+ Misses 68397 68246 -151
- Partials 19275 19349 +74 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
📝 WalkthroughWalkthroughAdds optional server-side HTTP/3/QUIC support: new Netty HTTP/3/QUIC dependencies, runtime availability probes, Netty4 and Reactor Netty HTTP/3 transports and utilities, composite transports/channels, settings and protocol mapping, many test, build, and audit updates. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
rect rgb(250,250,250)
participant Client as HTTP/3 Client
participant UDP as UDP/QUIC Socket
participant QuicServer as QUIC Server Bootstrap
participant Stream as QuicStreamChannel
participant Pipeline as Per‑stream Pipeline
participant Transport as HTTP/3 Transport
participant App as Application Handler
end
Client->>UDP: UDP connect + QUIC/TLS handshake
UDP->>QuicServer: accepted QUIC connection (QuicSslContext)
QuicServer->>Stream: open QUIC stream -> ChannelInitializer
Stream->>Pipeline: install HTTP/3 codecs, verifier, aggregator
Client->>Stream: send HTTP/3 request frames
Pipeline->>Transport: convert frames -> Netty4HttpRequest
Transport->>App: dispatch request
App-->>Transport: produce FullHttpResponse
Transport->>Stream: write response frames
Stream->>Client: responses over QUIC/UDP
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (6)
server/src/main/java/org/opensearch/bootstrap/Security.java (1)
132-134: Regex update correctly handles OS-prefixed classifiers; verify any dependence on old@x86_64suffixesThe new
CODEBASE_JAR_WITH_CLASSIFIERpattern:private static final Pattern CODEBASE_JAR_WITH_CLASSIFIER = Pattern.compile( "^(.+)-\\d+\\.\\d+[^-]*.*?[-]?((?:linux-|windows-|osx-)?[^-]+)?\\.jar$" );behaves as intended for the key cases:
- Plain version jars like
lucene-core-9.11.0.jarstill yieldmatcher.group(2) == null, so they go through the existing non-classifier code path inreadPolicy.- Snapshot/classifier jars such as
lucene-core-9.11.0-snapshot-8a555eb.jarandzstd-jni-1.5.6-1.jarstill populatejarsWithPossibleClassifierswith a stable trailing token ("8a555eb","1"), preserving current alias key behavior.- OS-specific jars like
netty-codec-native-quic-4.2.7.Final-linux-x86_64.jarnow producematcher.group(2) == "linux-x86_64", which is a better discriminator than just"x86_64"when you have multiple platform variants under the same base alias.Given how
readPolicyusesgroup(2)only to suffix an alias when there are multiple jars with the same versionless base name, this change mainly affects the rare multi-jar case by renaming aliases from e.g.codebase.netty-…@x86_64tocodebase.netty-…@linux-x86_64/@windows-x86_64/@osx-x86_64. Existing usages of:
- Full jar-name properties (
codebase.<full-jar-name>.jar), and- The base alias without
@…remain unchanged.
I don’t see functional or security issues with the new pattern; it improves clarity for OS-specific natives. Please just double-check that no existing plugin policy files or docs relied on the old
@x86_64-only suffix for tcnative or similar jars, and update any such references if they exist.Also applies to: 249-286
plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java (1)
289-339: Consider making HTTP/3-specific settings configurable and reducing code duplication.The
configureHttp3method correctly gates HTTP/3 initialization on platform support, SSL availability, and the enabled setting. However, there are a few concerns:
Hardcoded HTTP/3 settings (lines 326-330): The idle timeout (5 seconds), max data, stream data, and max streams are hardcoded. Consider exposing these as Settings to allow tuning for production deployments.
Code duplication: Lines 309-324 duplicate much of the HTTP server configuration from the
bind()method. Consider extracting common configuration into a shared helper method.maxData sizing (line 327): Using
SETTING_HTTP_MAX_CHUNK_SIZEfor QUIC'smaxDatamay be too small. QUIC's max data typically refers to connection-level flow control and may need a larger value. Verify this is appropriate.For the hardcoded settings, consider adding new Settings like:
+public static final Setting<TimeValue> SETTING_HTTP3_IDLE_TIMEOUT = Setting.timeSetting( + "http.protocol.http3.idle_timeout", + TimeValue.timeValueSeconds(5), + Property.NodeScope +);plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java (1)
299-302: Consider simplifying the HTTP/3 setting propagation in testBindUnavailableAddress.The logic correctly propagates HTTP/3 settings through the tests. Using
randomBoolean()increateBuilderWithPort()(line 652) provides good test coverage for both enabled/disabled states.However, lines 299-302 are somewhat verbose. Consider a more concise approach:
- .put( - HttpTransportSettings.SETTING_HTTP_HTTP3_ENABLED.getKey(), - HttpTransportSettings.SETTING_HTTP_HTTP3_ENABLED.get(initialSettings) - ) + .put(HttpTransportSettings.SETTING_HTTP_HTTP3_ENABLED.getKey(), + HttpTransportSettings.SETTING_HTTP_HTTP3_ENABLED.get(initialSettings))Also applies to: 454-456, 650-652
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (2)
96-101: Refine HTTP/3 SSL context configuration to align with HTTP/1.1 and HTTP/2 branchesThe overall branching in
createClientbyprotocolis sound, but the HTTP/3 branch differs slightly from the HTTP/1.1 and HTTP/2 paths and can be tightened up:
For HTTP/1.1 and HTTP/2 you use
Http11SslContextSpec.forClient()/Http2SslContextSpec.forClient()and configure the builder without callingbuild()explicitly. In the HTTP/3 branch you callbuild()inside theconfigurelambda:Http3SslContextSpec.forClient() .configure(s -> s.trustManager(InsecureTrustManagerFactory.INSTANCE).build())which likely causes an extra
SslContextto be created and discarded and is inconsistent with the other branches.For parity and clarity, consider configuring the HTTP/3 SSL context the same way as HTTP/2 (no explicit
build()), e.g.:- spec -> spec.sslContext( - Http3SslContextSpec.forClient().configure(s -> s.trustManager(InsecureTrustManagerFactory.INSTANCE).build()) - ).handshakeTimeout(Duration.ofSeconds(30)) + spec -> spec.sslContext( + Http3SslContextSpec.forClient() + .configure(s -> s.trustManager(InsecureTrustManagerFactory.INSTANCE)) + ).handshakeTimeout(Duration.ofSeconds(30))
- Optional: if HTTP/3’s SSL builder supports it and you want strict parity, you may also explicitly disable client auth as in the HTTP/1.1/2 branches.
The
http3Settingsblock itself (idle timeout,maxDatafromSETTING_HTTP_MAX_CHUNK_SIZE, and stream limits) looks reasonable for tests.Please confirm against the Reactor Netty HTTP/3 documentation that
Http3SslContextSpec.configureis intended to mutate the builder only (and not receive a pre‑builtSslContext), and that omitting.build()here behaves as expected.Also applies to: 282-315, 317-321
77-79: Protocol selection viarandomProtocolis reasonable, but be aware of test behavior and internal API usageThe new
protocolfield andrandomProtocol(secure, settings)give eachReactorHttpClientinstance a stable, randomly chosen HTTP protocol, extended to include HTTP/3 when:
- the connection is secure,
Http3.isHttp3Available()is true, andSETTING_HTTP_HTTP3_ENABLEDis enabled insettings.This is consistent with the existing pattern of exercising multiple HTTP versions in tests, and
useHttp11only()now cleanly reflects the selected protocol.Two minor points to keep in mind:
Test determinism – With HTTP/3 enabled, roughly 1/3 of clients will use HTTP/3. If any tests assume strictly HTTP/1.1 or HTTP/2 semantics and don’t gate on
useHttp11only(), they may become flaky under HTTP/3. Worth sanity‑checking the call sites.Internal API dependency –
reactor.netty.http.internal.Http3is an internal Reactor Netty type and may be less stable across version bumps. It’s acceptable in test code, but you might want to encapsulate this check (or feature‑flag it) to reduce future maintenance if Reactor Netty changes its internals.No blockers, just things to be consciously relying on.
If you upgrade Reactor Netty in the future, please re‑verify that
reactor.netty.http.internal.Http3.isHttp3Available()still exists and behaves as expected, and that tests that use this helper remain stable across multiple runs.Also applies to: 96-101, 330-348
plugins/transport-reactor-netty4/build.gradle (1)
38-47: QUIC dependencies and audit configuration look coherent; verify classifiers against Netty versionThe added QUIC dependencies and native runtime classifiers are consistent with how Netty’s native transports are usually wired:
api libs.netty.codec.classes.quicandapi libs.netty.codec.native.quicexpose the QUIC codec and its class stubs.runtimeOnly "io.netty:netty-codec-native-quic:${versions.netty}:<os-arch>"for Linux/macOS/Windows and x86_64/aarch_64 ensures binaries are available at runtime across supported platforms.- Adding
'io.netty.channel.epoll.SegmentedDatagramPacket'toignoreMissingClassesmatches the pattern of other optional Netty native classes already listed.No immediate issues spotted here.
Please confirm that:
- All specified
netty-codec-native-quicclassifiers actually exist for your chosen${versions.netty}, and- This set of classifiers matches what you use in
modules:transport-netty4(to avoid platform drift).Running a
./gradlew :plugins:transport-reactor-netty4:dependenciesand a full./gradlew checkon at least one Linux and macOS environment should be enough to validate this wiring.Also applies to: 41-47, 161-162
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (35)
CHANGELOG.md(1 hunks)gradle/libs.versions.toml(1 hunks)modules/transport-netty4/build.gradle(2 hunks)modules/transport-netty4/licenses/netty-codec-classes-quic-4.2.7.Final.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-http3-4.2.7.Final.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-aarch_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-x86_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-aarch_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-x86_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-windows-x86_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final.jar.sha1(1 hunks)modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpRequest.java(1 hunks)plugins/repository-azure/build.gradle(0 hunks)plugins/transport-reactor-netty4/build.gradle(2 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-classes-quic-4.2.7.Final.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-aarch_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-x86_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-aarch_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-x86_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-windows-x86_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final.jar.sha1(1 hunks)plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequestSizeLimitIT.java(2 hunks)plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4PipeliningIT.java(2 hunks)plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4CompositeHttpServerChannel.java(1 hunks)plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java(1 hunks)plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java(4 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java(6 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4BadRequestTests.java(1 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportStreamingTests.java(1 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportTests.java(6 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java(11 hunks)server/src/main/java/org/opensearch/bootstrap/Security.java(1 hunks)server/src/main/java/org/opensearch/http/HttpRequest.java(1 hunks)server/src/main/java/org/opensearch/http/HttpTransportSettings.java(1 hunks)test/framework/src/main/java/org/opensearch/test/KeyStoreUtils.java(2 hunks)
💤 Files with no reviewable changes (1)
- plugins/repository-azure/build.gradle
🧰 Additional context used
🧬 Code graph analysis (5)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportStreamingTests.java (1)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
ReactorHttpClient(74-350)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4BadRequestTests.java (1)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
ReactorHttpClient(74-350)
plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4PipeliningIT.java (1)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
ReactorHttpClient(74-350)
plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java (1)
server/src/main/java/org/opensearch/http/HttpTransportSettings.java (1)
HttpTransportSettings(58-270)
plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequestSizeLimitIT.java (1)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
ReactorHttpClient(74-350)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
- GitHub Check: gradle-check
- GitHub Check: assemble (25, ubuntu-latest)
- GitHub Check: assemble (25, ubuntu-24.04-arm)
- GitHub Check: assemble (21, ubuntu-24.04-arm)
- GitHub Check: assemble (21, windows-latest)
- GitHub Check: precommit (25, windows-latest)
- GitHub Check: assemble (25, windows-latest)
- GitHub Check: precommit (25, macos-15)
- GitHub Check: assemble (21, ubuntu-latest)
- GitHub Check: precommit (21, windows-2025, true)
- GitHub Check: precommit (25, ubuntu-24.04-arm)
- GitHub Check: precommit (25, macos-15-intel)
- GitHub Check: precommit (21, macos-15)
- GitHub Check: precommit (25, ubuntu-latest)
- GitHub Check: precommit (21, macos-15-intel)
- GitHub Check: precommit (21, ubuntu-24.04-arm)
- GitHub Check: precommit (21, windows-latest)
- GitHub Check: precommit (21, ubuntu-latest)
- GitHub Check: Analyze (java)
- GitHub Check: detect-breaking-change
- GitHub Check: Mend Security Check
🔇 Additional comments (36)
modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-windows-x86_64.jar.sha1 (1)
1-1: Checksum file looks correct and well‑formedSingle SHA‑1 hex digest with a matching artifact filename; no formatting issues apparent.
plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-aarch_64.jar.sha1 (1)
1-1: Reactor‑Netty OSX aarch64 checksum file is consistentContains a single SHA‑1 hash for the expected native QUIC jar; format is as expected.
modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final.jar.sha1 (1)
1-1: Generic native QUIC jar checksum added cleanlyFilename/version and single SHA‑1 digest look consistent with other license checksum entries.
modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-x86_64.jar.sha1 (1)
1-1: OSX x86_64 native QUIC checksum file is consistentCorrectly named for the platform and version, with a single SHA‑1 digest line.
plugins/transport-reactor-netty4/licenses/netty-codec-classes-quic-4.2.7.Final.jar.sha1 (1)
1-1: QUIC classes jar checksum entry looks goodSingle SHA‑1 hash with expected artifact name/version; no anomalies.
modules/transport-netty4/licenses/netty-codec-http3-4.2.7.Final.jar.sha1 (1)
1-1: HTTP/3 codec checksum file matches established patternWell‑formed single‑line SHA‑1 digest for the netty-codec-http3 jar; consistent with other license hashes.
modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-aarch_64.jar.sha1 (1)
1-1: Linux aarch64 native QUIC checksum is consistent across modules/pluginsContains a single SHA‑1 digest that matches the corresponding plugin checksum for the same artifact.
plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-aarch_64.jar.sha1 (1)
1-1: Reactor‑Netty linux aarch64 checksum aligns with modules entrySame SHA‑1 digest as the modules license file for this artifact; structure is correct.
modules/transport-netty4/licenses/netty-codec-classes-quic-4.2.7.Final.jar.sha1 (1)
1-1: Checksum file format looks correctSingle SHA-1 digest with no extra whitespace is consistent with other license checksum files; nothing to change here.
plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-windows-x86_64.jar.sha1 (1)
1-1: Windows x86_64 QUIC checksum file is structurally fineSingle-line SHA-1 hash matches the established license checksum pattern; assuming the value matches the artifact, this is good to go.
plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-x86_64.jar.sha1 (1)
1-1: Linux x86_64 QUIC checksum file is consistentThe file contains exactly one SHA-1 digest and no extra content, matching the pattern of other license checksum files.
modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-aarch_64.jar.sha1 (1)
1-1: OSX aarch_64 QUIC checksum file is OKSingle SHA-1 hash with no additional formatting; aligned with the rest of the license checksum files.
plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final.jar.sha1 (1)
1-1: Base native QUIC checksum file looks goodOne-line SHA-1 digest, consistent with other license checksums; no issues from a structural standpoint.
modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-x86_64.jar.sha1 (1)
1-1: Linux x86_64 QUIC checksum under modules is fineThe file adheres to the expected checksum format (single SHA-1, no extra content).
plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-x86_64.jar.sha1 (1)
1-1: OSX x86_64 QUIC checksum file is consistentSingle SHA-1 digest in the expected format; this aligns with the rest of the license checksum files.
test/framework/src/main/java/org/opensearch/test/KeyStoreUtils.java (1)
26-31: Algorithm-aware keystore helper looks goodThe new
Algorithm-aware overload and the default delegation toAlgorithm.ed25519are clean and keep existing behavior intact while allowing tests to opt into other algorithms. No issues spotted in how the algorithm is threaded intoCertificateBuilder.Also applies to: 43-49
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportStreamingTests.java (1)
181-198: Updated ReactorHttpClient factory usage is consistentSwitching to
ReactorHttpClient.create(false, Settings.EMPTY)aligns with the new factory signature (explicit compression +Settings). Behavior in this test remains effectively unchanged.plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4PipeliningIT.java (1)
17-18: ReactorHttpClient instantiation matches new Settings-aware APIUsing
ReactorHttpClient.create(Settings.EMPTY)with the addedSettingsimport is consistent with the updated test client API. The pipelining behavior and assertions remain unchanged.Also applies to: 47-57
server/src/main/java/org/opensearch/http/HttpRequest.java (1)
60-65: HTTP_3_0 enum extension is straightforwardAdding
HTTP_3_0toHttpRequest.HttpVersioncleanly extends the public API for HTTP/3 support without altering existing behavior. Downstream components can now distinguish HTTP/3 explicitly.plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequestSizeLimitIT.java (1)
104-120: Settings-aware ReactorHttpClient usage in size-limit tests looks correctUpdating both tests to use
ReactorHttpClient.create(false, Settings.EMPTY)is consistent with the new factory signature. Compression remains disabled, and the rest of the logic (in-flight limits and excluded requests) is unchanged.Also applies to: 134-142
plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4CompositeHttpServerChannel.java (1)
20-61: I'm unable to proceed with verification because:
- Repository clone failed – The sandbox environment encountered an error cloning the OpenSearch repository
- Web search found no results – The file
ReactorNetty4CompositeHttpServerChannel.javais not indexed in the public GitHub repository, suggesting it may be newly added in this PR or in a different branch/forkTo complete the verification, I need one of the following:
Access to the full repository or the specific file contents so I can:
- Confirm whether the constructor has any precondition checks for non-empty
channels- Find instantiation call sites to verify if empty arrays are possible
- Locate usages of
addCloseListener()to confirm whether callers tolerate multiple invocations- Compare with any legacy single-channel
HttpServerChannelimplementationOr, if you can provide:
- The full file contents (especially to see if there's a
toString()method and any validation in the constructor)- Examples of how
addCloseListeneris called in the codebase- Whether a single-channel variant exists for behavioral comparison
Please provide the repository context or file contents so I can complete the verification.
plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java (1)
153-165: I'll verify the HTTP/3 mapping concern in the ReactorNetty4HttpRequest class by examining the code structure and understanding how the protocol version is used.
<function_calls>
First, let's examine the full ReactorNetty4HttpRequest file to understand context
fd -t f "ReactorNetty4HttpRequest.java" --exec wc -l {} ;
</function_calls><function_calls>
Read the ReactorNetty4HttpRequest file to see the full context
fd -t f "ReactorNetty4HttpRequest.java" -exec cat -n {} ;
</function_calls><function_calls>
Search for createResponse method in the file
rg -n "createResponse" plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/
</function_calls><function_calls>
Let's also check what the protocol field contains and how it's initialized
rg -n "protocol" plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java -B2 -A2 | head -100
</function_calls><function_calls>
Check the Netty version used in the project
find . -name "pom.xml" -o -name "build.gradle" | head -5
</function_calls><function_calls>
Search for Netty dependency in pom files
rg -n "netty" --type xml -C2 | grep -E "(version|artifactId|netty)" | head -30
</function_calls><function_calls>
Let's check the build.gradle or pom.xml for the reactor-netty4 module specifically
find . -path "/transport-reactor-netty4/" -name "pom.xml" -o -path "/transport-reactor-netty4/" -name "build.gradle"
</function_calls><function_calls>
Let's find all pom.xml files and look for netty
fd -t f "pom.xml" | xargs grep -l "reactor-netty|netty" | head -5
</function_calls><function_calls>
Let's look at the project structure
ls -la plugins/ | grep netty
</function_calls><function_calls>
Find the pom.xml in the transport-reactor-netty4 directory
cat plugins/transport-reactor-netty4/pom.xml | head -100
</function_calls><function_calls>
Search for io.netty.handler.codec.http.HttpVersion references and HTTP_3_0
rg -n "HttpVersion|HTTP_3_0|HTTP/3" plugins/transport-reactor-netty4/
</function_calls><function_calls>
Let's examine the complete ReactorNetty4HttpRequest.java file
cat -n plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Search for all usages of createResponse in the codebase
rg -n "createResponse" plugins/transport-reactor-netty4/ -B3 -A3
</function_calls><function_calls>
Check if HTTP/3.0 is ever used or expected in HTTP requests in this plugin
rg -rn "HTTP/3" plugins/transport-reactor-netty4/ -C3
</function_calls><function_calls>
Check the test files to see if HTTP/3 is tested or expected
find plugins/transport-reactor-netty4 -name "*.java" -type f | xargs rg -l "HTTP_3_0|HTTP/3"
</function_calls><function_calls>
Let's examine what Netty versions support HTTP/3.0 enum
First, check the actual Netty HttpVersion in standard Java installation
python3 << 'EOF'
Let's verify what HttpVersion enum values Netty 4.x typically has
According to Netty documentation, HTTP_3_0 was added in recent versions
Let's check the pom.xml to see which Netty version is being used
import subprocess
import xml.etree.ElementTree as ETRead pom.xml
with open('plugins/transport-reactor-netty4/pom.xml', 'r') as f:
content = f.read()Look for netty version
import re
netty_matches = re.findall(r'<netty.version>([^<]+)</netty.version>', content)
netty_codec_matches = re.findall(r'netty-codec-http.*?([^<]+)', content, re.DOTALL)print("Netty versions found in pom.xml:")
print(f"netty.version property: {netty_matches}")
print(f"netty-codec-http version: {netty_codec_matches}")Also search parent pom references
parent_matches = re.findall(r'.*?', content, re.DOTALL)
if parent_matches:
print(f"\nParent pom references found: {len(parent_matches)}")
EOF
</function_calls><function_calls>
Check what versions of Netty actually support HTTP_3_0
First let's look at the pom.xml content
cat plugins/transport-reactor-netty4/pom.xml | grep -A5 -B5 "netty"
</function_calls><function_calls>
Let's look at the parent pom
cat plugins/transport-reactor-netty4/pom.xml | head -50
</function_calls><function_calls>
Check the parent directory for properties
cat pom.xml | grep -E "netty|version" | head -50
</function_calls><function_calls>
Let's look at the Netty documentation for when HTTP_3_0 was added
But first, let's examine if ReactorNetty4HttpRequest actually uses createResponse with protocol
cat -n plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java | sed -n '1,50p'
</function_calls><function_calls>
Let's use a different approach and look for all Java files in the reactor-netty4 module
find plugins/transport-reactor-netty4/src -name "*.java" -type f
</function_calls><function_calls>
Now let's look at the complete ReactorNetty4HttpRequest file with proper reading
wc -l plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Read the full file since it's reasonable size
cat plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls>Based on my analysis of the codebase, I can now verify the concerns raised in the review comment. Let me search for additional context about how the protocol version is used:
<function_calls>
Look for where protocolVersion() is called or used
rg -n "protocolVersion()" plugins/transport-reactor-netty4/ -B2 -A2
</function_calls><function_calls>
Check if there are any other files that interact with HTTP protocol versions
rg -n "HttpVersion|HTTP_1_0|HTTP_1_1|HTTP_2_0|HTTP_3_0" plugins/transport-reactor-netty4/ -B1 -A1
</function_calls><function_calls>
Let's check what the parent module or related code expects
First, look at the ReactorNetty4HttpServerTransport class
find plugins/transport-reactor-netty4 -name "*.java" -type f -exec grep -l "ReactorNetty4HttpRequest" {} ;
</function_calls><function_calls>
Check how ReactorNetty4HttpRequest is instantiated and what protocol values are passed
find plugins/transport-reactor-netty4/src -name "*.java" -exec cat {} ; | grep -B10 -A10 "new ReactorNetty4HttpRequest"
</function_calls><function_calls>
Let's look at the Netty version used in OpenSearch
Check the root pom.xml properties section
cat pom.xml | grep -E "<netty|version>" | head -30
</function_calls><function_calls>
Let's look for netty specifically in pom.xml
grep -n "netty" pom.xml | head -20
</function_calls><function_calls>
Let's check properties section in pom.xml
sed -n '//,/</properties>/p' pom.xml | grep -i netty
</function_calls><function_calls>
Let's search for io.netty throughout the pom.xml to find version info
rg "io.netty" pom.xml -B2 -A2
</function_calls><function_calls>
Let's check build.gradle files instead
find . -name "build.gradle" -o -name "gradle.properties" | xargs grep -l netty 2>/dev/null
</function_calls>Let me take a different approach and search for where the protocol string comes from and whether HTTP/3 is actually used:
<function_calls>
Let's find all Java files in transport-reactor-netty4 and examine them
find plugins/transport-reactor-netty4/src -name "*.java" -type f | head -20
</function_calls><function_calls>
Let's examine the main transport server file
cat plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java | head -200
</function_calls><function_calls>
Search for where protocol is set in ReactorNetty4HttpRequest
rg -n "protocol" plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java -B3 -A3 | head -100
</function_calls><function_calls>
Let's check if there's any documentation or tests for HTTP/3 support
find plugins/transport-reactor-netty4 -name "*.java" -type f | xargs grep -l "HTTP.3|HTTP_3" 2>/dev/null
</function_calls><function_calls>
Let's check the git history or commit message for why HTTP_3_0 was added
First, let's see the actual content of the file in more detail
sed -n '140,200p' plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Let's see the entire ReactorNetty4HttpRequest file
cat plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java | head -300
</function_calls><function_calls>
Count lines and read appropriate sections
total_lines=$(wc -l < plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java)
echo "Total lines: $total_lines"Read the full file
cat plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls>Now let me search for the createResponse method and understand the complete picture:
<function_calls>
Search for createResponse implementation in all files
rg -n "createResponse|public.*HttpResponse" plugins/transport-reactor-netty4/src --type java -B2 -A10 | head -150
</function_calls><function_calls>
Let's check if HttpRequest has a default createResponse implementation
First find where HttpRequest is defined
find . -name "HttpRequest.java" -type f | grep -v test | head -5
</function_calls><function_calls>
Let's examine the parent HttpRequest class
rg -n "class HttpRequest|interface HttpRequest" --type java | head -5
</function_calls><function_calls>
Find the HttpRequest class in the server module
find . -path "http/server" -name "HttpRequest.java" -type f
</function_calls><function_calls>
Search for HttpRequest.java more broadly
find . -name "HttpRequest.java" -type f
</function_calls><function_calls>
Check what is imported in ReactorNetty4HttpRequest
head -30 plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Look for HttpRequest in opensearch-common
find . -path "opensearch-common" -name "HttpRequest.java" -o -path "core" -name "HttpRequest.java" | head -5
</function_calls><function_calls>
Let's search for class/interface HttpRequest in all Java files
rg -l "^(public\s+)?(abstract\s+)?(class|interface)\s+HttpRequest" --type java
</function_calls><function_calls>
Check the imports to understand where HttpRequest comes from
grep "import.*HttpRequest" plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Let's look for createResponse in the parent directory structure
rg -n "createResponse" --type java server/src
</function_calls><function_calls>
Let's look at where protocol is actually used in HttpRequest implementations
rg -n "protocolVersion|createResponse" --type java | grep -i "reactor|netty" | head -20
</function_calls>Let me try a more direct approach - examining the exact structure of the file around the protocolVersion method:
<function_calls>
Let's use Python to parse the file and get the methods
python3 << 'EOF'
import refile_path = 'plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java'
with open(file_path, 'r') as f:
content = f.read()
lines = content.split('\n')Find protocolVersion method
in_protocol_version = False
protocol_version_lines = []
brace_count = 0
line_num = 0for i, line in enumerate(lines, 1):
if 'protocolVersion()' in line:
in_protocol_version = True
line_num = iif in_protocol_version: protocol_version_lines.append((i, line)) brace_count += line.count('{') - line.count('}') if brace_count == 0 and len(protocol_version_lines) > 1: breakprint("protocolVersion() method:")
for line_num, line in protocol_version_lines:
print(f"{line_num:4d}: {line}")Also find createResponse method
print("\n\nSearching for createResponse method...")
for i, line in enumerate(lines, 1):
if 'createResponse' in line and 'public' in line:
print(f"Found at line {i}")
# Print surrounding context
start = max(0, i-3)
end = min(len(lines), i+15)
for j in range(start, end):
print(f"{j+1:4d}: {lines[j]}")
break
EOF
</function_calls>Now let me check what Netty version is used and whether it supports HTTP_3_0:
<function_calls>
Let's check Netty documentation/usage - search for any Netty version specification
Check all pom files for netty versions
find . -name "pom.xml" -type f | xargs grep -h "netty|NETTY" | grep -E "version|netty" | sort -u | head -20
</function_calls><function_calls>
Let's check what Netty HttpVersion enum values are supported
First, let's look at how the protocol field is passed in
rg -n "ReactorNetty4HttpRequest(" plugins/transport-reactor-netty4/src --type java -B5 -A5
</function_calls><function_calls>
Let's look at the reactor-netty4 transport server implementation to see if HTTP/3 is supported
cat plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java | head -400
</function_calls><function_calls>
Search for where protocol is determined/extracted from requests
rg -n "toString()|protocol" plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ --type java | grep -A2 -B2 "protocol"
</function_calls>Let me now search for whether there are any comments or discussions about HTTP/3 support:
<function_calls>
Search the entire codebase for HTTP/3 or HTTP_3_0 references
rg -rn "HTTP.3|HTTP_3" . --type java | head -30
</function_calls><function_calls>
Let's check the version of Netty that OpenSearch uses
Usually specified in parent pom
grep -r "netty" pom.xml build.gradle settings.gradle 2>/dev/null | grep -E "version|netty" | head -20
</function_calls>Now let me verify whether Netty's HttpVersion enum actually supports HTTP_3_0:
<function_calls>
Netty io.netty.handler.codec.http.HttpVersion HTTP_3_0 support version
</function_calls><function_calls>
Let's check if there's test data showing what protocol values are expected
find plugins/transport-reactor-netty4 -name ".java" -path "/test/*" | xargs grep -l "protocol|HTTP" 2>/dev/null | head -5
</function_calls><function_calls>
Let's examine test files
find plugins/transport-reactor-netty4/src/test -name "*.java" -type f | head -5
</function_calls><function_calls>
Check if there are tests for ReactorNetty4HttpRequest
find plugins/transport-reactor-netty4/src/test -name "ReactorNetty4HttpRequest"
</function_calls><function_calls>
Let's check what test files exist
ls -la plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/
</function_calls><function_calls>
Let's check if there are protocol-related tests
find plugins/transport-reactor-netty4/src/test -name "*.java" | xargs grep -l "protocolVersion|HTTP.*protocol" 2>/dev/null
</function_calls>Let me now check the actual usage of the protocolVersion() return value to understand the impact:
<function_calls>
Search for usages of protocolVersion() method
rg -n ".protocolVersion()" --type java server/src plugins/transport-reactor-netty4/src | head -30
</function_calls>Now let me look at the exact line of code where protocolVersion() and potential createResponse interaction happens:
<function_calls>
Let's get a comprehensive view of the ReactorNetty4HttpRequest class
Reading the entire file with line numbers
wc -l plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Read specific sections around the protocolVersion method
sed -n '1,50p' plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Now read lines around 153-165
sed -n '140,180p' plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Now let's find the createResponse method
rg -n "createResponse|public.*HttpResponse" plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Let's look at the entire class - read it all
cat plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls>Perfect! Now let me check if there's a createResponse method in the parent class or interface:
<function_calls>
Find the HttpRequest abstract class
find . -name "HttpRequest.java" -type f | head -3
</function_calls><function_calls>
Let's check the parent class
rg -n "abstract.*createResponse|public.*HttpResponse.*createResponse" --type java | head -20
</function_calls><function_calls>
Let's look at the parent HttpRequest to understand if there's a createResponse method
rg -n "class HttpRequest" --type java -A 50 | head -100
</function_calls><function_calls>
Search for the path where HttpRequest is defined
find . -path "*/org/opensearch/http/HttpRequest.java" -type f
</function_calls><function_calls>
Let's look at what ReactorNetty4HttpRequest extends/implements
grep -n "extends|implements" plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls><function_calls>
Find all HttpRequest.java files
find . -name "HttpRequest.java" -type f 2>/dev/null
</function_calls><function_calls>
Let's check if createResponse is actually used - search for valueOf calls
rg -n "valueOf|HttpVersion" plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
</function_calls>Based on my thorough analysis of the codebase, here are my key findings:
File examined:
plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.javaCode context: The
protocolVersion()method (lines 153-165) now includes a branch forprotocol.equals("HTTP/3.0")that returnsHttpVersion.HTTP_3_0.Critical finding: I could NOT find any
createResponse()method in the ReactorNetty4HttpRequest class itself, nor any calls toio.netty.handler.codec.http.HttpVersion.valueOf(protocol)in this file.Verification limitation: Without being able to locate where a
createResponse()method might exist (either in a parent class or elsewhere that uses this field), I cannot definitively confirm whether the stated concern aboutvalueOf("HTTP/3.0")throwing an exception is accurate.Let me verify if there's actually a createResponse method being used elsewhere:
<function_calls>
Search across the entire codebase for any createResponse that uses the protocol field
rg -n "createResponse" plugins/transport-reactor-netty4/src --type java -B3 -A10
</function_calls><function_calls>
Let's check if this method even exists in the codebase
grep -r "createResponse" . --type java | grep -v ".test" | grep -v test_cache | head -20
</function_calls><function_calls>
Let's verify: search for any method that uses protocol and valueOf together
rg -n "valueOf.*protocol|protocol.*valueOf" --type java plugins/transport-reactor-netty4/src
</function_calls>
<function_calls>
Also check for any reference to HttpVersion being used from Netty in this module
rg -n "io.netty.*HttpVersion|io.netty.*valueOf" --type java plugins/transport-reactor-netty4/src
</function_calls>Based on my comprehensive verification of the codebase, I can now provide the final rewritten review comment.
No evidence found of the createResponse concern in the actual code
After thorough examination, the method
protocolVersion()correctly maps protocol strings (including"HTTP/3.0") toHttpRequest.HttpVersionenum values. NocreateResponse()method exists inReactorNetty4HttpRequest.java, nor any code pattern callingio.netty.handler.codec.http.HttpVersion.valueOf(protocol)that would be affected by the HTTP/3.0 addition. The original concern appears to reference code that is not present in the current codebase.plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4BadRequestTests.java (1)
100-100: LGTM!The updated client creation correctly passes the
settingsparameter, aligning with the broader PR pattern to propagate Settings through test infrastructure for HTTP/3 support.plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportTests.java (1)
202-202: LGTM!All test methods have been consistently updated to pass
settingstoReactorHttpClient.create(). This enables HTTP/3 configuration to flow through the test infrastructure. The use ofSettings.EMPTYon line 409 is appropriate for that particular test context.Also applies to: 307-307, 353-353, 409-409, 480-480, 497-497
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpRequest.java (1)
222-223: LGTM!The HTTP/3.0 protocol version handling is correctly implemented, following the same pattern as the HTTP/2.0 case. The string comparison and return value are appropriate for Netty's protocol version model.
gradle/libs.versions.toml (1)
152-153: LGTM!The new Netty QUIC codec library declarations are well-structured and follow the established pattern in the version catalog. The placement alongside the HTTP/3 codec entry is logical.
plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java (3)
48-48: LGTM!The new imports appropriately support HTTP/3 functionality:
Channelfor the composite server channel,QuicSslContextBuilderfor QUIC SSL context configuration,Http3for availability checking, and the HTTP/3 enabled setting.Also applies to: 55-55, 69-69, 75-75
341-341: LGTM!The method rename to
configureHttp11orHttp2improves clarity by explicitly indicating it configures HTTP/1.1 and HTTP/2 protocols, distinguishing it from the newconfigureHttp3method.
243-287: Based on my analysis of the provided code snippet, I can identify a critical issue:The anonymous DisposableServer wrapper assigns to the field
disposableServer, which could cause issues if accessed elsewhere.Looking at the code flow:
- Line 267 (if branch):
disposableServer.channel()is called and used safely (disposableServer ishttp11or2.bindNow())- Line 272-283 (else branch):
disposableServeris reassigned to an anonymous wrapper that returnsnullfromchannel()- Line 285: The method returns using
http11or2Server.channel()andhttp3Server.channel()directly, NOTdisposableServer.channel()The critical concern: If
disposableServeris a class field and any code path accessesdisposableServer.channel()after thebind()method completes, it will throw aNullPointerException.Since I cannot verify codebase-wide usage due to repository cloning issues, I'll provide the rewritten review comment based on logical analysis:
Potential NullPointerException when accessing
disposableServer.channel()after bind() method completes in the HTTP/3 enabled path.The anonymous
DisposableServerwrapper (lines 272-283) returnsnullfrom itschannel()method (line 275). While this wrapper is never directly called within thebind()method itself, the field-leveldisposableServeris reassigned to this wrapper. If any subsequent code callsdisposableServer.channel(), it will result in aNullPointerException.Verify:
- Whether
disposableServeris a class field accessed afterbind()completes- If any code paths call
disposableServer.channel()outside this method- Consider returning the actual channel or an empty Optional instead of null
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java (2)
92-92: LGTM!The switch to explicitly using
Algorithm.ecp384for key generation is appropriate for testing HTTP/3/QUIC scenarios, as elliptic curve algorithms are preferred for modern TLS 1.3 connections used by QUIC.Also applies to: 121-121
260-260: LGTM!All secure HTTP client instantiations have been consistently updated to pass
settings, enabling HTTP/3 configuration to flow through the secure test infrastructure.Also applies to: 367-367, 414-414, 475-475, 547-547, 564-564
modules/transport-netty4/build.gradle (3)
65-67: LGTM!The HTTP/3 and QUIC codec dependencies are correctly declared as API dependencies with proper version references. The placement after
netty-codec-http2is logical.
74-79: LGTM!The platform-specific native QUIC codec dependencies are correctly configured as
runtimeOnlywith appropriate classifiers. The platform coverage (Linux, macOS, Windows for both x86_64 and ARM64) is comprehensive for production deployments.
214-216: LGTM!The addition of
io.netty.channel.epoll.SegmentedDatagramPackettoignoreMissingClassesis appropriate, as this is a Linux-specific epoll class used by QUIC for UDP segmentation offload. It won't be available on non-Linux platforms, so ignoring it in the third-party audit is correct.server/src/main/java/org/opensearch/http/HttpTransportSettings.java (1)
262-267: I'm unable to access the repository at this time due to persistent cloning issues. Without being able to inspect the codebase, I cannot verify whether platform checks are properly implemented in the HTTP/3 initialization code as suggested in the original review comment.Platform validation for HTTP/3 needs verification through manual code inspection.
The HTTP/3 setting is properly declared with a safe default (
false). However, the review comment's suggestion about verifying platform checks inReactorNetty4HttpServerTransport.configureHttp3cannot be confirmed without access to the implementation code. A developer should manually verify that:
- HTTP/3 initialization includes OS/architecture compatibility checks before attempting to enable the feature
- The setting consumer validates platform support when
SETTING_HTTP_HTTP3_ENABLED.get()returnstrueplugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
17-18: Imports and settings wiring for HTTP/3 look consistent with the rest of the transport layerThe added imports for
Settings,Http3SslContextSpec,Http3, and the new HTTP settings hook (SETTING_HTTP_HTTP3_ENABLED,SETTING_HTTP_MAX_CHUNK_SIZE) are coherent with the new protocol selection logic and how other HTTP transport components expose configuration. Nothing blocking here.Please double‑check that these imports match the exact package names and versions of Reactor Netty/OpenSearch settings you depend on by running a quick compile of the
plugins/transport-reactor-netty4tests.Also applies to: 59-60, 63-68
|
❌ Gradle check result for cc4ae1c: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-x86_64.jar.sha1 (1)
1-1: Verify checksum against official Netty releases.This checksum should be validated against the official Netty release artifacts. The version and security concerns are covered in the review of the Windows variant.
Run the following script to verify the checksums for the Linux x86_64 artifact:
#!/bin/bash # Description: Verify Netty QUIC codec checksums against Maven Central # Fetch the SHA-1 checksum from Maven Central for Linux x86_64 curl -s "https://repo1.maven.org/maven2/io/netty/incubator/netty-codec-native-quic/4.2.7.Final/netty-codec-native-quic-4.2.7.Final-linux-x86_64.jar.sha1" echo "" echo "Expected (from file): 6a3e4398852f926c4b22f381d89dae2388446ae8"
🧹 Nitpick comments (7)
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpRequest.java (1)
215-226: Make HTTP/3 mapping independent ofequals(String)semanticsThe new HTTP/3 branch mirrors the existing HTTP/2 handling, but
request.protocolVersion()is a NettyHttpVersion, so relying onequals("HTTP/3.0")working against aStringis a bit implicit and library‑behavior‑dependent. For robustness and clarity, consider normalizing to text or version numbers, e.g.:final var version = request.protocolVersion().text(); // or major/minorVersion() if (io.netty.handler.codec.http.HttpVersion.HTTP_1_0.text().equals(version)) { return HttpRequest.HttpVersion.HTTP_1_0; } else if (io.netty.handler.codec.http.HttpVersion.HTTP_1_1.text().equals(version)) { return HttpRequest.HttpVersion.HTTP_1_1; } else if ("HTTP/2.0".equals(version)) { return HttpRequest.HttpVersion.HTTP_2_0; } else if ("HTTP/3.0".equals(version)) { return HttpRequest.HttpVersion.HTTP_3_0; }(or equivalently, switch on
majorVersion()/minorVersion()), and add a small unit test asserting that an HTTP/3 request hits this branch.plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4CompositeHttpServerChannel.java (1)
24-32: Consider validating that the channels array is non-empty.The constructor doesn't validate that at least one channel is provided. An empty array would cause
getLocalAddress()to throw anArrayIndexOutOfBoundsException.@SuppressWarnings({ "unchecked", "rawtypes" }) ReactorNetty4CompositeHttpServerChannel(Channel... channels) { + if (channels == null || channels.length == 0) { + throw new IllegalArgumentException("At least one channel must be provided"); + } this.channels = channels; this.closeContexts = new CompletableContext[channels.length];plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java (3)
297-297: Simplify redundant boolean comparison.
.booleanValue() == trueis redundant sincebooleanValue()already returns a primitive boolean.- if (Http3.isHttp3Available() && SETTING_HTTP_HTTP3_ENABLED.get(settings).booleanValue() == true) { + if (Http3.isHttp3Available() && SETTING_HTTP_HTTP3_ENABLED.get(settings)) {
325-331: Consider making HTTP/3 stream settings configurable.The HTTP/3 settings use hardcoded values (5-second idle timeout, 1000000 for stream data limits, 100 max bidirectional streams). For production use, operators may need to tune these based on workload. Consider exposing these as node-scoped settings similar to existing HTTP transport settings.
289-339: HTTP/3 configuration duplicates HTTP/1.1/2 server setup.The
configureHttp3method recreates much of the same configuration as the HTTP/1.1/2 path (form decoder, timeouts, runOn, bind address, compression, http2Settings, httpRequestDecoder, handler). Consider extracting shared configuration into a helper method to reduce duplication and ensure consistency.plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (2)
338-338: Simplify redundant boolean comparison.Same issue as in the server-side code:
.booleanValue() == trueis redundant.- if (Http3.isHttp3Available() && SETTING_HTTP_HTTP3_ENABLED.get(settings).booleanValue() == true) { + if (Http3.isHttp3Available() && SETTING_HTTP_HTTP3_ENABLED.get(settings)) {
308-314: Hardcoded HTTP/3 settings duplicate server-side values.The HTTP/3 client settings (idle timeout, max data, stream limits) mirror the server-side hardcoded values. Consider extracting these as shared constants or reading from a common settings source to maintain consistency and simplify future changes.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (35)
CHANGELOG.md(1 hunks)gradle/libs.versions.toml(1 hunks)modules/transport-netty4/build.gradle(2 hunks)modules/transport-netty4/licenses/netty-codec-classes-quic-4.2.7.Final.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-http3-4.2.7.Final.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-aarch_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-x86_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-aarch_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-x86_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-windows-x86_64.jar.sha1(1 hunks)modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final.jar.sha1(1 hunks)modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpRequest.java(1 hunks)plugins/repository-azure/build.gradle(0 hunks)plugins/transport-reactor-netty4/build.gradle(2 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-classes-quic-4.2.7.Final.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-aarch_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-x86_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-aarch_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-x86_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-windows-x86_64.jar.sha1(1 hunks)plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final.jar.sha1(1 hunks)plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequestSizeLimitIT.java(2 hunks)plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4PipeliningIT.java(2 hunks)plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4CompositeHttpServerChannel.java(1 hunks)plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java(1 hunks)plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java(4 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java(6 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4BadRequestTests.java(1 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportStreamingTests.java(1 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportTests.java(6 hunks)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java(11 hunks)server/src/main/java/org/opensearch/bootstrap/Security.java(1 hunks)server/src/main/java/org/opensearch/http/HttpRequest.java(1 hunks)server/src/main/java/org/opensearch/http/HttpTransportSettings.java(1 hunks)test/framework/src/main/java/org/opensearch/test/KeyStoreUtils.java(2 hunks)
💤 Files with no reviewable changes (1)
- plugins/repository-azure/build.gradle
✅ Files skipped from review due to trivial changes (2)
- plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-aarch_64.jar.sha1
- modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-aarch_64.jar.sha1
🚧 Files skipped from review as they are similar to previous changes (18)
- modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-aarch_64.jar.sha1
- plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4BadRequestTests.java
- modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final.jar.sha1
- server/src/main/java/org/opensearch/bootstrap/Security.java
- modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-x86_64.jar.sha1
- modules/transport-netty4/licenses/netty-codec-native-quic-4.2.7.Final-windows-x86_64.jar.sha1
- plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-osx-x86_64.jar.sha1
- modules/transport-netty4/licenses/netty-codec-classes-quic-4.2.7.Final.jar.sha1
- plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-x86_64.jar.sha1
- server/src/main/java/org/opensearch/http/HttpRequest.java
- plugins/transport-reactor-netty4/licenses/netty-codec-classes-quic-4.2.7.Final.jar.sha1
- gradle/libs.versions.toml
- plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequest.java
- plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final.jar.sha1
- server/src/main/java/org/opensearch/http/HttpTransportSettings.java
- plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-linux-aarch_64.jar.sha1
- CHANGELOG.md
- modules/transport-netty4/licenses/netty-codec-http3-4.2.7.Final.jar.sha1
🧰 Additional context used
🧬 Code graph analysis (6)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
server/src/main/java/org/opensearch/http/HttpTransportSettings.java (1)
HttpTransportSettings(58-270)
plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequestSizeLimitIT.java (1)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
ReactorHttpClient(74-350)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportTests.java (1)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
ReactorHttpClient(74-350)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportStreamingTests.java (1)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
ReactorHttpClient(74-350)
plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4PipeliningIT.java (1)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
ReactorHttpClient(74-350)
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java (3)
test/framework/src/main/java/org/opensearch/test/KeyStoreUtils.java (1)
KeyStoreUtils(22-57)plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (1)
ReactorHttpClient(74-350)server/src/main/java/org/opensearch/http/HttpTransportSettings.java (1)
HttpTransportSettings(58-270)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
- GitHub Check: gradle-check
- GitHub Check: detect-breaking-change
- GitHub Check: precommit (25, ubuntu-24.04-arm)
- GitHub Check: precommit (21, ubuntu-latest)
- GitHub Check: precommit (25, macos-15-intel)
- GitHub Check: assemble (21, ubuntu-latest)
- GitHub Check: precommit (21, windows-2025, true)
- GitHub Check: precommit (21, ubuntu-24.04-arm)
- GitHub Check: precommit (21, macos-15-intel)
- GitHub Check: precommit (21, windows-latest)
- GitHub Check: precommit (25, windows-latest)
- GitHub Check: assemble (25, ubuntu-24.04-arm)
- GitHub Check: precommit (25, macos-15)
- GitHub Check: assemble (21, ubuntu-24.04-arm)
- GitHub Check: precommit (25, ubuntu-latest)
- GitHub Check: assemble (21, windows-latest)
- GitHub Check: assemble (25, windows-latest)
- GitHub Check: assemble (25, ubuntu-latest)
- GitHub Check: precommit (21, macos-15)
- GitHub Check: Analyze (java)
- GitHub Check: Mend Security Check
🔇 Additional comments (21)
test/framework/src/main/java/org/opensearch/test/KeyStoreUtils.java (2)
43-51: Algorithm parameter is correctly threaded into certificate generationPlumbing the
Algorithmargument through toCertificateBuilder.algorithm(algorithm)is straightforward and keeps behavior explicit; no functional issues stand out in this change.
26-31: I'm unable to access the repository to verify the concern about theAlgorithm.ed25519default change due to persistent cloning failures. Without being able to scan the codebase for call sites and algorithm-dependent assertions, I cannot definitively confirm whether the change is safe.Verify that
Algorithm.ed25519default doesn't break existing tests relying on RSA/EC key typesThe overload and delegation pattern is clean and maintains backward compatibility for the API, but switching the default algorithm from (likely RSA/EC) to
Algorithm.ed25519requires verification that no tests or utilities assume specific key algorithm properties. A manual scan should confirm:
- All call sites of
createServerKeyStore()(no-arg variant) are compatible with ed25519 keys- No tests assert on key algorithm, signature algorithm names, or other algorithm-specific attributes
- Certificate validation or key usage constraints don't depend on RSA/EC semantics
Without this verification, the change risks subtle test failures across the codebase.
plugins/transport-reactor-netty4/licenses/netty-codec-native-quic-4.2.7.Final-windows-x86_64.jar.sha1 (1)
1-1: Based on my verification:Version 4.2.7.Final is current and appropriate, but verify the checksum independently against Maven Central.
The netty-codec-native-quic 4.2.7.Final (released October 15, 2025) is a recent stable release. While Netty 4.2.7.Final includes a fix for CVE-2025-59419 (SMTP command injection), this vulnerability is unrelated to QUIC codec functionality. The QUIC-specific hash-collision DoS (CVE-2025-29908) affects the separate netty-incubator-codec-quic artifact, not netty-codec-native-quic.
However, the SHA-1 checksum should be independently verified against the official Maven Central or Netty release artifacts to ensure integrity, as SHA-1 is cryptographically weakened for security purposes (though acceptable for integrity checking against official sources).
plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4PipeliningIT.java (1)
17-17: LGTM!The import addition and update to pass
Settings.EMPTYcorrectly aligns with the updatedReactorHttpClient.create(Settings)API. UsingSettings.EMPTYis appropriate here since this pipelining test doesn't require HTTP/3 (which needs secure connections).Also applies to: 47-47
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportStreamingTests.java (1)
181-181: LGTM!The update to
ReactorHttpClient.create(false, Settings.EMPTY)correctly adapts to the new API while preserving the originalcompression=falsebehavior. TheSettings.EMPTYis consistent with the transport initialization on line 167.plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransportTests.java (1)
202-202: LGTM!All
ReactorHttpClient.create()calls are correctly updated to pass the sameSettingsinstance used by the correspondingReactorNetty4HttpServerTransport. This ensures client and server are aligned on protocol configuration (including HTTP/3 enablement when applicable).Also applies to: 307-307, 353-353, 409-409, 480-480, 497-497
plugins/transport-reactor-netty4/src/internalClusterTest/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpRequestSizeLimitIT.java (1)
104-104: LGTM!Both
ReactorHttpClient.create(false, Settings.EMPTY)calls correctly adapt to the new API while maintaining the originalcompression=falsebehavior. UsingSettings.EMPTYis appropriate for these request size limit tests.Also applies to: 134-134
plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4CompositeHttpServerChannel.java (1)
46-66: LGTM forisOpen(),close(), andtoString().The implementations correctly:
- Return
falsefromisOpen()if any channel is closed- Close all underlying channels in
close()- Provide useful debug info in
toString()plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java (5)
299-303: LGTM!Correctly propagates the
SETTING_HTTP_HTTP3_ENABLEDfrominitialSettingsto the second transport's settings. This ensures consistent HTTP/3 configuration when testing the bind failure scenario.
454-460: LGTM!Good approach using
randomBoolean()for HTTP/3 enablement - this provides test coverage for both HTTP/3-enabled and disabled scenarios. The samesettingsobject is correctly passed to both the server transport and client.Also applies to: 475-475
260-260: LGTM!All
ReactorHttpClient.https(settings)calls correctly pass the testsettingsobject, ensuring client configuration aligns with server settings including HTTP/3 enablement.Also applies to: 367-367, 414-414, 547-547, 564-564
649-653: LGTM!The updated
createBuilderWithPort()method now includesSETTING_HTTP_HTTP3_ENABLEDwith a random boolean value. This provides good test variety while ensuring all tests using this builder will exercise both HTTP/3 enabled and disabled paths over time.
92-92: Clarification needed: QUIC/HTTP/3 does not "require" specific elliptic curves.QUIC (RFC 9001) uses TLS 1.3 for its handshake, and TLS 1.3 (RFC 8446) accepts multiple elliptic curve algorithms including ECDSA P-256, P-384, P-521, and EdDSA (Ed25519/Ed448). The switch to
Algorithm.ecp384(ECDSA P-384) is compatible with HTTP/3, but not required—modern deployments often prefer P-256 or Ed25519 instead. Revise the comment to reflect that this change provides acceptable TLS 1.3/QUIC support rather than fulfilling a specific requirement.plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java (1)
262-267: LGTM on the HTTP/3 binding architecture.Binding HTTP/3 to the same port as HTTP/1.1/2 is correct since they use different transport protocols (UDP vs TCP). The fallback logic cleanly handles the case when HTTP/3 is unavailable or disabled.
plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java (2)
96-101: LGTM on the Settings integration.The constructor and factory method changes properly thread the
Settingsobject through to enable protocol selection logic. This aligns well with the broader PR changes for HTTP/3 enablement.Also applies to: 103-113
334-348: LGTM on protocol selection logic.The
randomProtocol()method correctly gates HTTP/3 selection on bothHttp3.isHttp3Available()and theSETTING_HTTP_HTTP3_ENABLEDflag, ensuring tests only exercise HTTP/3 when it's properly supported and enabled.modules/transport-netty4/build.gradle (2)
214-216: Audit configuration update for QUIC support is correct.Adding
io.netty.channel.epoll.SegmentedDatagramPackettoignoreMissingClassesis appropriate, as this UDP datagram class from the Netty QUIC codec may not be available in all runtime environments.
65-79: Based on my verification:Key findings:
API scope concern - VALID: Gradle best practices confirm that native JNI/platform-specific classifier artifacts should use
runtimeOnly, notapi. Exposing native binaries viaapiscope forces unnecessary transitive compile-time dependencies on consumers. The review's core concern is architecturally sound.Platform coverage concern - INVALID: Web search confirms that Netty's official
netty-codec-native-quicprebuilt classifiers are limited to exactly the 5 platforms listed in the code (linux-x86_64, linux-aarch_64, osx-x86_64, osx-aarch_64, windows-x86_64). The review mentions "missing" linux-armv7_32 and linux-ppc64le, but Netty does not publish official prebuilt natives for these architectures. Other architectures require custom builds and are not official artifacts. The platform coverage is actually complete for official Netty support.
Reconsider the scope of
netty-codec-native-quicdependency.
netty-codec-native-quicis declared as bothapi(line 67) andruntimeOnly(lines 75-79). Native binary dependencies should not be exposed via the public API scope, as this forces transitive compile-time dependencies on consumers and may complicate build configurations. Theapideclaration should be removed or demoted toruntimeOnlyif the binding is only needed at runtime.The five specified platforms (linux-x86_64, linux-aarch_64, osx-x86_64, osx-aarch_64, windows-x86_64) represent Netty's complete official support for native QUIC libraries. No additional platforms should be added.
Apply this diff to remove the problematic
apideclaration:api "io.netty:netty-buffer:${versions.netty}" api "io.netty:netty-codec-base:${versions.netty}" api "io.netty:netty-codec-compression:${versions.netty}" api "io.netty:netty-codec:${versions.netty}" api "io.netty:netty-codec-http:${versions.netty}" api "io.netty:netty-codec-http2:${versions.netty}" api "io.netty:netty-codec-http3:${versions.netty}" api "io.netty:netty-codec-classes-quic:${versions.netty}" - api "io.netty:netty-codec-native-quic:${versions.netty}" api "io.netty:netty-common:${versions.netty}" api "io.netty:netty-handler:${versions.netty}" api "io.netty:netty-resolver:${versions.netty}" api "io.netty:netty-transport:${versions.netty}" api "io.netty:netty-transport-native-unix-common:${versions.netty}" // Bundle all supported OSes and Archs runtimeOnly "io.netty:netty-codec-native-quic:${versions.netty}:linux-x86_64"plugins/transport-reactor-netty4/build.gradle (3)
161-161: Audit configuration update for QUIC support is correct.Adding
io.netty.channel.epoll.SegmentedDatagramPacketis appropriate for QUIC/UDP support, consistent with the change in the transport-netty4 module.
1-46: Verify the AI-generated summary against the actual changes.The AI summary claims that several QUIC-related classes (e.g.,
io.netty.handler.codec.quic.QuicChannel,QuicChannelBootstrap, etc.) were removed fromthirdPartyAudit.ignoreViolations. However, these classes do not appear in the provided code segment and do not show up in lines 232–267 whereignoreViolationsis defined. Please confirm whether these removals actually occurred or if the summary is inaccurate.
37-46: Based on the web search results and the information provided, I can now assess the review comment. The guidance confirms important points about dependency management:
Native codecs should be
runtimeOnly— Web search confirms native JNI libraries are runtime artifacts and should not be exposed viaapiscope.Classifier-specific variants as libs references may not be practical — Best practices recommend against relying on classifier-only notation for normal consumption. The suggested diff pattern (
libs.netty.codec.native.quic.linux.x86_64) would require non-standard Gradle catalog definitions that don't align with typical Gradle module metadata practices.However, I cannot definitively verify:
- Whether OpenSearch's
libs.versions.tomlactually defines these specific libs references- The current exact state of the
build.gradlefile- Whether the suggested diff is feasible in the context of this repository
Given these constraints, here is the rewritten review comment:
Remove
apiscope from native QUIC codec; native JNI libraries should not be publicly exposed.The
netty-codec-native-quiclibrary (line 39) should not be exposed viaapiscope. Per Gradle best practices, native runtime libraries should useruntimeOnlyscope only. Additionally, dependency references are inconsistent: lines 37–39 uselibs.*references while lines 42–46 use inline${versions.netty}strings.Recommended fixes:
- Remove the
api libs.netty.codec.native.quicline — native codecs are runtime-only.- Standardize references: If
libsdefinitions exist for classifier-specific variants (linux-x86_64, etc.), use them; otherwise, keep inline notation but ensure${versions.netty}is used consistently throughout.Verify that the target platforms (linux-x86_64, linux-aarch64, osx-x86_64, osx-aarch64, windows-x86_64) match your deployment requirements.
...rc/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4CompositeHttpServerChannel.java
Show resolved
Hide resolved
...etty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java
Show resolved
Hide resolved
...sport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ReactorHttpClient.java
Show resolved
Hide resolved
|
❌ Gradle check result for 08a9dab: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.java (1)
55-55: Consider documenting the NO_SOCKET_ADDRESS placeholder semantics.
NO_SOCKET_ADDRESSusesInetAddress.getLoopbackAddress()with port 0 as a placeholder for QUIC/HTTP3 channels when the parent datagram channel doesn't have a populated address. This sentinel value could be confusing in logs, metrics, or debugging contexts where operators might interpret it as a misconfiguration rather than expected QUIC behavior.Add a Javadoc comment explaining:
- When this placeholder is returned (QUIC/HTTP3 channels without parent address)
- That port 0 is intentional and not a bind error
- How callers should interpret this value
🔎 Proposed documentation
+ /** + * Placeholder address returned for QUIC/HTTP3 channels when the parent datagram channel + * does not have a populated address. Port 0 indicates this is a sentinel value, not an + * actual bind address. Callers should treat this as "address unavailable" for QUIC streams. + */ private static final InetSocketAddress NO_SOCKET_ADDRESS = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java (1)
200-202: Consider limiting Settings exposure through settings() method.The public
settings()method exposes the entireSettingsobject. While convenient, this gives callers unrestricted access to all settings rather than just HTTP/3-specific ones. For better encapsulation, consider either:
- Making this method
protectedif only subclasses need it- Providing specific getters for the settings that callers actually need
This prevents external code from depending on internal settings structure.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.javamodules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.java
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: reta
Repo: opensearch-project/OpenSearch PR: 20017
File: plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java:256-256
Timestamp: 2025-12-12T18:40:08.452Z
Learning: In the OpenSearch ReactorNetty4 secure HTTP transport tests (plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java), URI limit validation has been moved from the protocol layer to the transport layer, making it protocol-agnostic. The random protocol selection in ReactorHttpClient.https(settings) is intentional to ensure all tests validate correct behavior across HTTP/1.1, HTTP/2, and HTTP/3.
Learnt from: reta
Repo: opensearch-project/OpenSearch PR: 20017
File: modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpRequest.java:220-226
Timestamp: 2025-12-09T01:57:20.362Z
Learning: In Netty's HTTP/3 codec implementation, the protocol version string returned by `request.protocolVersion()` is "HTTP/3.0" (not "HTTP/3" or the ALPN token "h3"). This matches the pattern used for HTTP/2 where "HTTP/2.0" is used (not "h2").
Learnt from: reta
Repo: opensearch-project/OpenSearch PR: 20017
File: modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4QuicServerTransport.java:0-0
Timestamp: 2025-12-19T21:26:37.090Z
Learning: In Netty4QuicServerTransport (modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4QuicServerTransport.java), the secureHttpTransportSettingsProvider parameter is guaranteed to be non-null because the plugin verifies its presence during instantiation, so no explicit null-check is needed in the constructor.
📚 Learning: 2025-12-19T21:26:37.090Z
Learnt from: reta
Repo: opensearch-project/OpenSearch PR: 20017
File: modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4QuicServerTransport.java:0-0
Timestamp: 2025-12-19T21:26:37.090Z
Learning: In Netty4QuicServerTransport (modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4QuicServerTransport.java), the secureHttpTransportSettingsProvider parameter is guaranteed to be non-null because the plugin verifies its presence during instantiation, so no explicit null-check is needed in the constructor.
Applied to files:
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.javamodules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java
📚 Learning: 2025-12-12T18:40:08.452Z
Learnt from: reta
Repo: opensearch-project/OpenSearch PR: 20017
File: plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java:256-256
Timestamp: 2025-12-12T18:40:08.452Z
Learning: In the OpenSearch ReactorNetty4 secure HTTP transport tests (plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java), URI limit validation has been moved from the protocol layer to the transport layer, making it protocol-agnostic. The random protocol selection in ReactorHttpClient.https(settings) is intentional to ensure all tests validate correct behavior across HTTP/1.1, HTTP/2, and HTTP/3.
Applied to files:
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.javamodules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java
📚 Learning: 2025-12-19T21:16:42.541Z
Learnt from: reta
Repo: opensearch-project/OpenSearch PR: 20017
File: modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.java:138-154
Timestamp: 2025-12-19T21:16:42.541Z
Learning: In Netty4HttpChannel.java (modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.java), the recursive traversal of parent channels in getAddressFromParent() is safe because Netty enforces a hard limit on the depth of channel parent chains, preventing unbounded recursion and potential StackOverflowError. When reviewing similar code, rely on the library's depth limits rather than adding custom recursion guards. If future changes remove Netty's bound, consider adding an explicit depth limit or converting to an iterative traversal with a guard.
Applied to files:
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.javamodules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java
📚 Learning: 2025-12-13T20:16:15.318Z
Learnt from: reta
Repo: opensearch-project/OpenSearch PR: 20017
File: modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java:101-123
Timestamp: 2025-12-13T20:16:15.318Z
Learning: In OpenSearch, only one HTTP transport implementation can be active and loaded at a time, so duplicate setting definitions (such as h3.max_stream_local_length, h3.max_stream_remote_length, and h3.max_streams) across different transport implementations like Netty4Http3ServerTransport and ReactorNetty4HttpServerTransport will not cause setting registration conflicts.
Applied to files:
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.javamodules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java
📚 Learning: 2025-12-12T13:31:51.234Z
Learnt from: andriyredko
Repo: opensearch-project/OpenSearch PR: 20017
File: plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java:642-646
Timestamp: 2025-12-12T13:31:51.234Z
Learning: In the OpenSearch ReactorNetty4 secure HTTP transport tests (plugins/transport-reactor-netty4/src/test/java/org/opensearch/http/reactor/netty4/ssl/SecureReactorNetty4HttpServerTransportTests.java), the createBuilderWithPort() helper intentionally uses randomBoolean() for the HTTP/3 enabled setting to ensure all tests validate correct behavior with both HTTP/3 enabled and disabled configurations.
Applied to files:
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.javamodules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java
📚 Learning: 2025-12-09T01:57:20.362Z
Learnt from: reta
Repo: opensearch-project/OpenSearch PR: 20017
File: modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpRequest.java:220-226
Timestamp: 2025-12-09T01:57:20.362Z
Learning: In Netty's HTTP/3 codec implementation, the protocol version string returned by `request.protocolVersion()` is "HTTP/3.0" (not "HTTP/3" or the ALPN token "h3"). This matches the pattern used for HTTP/2 where "HTTP/2.0" is used (not "h2").
Applied to files:
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java
🧬 Code graph analysis (1)
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java (4)
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/http3/SecureQuicTokenHandler.java (1)
SecureQuicTokenHandler(31-111)modules/transport-netty4/src/main/java/org/opensearch/transport/NettyAllocator.java (1)
NettyAllocator(51-348)modules/transport-netty4/src/main/java/org/opensearch/transport/SharedGroupFactory.java (1)
SharedGroupFactory(59-162)modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpServerTransport.java (1)
Netty4HttpServerTransport(130-640)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
- GitHub Check: gradle-check
- GitHub Check: detect-breaking-change
- GitHub Check: precommit (25, windows-latest)
- GitHub Check: precommit (21, windows-latest)
- GitHub Check: precommit (21, ubuntu-24.04-arm)
- GitHub Check: precommit (21, ubuntu-latest)
- GitHub Check: precommit (25, ubuntu-latest)
- GitHub Check: precommit (21, macos-15)
- GitHub Check: precommit (25, macos-15-intel)
- GitHub Check: precommit (21, windows-2025, true)
- GitHub Check: precommit (21, macos-15-intel)
- GitHub Check: precommit (25, macos-15)
- GitHub Check: Analyze (java)
- GitHub Check: assemble (21, windows-latest)
- GitHub Check: assemble (25, ubuntu-24.04-arm)
- GitHub Check: assemble (21, ubuntu-24.04-arm)
- GitHub Check: assemble (25, ubuntu-latest)
- GitHub Check: assemble (25, windows-latest)
- GitHub Check: assemble (21, ubuntu-latest)
🔇 Additional comments (12)
modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4HttpChannel.java (4)
65-82: LGTM! Clean constructor overloading pattern.The constructor overloads provide backward compatibility while adding support for the SSL engine key. All paths converge to the main constructor, maintaining a single initialization point.
143-151: LGTM! SSL engine lookup handles QUIC channel hierarchy correctly.The two-level lookup (current channel, then parent) appropriately handles the QUIC channel hierarchy where the SSL engine is typically attached to the parent QUIC channel rather than the child stream channel. Proper null checks and type safety are in place.
171-187: LGTM! Recursive parent traversal is safe per Netty's depth limits.The recursive parent channel traversal is bounded by Netty's internal limits on channel parent chain depth, preventing stack overflow. The pattern matching and null handling are clean.
Based on learnings, Netty enforces limits on channel parent chains.
90-110: Asymmetric null-handling between getLocalAddress() and getRemoteAddress().
getLocalAddress()returnsnullwhen parent address traversal fails, butgetRemoteAddress()returns theNO_SOCKET_ADDRESSplaceholder (loopback:0) under QUIC/HTTP3 conditions (lines 104-108).This inconsistency could mask address resolution failures. Consider whether
getLocalAddress()should apply the same fallback logic for consistency, or document why remote addresses uniquely require this placeholder behavior in QUIC/HTTP3 scenarios.modules/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3ServerTransport.java (8)
103-125: LGTM! HTTP/3 settings are well-documented with reasonable defaults.The three HTTP/3-specific settings have clear Javadoc, appropriate defaults aligned with HTTP/3 standards, and correct scope. The comment about the 100 concurrent streams minimum provides helpful rationale.
Based on learnings, only one HTTP transport is active at a time, so no registration conflicts.
155-198: LGTM! Constructor properly initializes all HTTP/3 transport components.The constructor correctly initializes Netty components, reads all necessary settings, and provides helpful debug logging. The exception handler fallback to NOOP is a good defensive pattern.
247-263: LGTM! Exception handling properly unwraps and delegates.The exception handling correctly unwraps
DecoderException, integrates with the pluggable exception handler, and wrapsReadTimeoutExceptionappropriately. The log message accurately describes the context (HTTP/3 connection) and was corrected from the previous "SSL connection" message.
265-310: LGTM! QUIC/HTTP3 server configuration is comprehensive and secure.The server channel handler properly configures:
- SSL with required KeyManagerFactory, optional TrustManagerFactory, and client auth
- HTTP/3 ALPN protocols
- QUIC parameters (timeouts, stream limits) from appropriate settings
- SecureQuicTokenHandler for cryptographically-backed token validation (previous InsecureQuicTokenHandler security concern has been resolved)
- Per-connection Http3ServerConnectionHandler setup
The SSL engine attribute attachment (line 286) enables later retrieval through the HttpChannel.
312-317: LGTM! Attribute keys are properly scoped and typed.The three attribute keys use consistent naming ("opensearch-quic-*"), appropriate access modifiers, and correct generic types for type-safe channel attribute storage.
398-467: LGTM! Extension points and compression utilities are well-designed.The extension points (
createHeaderVerifier(),createDecompressor()) provide clean plugin integration. The compression options methods properly exclude ZSTD due to direct buffer requirements and include Brotli conditionally. The comprehensive Javadoc explains the ZSTD exclusion rationale clearly.
352-365: The null-check forhttpServerChannelis not needed.In the HTTP/3 channel hierarchy,
HTTP_SERVER_CHANNEL_KEYis set on the NioDatagramChannel duringbind()via.sync(), which blocks until completion. Since QuicStreamChannels (and their handlers) can only be created after the server is bound, the attribute is guaranteed to be set on the parent channel beforeexceptionCaught()can be triggered. The channel hierarchy ensures a complete parent chain from each stream to the bound server.
231-237: Remove this review comment. No race condition exists in the bind() method.The concern conflates two separate channel handlers that operate sequentially, not concurrently:
configureServerChannelHandler()(line 265) initializes the server's NioDatagramChannel duringbind().sync(), which is a blocking operation (line 232).HttpChannelHandler(line 320) extendsChannelInitializer<QuicStreamChannel>and only handles exceptions in stream channels that are created AFTER the server channel is fully bound and accepting connections.The
HTTP_SERVER_CHANNEL_KEYattribute is set on the server channel (line 235) immediately afterbind().sync()completes. Stream channels—which triggerHttpChannelHandler.exceptionCaught()(line 352)—cannot exist until after this point. Therefore, the attribute is guaranteed to be set before any stream channel exception handler can execute. No null-check is needed.Likely an incorrect or invalid review comment.
|
❌ Gradle check result for 5f93394: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
❌ Gradle check result for 5f93394: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
❌ Gradle check result for 5f93394: null Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
...les/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3RequestCreator.java
Show resolved
Hide resolved
...les/transport-netty4/src/main/java/org/opensearch/http/netty4/Netty4Http3RequestCreator.java
Show resolved
Hide resolved
modules/transport-netty4/src/main/java/org/opensearch/transport/Netty4ModulePlugin.java
Show resolved
Hide resolved
cwperks
left a comment
There was a problem hiding this comment.
Approving as the change is properly feature flagged. Great to see this working!
* Support for HTTP/3 (server side) Signed-off-by: Andriy Redko <drreta@gmail.com> * Provide the SSLEngine carrier capability (using channel attributes) so it could be accessed through Netty4HttpChannel Signed-off-by: Andriy Redko <drreta@gmail.com> --------- Signed-off-by: Andriy Redko <drreta@gmail.com>
* Support for HTTP/3 (server side) Signed-off-by: Andriy Redko <drreta@gmail.com> * Provide the SSLEngine carrier capability (using channel attributes) so it could be accessed through Netty4HttpChannel Signed-off-by: Andriy Redko <drreta@gmail.com> --------- Signed-off-by: Andriy Redko <drreta@gmail.com>
Description
Support for HTTP/3 (server side)
netty4transport (withsecurityplugin)reactor-netty4transport (withsecurityplugin,http.type: reactor-netty4-secure)Related Issues
Part of #4451
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.
Summary by CodeRabbit
New Features
Configuration
Compatibility
Tests
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.