[POC] Server-side integration for xDS - #6797
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds connection-level server configuration, xDS filter-chain matching and downstream TLS resolution, ChangesServer-side xDS plugin with connection-level TLS and filter-chain integration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 19
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java (1)
199-233:⚠️ Potential issue | 🟠 Major | ⚡ Quick winApply per-connection max-age overrides on plaintext connections.
Line 221 uses global
config.maxConnectionAgeMillis()infinishConfigureHttp(...), so values set viaConnectionContext.setMaxConnectionAgeMillis(...)in the acceptor are ignored for non-TLS connections.Suggested fix
private void configureHttp(ChannelPipeline p, `@Nullable` ProxiedAddresses proxiedAddresses) { final Channel ch = p.channel(); final ConnectionContext connectionContext = new ConnectionContext(H1C, "", null, proxiedAddresses, ch); + ch.attr(ConnectionContext.ATTR).set(connectionContext); @@ private void finishConfigureHttp(ChannelPipeline p, ConnectionContext connectionContext) { final long idleTimeoutMillis = config.idleTimeoutMillis(); - final long maxConnectionAgeMillis = config.maxConnectionAgeMillis(); + final long maxConnectionAgeMillis = resolveMaxConnectionAge(p.channel());Also applies to: 253-259
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java` around lines 199 - 233, configureHttp/finishConfigureHttp currently use global config values (e.g., config.maxConnectionAgeMillis(), config.maxNumRequestsPerConnection()) so per-connection overrides set via ConnectionContext.setMaxConnectionAgeMillis(...) are ignored for plaintext connections; change finishConfigureHttp to read the effective values from the provided ConnectionContext (e.g., use connectionContext.maxConnectionAgeMillis() and connectionContext.maxNumRequestsPerConnection(), falling back to config.* if those are unset) before calling needsKeepAliveHandler and when constructing Http1ServerKeepAliveHandler so the per-connection overrides are honored (also apply the same change to the later block referenced around the second occurrence).
🧹 Nitpick comments (2)
core/src/test/java/com/linecorp/armeria/server/ServerTlsProviderTest.java (1)
148-156: ⚡ Quick winExercise the null-provider fallback, not just
build().
TlsProvider.of(TlsKeyPair.ofSelfSigned())never returnsnull, so this never hits thetls()fallback, and the server is never started or used for a TLS handshake. A regression inFallbackServerTlsProviderwould still pass here. Use a provider that returnsnullfor at least one hostname and assert the negotiated certificate over HTTPS.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/test/java/com/linecorp/armeria/server/ServerTlsProviderTest.java` around lines 148 - 156, The test currently uses a non-null provider so it never exercises the tls() fallback; update ServerTlsProviderTest.allowTlsProviderWithTlsSettings() to use a TlsProvider implementation (or a FallbackServerTlsProvider configuration) that returns null for at least one hostname so the Server will fall back to tls(TlsKeyPair.ofSelfSigned()), start the server (call server.start() or ensure it accepts requests), perform an HTTPS request against that hostname, and assert the negotiated certificate is the self-signed one; keep references to Server.builder(), tls(), tlsProvider(TlsProvider), and the test method name to locate where to change.xds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.java (1)
122-130: ⚡ Quick winConsider including filter chain snapshots in debug output.
The
toDebugString()method does not includefilterChainSnapshotsordefaultFilterChainSnapshot, whiletoString()does (lines 117-118). Including these in the debug string would provide more complete debugging information.📋 Proposed addition to debug output
`@Override` public String toDebugString() { return MoreObjects.toStringHelper(this) .omitNullValues() .add("listener", listenerXdsResource.resource()) .add("routeSnapshot", SnapshotUtil.debugString(routeSnapshot, RouteSnapshot::toDebugString)) + .add("filterChainSnapshots", filterChainSnapshots) + .add("defaultFilterChainSnapshot", defaultFilterChainSnapshot) .toString(); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.java` around lines 122 - 130, The toDebugString() implementation in ListenerSnapshot omits filterChainSnapshots and defaultFilterChainSnapshot (present in toString()), so update ListenerSnapshot.toDebugString() to also include these fields: add entries for "filterChainSnapshots" with SnapshotUtil.debugString(filterChainSnapshots, FilterChainSnapshot::toDebugString) and "defaultFilterChainSnapshot" with defaultFilterChainSnapshot (or SnapshotUtil.debugString if needed) alongside the existing listenerXdsResource.resource() and routeSnapshot entries to produce a more complete debug output.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@core/src/main/java/com/linecorp/armeria/internal/server/DefaultServiceRequestContext.java`:
- Around line 269-272: Add a Javadoc comment to the public method
connectionContext() in class DefaultServiceRequestContext explaining what it
returns (the associated ConnectionContext for this request), any
threading/ownership assumptions or lifecycle notes (e.g., non-null and valid for
the lifetime of the request context), and include the `@return` tag describing the
ConnectionContext; reference the method name connectionContext() and the class
DefaultServiceRequestContext when locating where to add the comment.
- Around line 264-267: The channel() accessor is wrongly annotated `@Nullable`
despite ch being required non-null in the constructor; remove the `@Nullable`
annotation from the channel() method (or replace it with a non-null annotation
if your codebase uses one) so the signature correctly reflects that channel()
always returns a non-null Channel; locate the method named channel() and the ch
field/constructor check to make the change.
In `@core/src/main/java/com/linecorp/armeria/server/ConnectionContext.java`:
- Around line 63-64: Add explicit null checks using Objects.requireNonNull(...,
"...") for all public API parameters in ConnectionContext: at minimum add
Objects.requireNonNull(channel, "channel") at the start of public static
ConnectionContext get(Channel channel), and likewise add
Objects.requireNonNull(...) for the user-facing parameters in the other public
methods shown around lines 143 and 150 (use the exact parameter names from those
method signatures and provide clear messages), so each public method validates
its inputs with the required project convention.
- Around line 113-121: The two methods localAddress() and remoteAddress() should
not cast channel.localAddress()/channel.remoteAddress() directly to
InetSocketAddress because domain-socket channels can return other SocketAddress
types; change both method signatures to return java.net.SocketAddress (remove
the direct cast and return channel.localAddress()/channel.remoteAddress() as-is)
and add optional helpers like inetLocalAddress()/inetRemoteAddress() that
perform an instanceof check and return an InetSocketAddress or null (or
Optional<InetSocketAddress>) to preserve callers that need InetSocketAddress
while avoiding ClassCastException.
In `@core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java`:
- Around line 170-178: The constructor for DefaultServerConfig must enforce the
HTTPS wiring invariant: ensure serverTlsProvider and sslContextFactory are
either both non-null or both null; if one is null and the other is non-null,
throw an IllegalArgumentException describing the mismatch. Add the same
validation to the other constructor/overload referenced around lines 285-296 so
the class cannot be constructed into a partially-populated HTTPS state (check
the serverTlsProvider and sslContextFactory parameters in those constructors and
reject the XOR case).
In
`@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java`:
- Around line 207-212: The acceptor callback currently only closes the channel
when accepted equals Boolean.FALSE, allowing null to be treated as acceptance;
change the logic in the whenCompleteAsync handler for
acceptor.accept(connectionContext) to treat any non-TRUE result as rejection by
using a strict Boolean.TRUE check (i.e., replace the
Boolean.FALSE.equals(accepted) check with !Boolean.TRUE.equals(accepted)) so
that on (t != null || !Boolean.TRUE.equals(accepted)) you call ch.close(),
otherwise call finishConfigureHttp(p, connectionContext).
In `@core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java`:
- Around line 348-349: The new public API methods ports() and
connectionAcceptor() in ServerBuilder are missing the required `@UnstableApi`
annotation; update their declarations to add the `@UnstableApi` annotation (same
as other newly added methods) so both ServerBuilder.ports() and
ServerBuilder.connectionAcceptor() are annotated accordingly and import the
annotation if missing.
In `@core/src/main/java/com/linecorp/armeria/server/ServerTlsProvider.java`:
- Around line 51-62: The Javadoc for ServerTlsProvider.serverTlsSpec is
incorrect: the method must never return null but must return a non-null
CompletableFuture that may complete with null to indicate fallthrough; update
the doc to state “returns a non-null CompletableFuture that completes with a
ServerTlsSpec or with null to indicate this provider does not handle the
connection,” and mention examples like FallbackServerTlsProvider which expect a
non-null future; ensure the contract clearly requires implementations
(serverTlsSpec) to return CompletableFuture.completedFuture(null) for
fallthrough rather than returning null.
In
`@core/src/main/java/com/linecorp/armeria/server/ServiceRequestContextBuilder.java`:
- Around line 246-247: The synthetic ConnectionContext is being created with
null proxied addresses causing ctx.connectionContext().proxiedAddresses() to be
incorrect; in ServiceRequestContextBuilder replace the null proxied-address
argument when constructing new ConnectionContext(...) with the resolved
proxiedAddresses variable (i.e. new ConnectionContext(sessionProtocol(), "",
proxiedAddresses, null, ch) or the correct parameter position for proxied
addresses), ensuring the existing proxiedAddresses field is passed through to
the ConnectionContext constructor.
In
`@core/src/main/java/com/linecorp/armeria/server/ServiceRequestContextWrapper.java`:
- Around line 78-81: Add a Javadoc comment to the public method
ServiceRequestContextWrapper.connectionContext() describing that it returns the
current ConnectionContext and that the implementation delegates to
unwrap().connectionContext(); include a brief description, an `@return` tag
specifying it returns the ConnectionContext for this request, and note that it
forwards to the underlying context via unwrap() so callers understand
delegation.
In `@core/src/main/java/com/linecorp/armeria/server/StaticTlsProvider.java`:
- Around line 69-82: The mapping currently keys TLS specs only by
originalHostnamePattern (in buildMapping) which collapses different
ServerTlsSpec for the same hostname on different ports; change the key to
include the listening port (e.g., combine vh.originalHostnamePattern() with the
ServerPort or its port number) when calling builder.add in buildMapping (and/or
maintain a separate DomainWildcardMappingBuilder per ServerPort), and update the
resolution logic that reads ctx.sniHostname() (the StaticTlsProvider lookup code
around lines 90–97) to lookup by the same port+hostname composite key (extract
the port from the channel/ctx/local address or ServerPort context) so each
port+hostname maps to its own ServerTlsSpec.
In
`@it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.java`:
- Around line 167-173: In ServerMultiplePluginTest, avoid brittle root-cause
assertion on TLS handshake failures: update the assertion on the
client3.execute(...) call to only assert the outer exception type
(UnprocessedRequestException) and remove the
hasRootCauseInstanceOf(SignatureException.class) check so the test does not
depend on provider/JDK-specific TLS exception types.
- Around line 133-139: The test currently assumes ordering from
server.server().activePorts() maps ports to certs; instead, probe each HTTPS
port (from ServerPort entries filtered by ServerPort::hasHttps and mapped via
localAddress().getPort()) by attempting TLS connections using both ClientTlsSpec
variants for cert1 and cert2, record which ClientTlsSpec succeeds for each port,
and then assert that one port accepts cert1 and the other accepts cert2; update
ServerMultiplePluginTest to replace the index-based httpsPorts.get(...) checks
with this probe-and-map approach (use the existing ClientTlsSpec instances and
the test helper that makes a TLS request to a port to determine success).
In
`@it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.java`:
- Around line 33-41: Add Javadoc comments for the public class
XdsEchoConfigurator and its public override method reconfigure(ServerBuilder
sb): document the purpose of XdsEchoConfigurator (what it configures, e.g., sets
up the test echo server, constants like LISTENER_NAME and SERVER_PORT) and
describe the behavior and parameters of reconfigure(ServerBuilder sb) (what the
ServerBuilder is configured to do and any side effects). Keep comments concise,
include `@param` for the ServerBuilder parameter and `@throws` if the method can
throw checked exceptions, and follow the project's Javadoc style.
In `@xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java`:
- Around line 220-254: ResolvedFilterChain.matches(): the server_name
restriction currently only runs when sniHostname is non-empty, allowing chains
with configured serverNames to match connections that provide no SNI; change the
logic using filterChainMatch.getServerNamesList()/serverNames and sniHostname so
that if serverNames is non-empty and sniHostname is empty the method returns
false, and otherwise require serverNames.contains(sniHostname) to match; update
the block that references serverNames/sniHostname so it reads: if
(!serverNames.isEmpty()) { if (sniHostname.isEmpty() ||
!serverNames.contains(sniHostname)) return false; }.
In `@xds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.java`:
- Around line 182-202: The server mTLS code in buildServerTlsSpec currently sets
ClientAuth.REQUIRE without mirroring the client-side handling of trusted CA /
verifier factories and system-root/no-verify semantics; update
buildServerTlsSpec (and ServerTlsSpecBuilder usage) so that when
DownstreamTlsTransportSocketFactory.requireClientCertificate(...) is true you
only set clientAuth and the trust configuration in the same way
buildClientTlsSpec does: copy trustedCertificates from
validationContext.trustedCa when present, apply
validationContext.peerVerifierFactories() (SPKI/hash/SAN match verifiers) to the
ServerTlsSpec so server-side verifierFactories are used, and handle the
validationContext cases for system_root_certs or “no-verify” exactly as the
client path does instead of relying on JVM default trust managers; in short,
reuse or mirror the client-side trust-selection logic (trustedCa,
peerVerifierFactories, system-root/no-verify handling) when constructing the
ServerTlsSpec in buildServerTlsSpec so server mTLS semantics match client mTLS
semantics.
In `@xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java`:
- Around line 131-142: Add Javadoc to the public install(ServerBuilder sb)
method (in class XdsServerPlugin) describing its behavior: explain that it
blocks until the first xDS snapshot is resolved by calling
watcher.whenReady().get(readyTimeout.toMillis(), TimeUnit.MILLISECONDS), state
what happens when the timeout is exceeded (throws RuntimeException wrapping the
caught exception), and note that after readiness it registers configured server
ports (serverPorts) with the provided ServerBuilder and installs xDS-related
policies/decorators; ensure the Javadoc mentions the method implements
ServerPlugin.install and documents parameters and thrown behavior concisely.
- Around line 187-190: The public close() method in XdsServerPlugin lacks
Javadoc; add a Javadoc comment above the close() method in class XdsServerPlugin
that states this method closes the underlying xDS listener and cleans up
resources (e.g., "Closes the underlying xDS listener and releases any associated
resources."), mention any important behavior such as idempotence or exceptions
if applicable, and reference listenerRoot as the resource being closed.
- Around line 72-106: Add Javadoc for all public XdsServerPlugin constructors:
document the constructor that takes (XdsBootstrap, String listenerName) as
creating a plugin that subscribes to the named xDS listener and listens on an
ephemeral port (HTTP/HTTPS) and indicate the DEFAULT_READY_TIMEOUT used;
document the (XdsBootstrap, String listenerName, int... ports) overload and
explain that the varargs ports are converted via toServerPorts(...) and
represent numeric ports to listen on; document the (XdsBootstrap, String
listenerName, ServerPort) overload and clarify that ServerPort allows explicit
SessionProtocol settings; and document the (XdsBootstrap, String listenerName,
ServerPort, Duration readyTimeout) overload including the readyTimeout behavior
(how long to wait for the first xDS snapshot before starting) and that the other
constructors delegate to it. Include `@param` entries for bootstrap, listenerName
(purpose), ports/ serverPort, readyTimeout (units and default), and a brief
`@throws` or `@see` if applicable.
---
Outside diff comments:
In
`@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java`:
- Around line 199-233: configureHttp/finishConfigureHttp currently use global
config values (e.g., config.maxConnectionAgeMillis(),
config.maxNumRequestsPerConnection()) so per-connection overrides set via
ConnectionContext.setMaxConnectionAgeMillis(...) are ignored for plaintext
connections; change finishConfigureHttp to read the effective values from the
provided ConnectionContext (e.g., use connectionContext.maxConnectionAgeMillis()
and connectionContext.maxNumRequestsPerConnection(), falling back to config.* if
those are unset) before calling needsKeepAliveHandler and when constructing
Http1ServerKeepAliveHandler so the per-connection overrides are honored (also
apply the same change to the later block referenced around the second
occurrence).
---
Nitpick comments:
In `@core/src/test/java/com/linecorp/armeria/server/ServerTlsProviderTest.java`:
- Around line 148-156: The test currently uses a non-null provider so it never
exercises the tls() fallback; update
ServerTlsProviderTest.allowTlsProviderWithTlsSettings() to use a TlsProvider
implementation (or a FallbackServerTlsProvider configuration) that returns null
for at least one hostname so the Server will fall back to
tls(TlsKeyPair.ofSelfSigned()), start the server (call server.start() or ensure
it accepts requests), perform an HTTPS request against that hostname, and assert
the negotiated certificate is the self-signed one; keep references to
Server.builder(), tls(), tlsProvider(TlsProvider), and the test method name to
locate where to change.
In `@xds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.java`:
- Around line 122-130: The toDebugString() implementation in ListenerSnapshot
omits filterChainSnapshots and defaultFilterChainSnapshot (present in
toString()), so update ListenerSnapshot.toDebugString() to also include these
fields: add entries for "filterChainSnapshots" with
SnapshotUtil.debugString(filterChainSnapshots,
FilterChainSnapshot::toDebugString) and "defaultFilterChainSnapshot" with
defaultFilterChainSnapshot (or SnapshotUtil.debugString if needed) alongside the
existing listenerXdsResource.resource() and routeSnapshot entries to produce a
more complete debug output.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a6ea0757-a07d-4bf4-acde-2831345667a4
📒 Files selected for processing (60)
benchmarks/jmh/benchmarks/jmh/build/results/jmh/aggregate-results.txtbenchmarks/jmh/run-benchmark.shcore/src/main/java/com/linecorp/armeria/internal/server/DefaultServiceRequestContext.javacore/src/main/java/com/linecorp/armeria/server/ConnectionAcceptHandler.javacore/src/main/java/com/linecorp/armeria/server/ConnectionAcceptor.javacore/src/main/java/com/linecorp/armeria/server/ConnectionContext.javacore/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.javacore/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.javacore/src/main/java/com/linecorp/armeria/server/FallbackServerTlsProvider.javacore/src/main/java/com/linecorp/armeria/server/Http2ServerConnectionHandler.javacore/src/main/java/com/linecorp/armeria/server/HttpServerHandler.javacore/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.javacore/src/main/java/com/linecorp/armeria/server/Server.javacore/src/main/java/com/linecorp/armeria/server/ServerBuilder.javacore/src/main/java/com/linecorp/armeria/server/ServerPlugin.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsConfig.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsConfigBuilder.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsProvider.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsSpec.javacore/src/main/java/com/linecorp/armeria/server/ServiceRequestContext.javacore/src/main/java/com/linecorp/armeria/server/ServiceRequestContextBuilder.javacore/src/main/java/com/linecorp/armeria/server/ServiceRequestContextWrapper.javacore/src/main/java/com/linecorp/armeria/server/StaticTlsProvider.javacore/src/main/java/com/linecorp/armeria/server/TlsProviderAdapter.javacore/src/main/java/com/linecorp/armeria/server/TlsProviderMapping.javacore/src/main/java/com/linecorp/armeria/server/UpdatableServerConfig.javacore/src/main/java/com/linecorp/armeria/server/VirtualHost.javacore/src/main/java/com/linecorp/armeria/server/VirtualHostBuilder.javacore/src/test/java/com/linecorp/armeria/server/ServerTlsProviderTest.javacore/src/test/java/com/linecorp/armeria/server/TlsProviderMappingTest.javacore/src/test/java/com/linecorp/armeria/server/VirtualHostAnnotatedServiceBindingBuilderTest.javacore/src/test/java/com/linecorp/armeria/server/VirtualHostBuilderTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiPortTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.javait/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactoryit/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.javait/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.javaxds-api/src/main/proto/envoy/config/listener/v3/listener.protoxds-api/src/main/proto/envoy/config/listener/v3/listener_components.protoxds-api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.protoxds/docs/SERVER_DESIGN.mdxds/docs/SERVER_PROPOSAL.mdxds/src/main/java/com/linecorp/armeria/xds/DelegatingHttpService.javaxds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.javaxds/src/main/java/com/linecorp/armeria/xds/FilterChainSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/FilterUtil.javaxds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/ListenerStream.javaxds/src/main/java/com/linecorp/armeria/xds/ParsedFilterChain.javaxds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.javaxds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/XdsExtensionRegistry.javaxds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.javaxds/src/main/java/com/linecorp/armeria/xds/filter/XdsHttpFilter.java
💤 Files with no reviewable changes (2)
- core/src/test/java/com/linecorp/armeria/server/TlsProviderMappingTest.java
- core/src/main/java/com/linecorp/armeria/server/TlsProviderMapping.java
| @Override | ||
| public ConnectionContext connectionContext() { | ||
| return connectionContext; | ||
| } |
There was a problem hiding this comment.
Add Javadoc for the new public method.
The connectionContext() method is public and requires Javadoc documentation. As per coding guidelines, all public and protected methods must have Javadoc.
📝 Suggested Javadoc
+ /**
+ * Returns the {`@link` ConnectionContext} for this request.
+ */
`@Override`
public ConnectionContext connectionContext() {As per coding guidelines: "ensure all public classes and public/protected methods have Javadoc."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Override | |
| public ConnectionContext connectionContext() { | |
| return connectionContext; | |
| } | |
| /** | |
| * Returns the {`@link` ConnectionContext} for this request. | |
| */ | |
| `@Override` | |
| public ConnectionContext connectionContext() { | |
| return connectionContext; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@core/src/main/java/com/linecorp/armeria/internal/server/DefaultServiceRequestContext.java`
around lines 269 - 272, Add a Javadoc comment to the public method
connectionContext() in class DefaultServiceRequestContext explaining what it
returns (the associated ConnectionContext for this request), any
threading/ownership assumptions or lifecycle notes (e.g., non-null and valid for
the lifetime of the request context), and include the `@return` tag describing the
ConnectionContext; reference the method name connectionContext() and the class
DefaultServiceRequestContext when locating where to add the comment.
| public static ConnectionContext get(Channel channel) { | ||
| return channel.attr(ATTR).get(); |
There was a problem hiding this comment.
Add explicit null checks for new public API parameters.
Line 63, Line 143, and Line 150 accept user-facing parameters without requireNonNull(...), which weakens error messages and violates the project’s public API validation convention.
Suggested fix
`@Nullable`
public static ConnectionContext get(Channel channel) {
+ requireNonNull(channel, "channel");
return channel.attr(ATTR).get();
}
@@
`@Nullable`
public <T> T attr(AttributeKey<T> key) {
+ requireNonNull(key, "key");
return attrs.attr(key);
}
@@
public <T> void setAttr(AttributeKey<T> key, `@Nullable` T value) {
+ requireNonNull(key, "key");
attrs.set(key, value);
}As per coding guidelines: "use Objects.requireNonNull(..., "...") for explicit null checks on user-facing public parameters."
Also applies to: 143-151
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@core/src/main/java/com/linecorp/armeria/server/ConnectionContext.java` around
lines 63 - 64, Add explicit null checks using Objects.requireNonNull(..., "...")
for all public API parameters in ConnectionContext: at minimum add
Objects.requireNonNull(channel, "channel") at the start of public static
ConnectionContext get(Channel channel), and likewise add
Objects.requireNonNull(...) for the user-facing parameters in the other public
methods shown around lines 143 and 150 (use the exact parameter names from those
method signatures and provide clear messages), so each public method validates
its inputs with the required project convention.
| @Nullable ServerTlsProvider serverTlsProvider, | ||
| @Nullable SslContextFactory sslContextFactory, | ||
| Http1HeaderNaming http1HeaderNaming, | ||
| DependencyInjector dependencyInjector, | ||
| Function<? super String, String> absoluteUriTransformer, | ||
| long unloggedExceptionsReportIntervalMillis, | ||
| List<ShutdownSupport> shutdownSupports, | ||
| @Nullable Function<? super String, ? extends EventLoopGroup> bossGroupFactory) { | ||
| @Nullable Function<? super String, ? extends EventLoopGroup> bossGroupFactory, | ||
| @Nullable ConnectionAcceptor connectionAcceptor) { |
There was a problem hiding this comment.
Validate the HTTPS wiring invariant in the config constructor.
core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java, Lines 261-268, assumes serverTlsProvider and sslContextFactory are present together and only protects that with assert. This constructor now allows them to diverge, so a partially populated DefaultServerConfig will survive construction and fail later on the HTTPS path once assertions are off. Reject that partial state here.
Suggested invariant check
this.errorHandler = requireNonNull(errorHandler, "errorHandler");
+ if ((serverTlsProvider == null) != (sslContextFactory == null)) {
+ throw new IllegalArgumentException(
+ "serverTlsProvider and sslContextFactory must be set together");
+ }
this.serverTlsProvider = serverTlsProvider;
this.sslContextFactory = sslContextFactory;Also applies to: 285-296
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java`
around lines 170 - 178, The constructor for DefaultServerConfig must enforce the
HTTPS wiring invariant: ensure serverTlsProvider and sslContextFactory are
either both non-null or both null; if one is null and the other is non-null,
throw an IllegalArgumentException describing the mismatch. Add the same
validation to the other constructor/overload referenced around lines 285-296 so
the class cannot be constructed into a partially-populated HTTPS state (check
the serverTlsProvider and sslContextFactory parameters in those constructors and
reject the XOR case).
| boolean matches(int destinationPort, String transportProtocol, | ||
| String sniHostname, @Nullable List<String> alpnProtocols) { | ||
| if (filterChainMatch.hasDestinationPort() && | ||
| filterChainMatch.getDestinationPort().getValue() != destinationPort) { | ||
| return false; | ||
| } | ||
|
|
||
| final String matchTransport = filterChainMatch.getTransportProtocol(); | ||
| if (!matchTransport.isEmpty() && !matchTransport.equals(transportProtocol)) { | ||
| return false; | ||
| } | ||
|
|
||
| final List<String> serverNames = filterChainMatch.getServerNamesList(); | ||
| if (!serverNames.isEmpty() && !sniHostname.isEmpty()) { | ||
| if (!serverNames.contains(sniHostname)) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| final List<String> matchAlpn = filterChainMatch.getApplicationProtocolsList(); | ||
| if (!matchAlpn.isEmpty() && alpnProtocols != null) { | ||
| boolean found = false; | ||
| for (String offered : alpnProtocols) { | ||
| if (matchAlpn.contains(offered)) { | ||
| found = true; | ||
| break; | ||
| } | ||
| } | ||
| if (!found) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
How does Envoy filter chain matching handle server_names when SNI is not provided by the client?
💡 Result:
In Envoy, the server_name field in a filter_chain_match specifically refers to the SNI (Server Name Indication) extracted during a TLS handshake [1][2]. When a client does not provide SNI—or when the connection is not TLS—Envoy cannot populate this field [3][4]. How Envoy handles connections missing an SNI depends on your filter chain configuration: 1. Matching Behavior: If you configure a filter chain with a server_names requirement, Envoy will only select that filter chain if the SNI matches one of the specified values [1][2]. If no SNI is provided, that specific filter chain will not be selected [5]. 2. Default/Fallback Chains: To handle connections without an SNI (or with an unknown SNI), you must define a catch-all filter chain that does not include a server_names requirement [5][1]. Envoy prioritizes more specific matches; if an incoming connection does not have an SNI, it will fall back to a filter chain where server_names is omitted (left empty), as this is treated as the least specific match [1][2]. 3. Detecting Missing SNI: Because filter chain matching is a static selection process based on available metadata, you cannot explicitly match against an "empty" SNI within the filter_chain_match criteria [6][5]. To handle these cases, you should: - Provide a default filter chain without a server_names field to capture traffic that fails to match your specific SNI-based chains [5]. - If you need to distinguish between connections with and without SNI for logic later in the filter stack, you can use a regular expression match on server_names (e.g., ^.+$) in a specific chain to capture all connections where SNI is present, leaving a separate, non-matching chain to handle the rest [6]. In summary, when SNI is missing, Envoy simply skips any filter chain that requires a specific server_name and proceeds to evaluate other available chains. If no non-server-name-restricted chain exists, the connection will fail with a "no matching filter chain found" error [5].
Citations:
- 1: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener_components.proto.html?highlight=filterchainmatch
- 2: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener_components.proto.html
- 3: filter_chain_match.server_names is not working for TCP filter envoyproxy/envoy#3615
- 4: http inspector filter is not filling
server_nameenvoyproxy/envoy#22612 - 5: Connecting with IP when the listener is configured with SNI envoyproxy/envoy#15869
- 6: How to detect if server_name is populated for TLS transport protocol envoyproxy/envoy#37256
🏁 Script executed:
#!/bin/bash
set -euo pipefail
repo_root="$(pwd)"
file="xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java"
# Show the matches method and surrounding call site context
python3 - <<PY
import itertools,sys
path="${file}"
start=130
end=280
with open(path,'r',encoding='utf-8') as f:
for i,line in enumerate(f, start=1):
if start <= i <= end:
sys.stdout.write(f"{i:5d}:{line}")
PY
# Also locate ctx.sniHostname() definition / usage in this file
rg -n "sniHostname\\(" "$file" || true
rg -n "getServerNamesList\\(" "$file" || trueRepository: line/armeria
Length of output: 6320
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file="xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java"
python3 - <<'PY'
import sys
path="xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java"
start=140
end=270
with open(path,'r',encoding='utf-8') as f:
for lineno,line in enumerate(f, start=1):
if start <= lineno <= end:
sys.stdout.write(f"{lineno:5d}:{line}")
PY
echo "---- sniHostname usages ----"
rg -n "sniHostname" "$file" || true
echo "---- serverNamesList usages ----"
rg -n "getServerNamesList" "$file" || trueRepository: line/armeria
Length of output: 6169
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file="xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java"
python3 - <<'PY'
import sys
path="xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java"
start=140
end=270
with open(path,'r',encoding='utf-8') as f:
for lineno,line in enumerate(f, start=1):
if start <= lineno <= end:
sys.stdout.write(f"{lineno:5d}:{line}")
PY
echo "---- sniHostname usages ----"
rg -n "sniHostname" "$file" || true
echo "---- serverNamesList usages ----"
rg -n "getServerNamesList" "$file" || trueRepository: line/armeria
Length of output: 6169
Fix SNI server_names matching when SNI is missing
In ResolvedFilterChain.matches() the serverNames restriction only runs when !sniHostname.isEmpty() (lines 232-237). If a filter chain specifies server_names but the connection provides no SNI (empty sniHostname), the match currently “passes” by default, which diverges from Envoy’s behavior (server_name-restricted chains are skipped when SNI isn’t provided).
- Adjust logic so that when
serverNamesis non-empty, an emptysniHostnamecausesreturn falseunless it matches one of the configured names.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java` around
lines 220 - 254, ResolvedFilterChain.matches(): the server_name restriction
currently only runs when sniHostname is non-empty, allowing chains with
configured serverNames to match connections that provide no SNI; change the
logic using filterChainMatch.getServerNamesList()/serverNames and sniHostname so
that if serverNames is non-empty and sniHostname is empty the method returns
false, and otherwise require serverNames.contains(sniHostname) to match; update
the block that references serverNames/sniHostname so it reads: if
(!serverNames.isEmpty()) { if (sniHostname.isEmpty() ||
!serverNames.contains(sniHostname)) return false; }.
| @Override | ||
| public void install(ServerBuilder sb) { | ||
| // Block until the first xDS snapshot is resolved so TLS and decorators | ||
| // are available before the server is built. | ||
| try { | ||
| watcher.whenReady().get(readyTimeout.toMillis(), TimeUnit.MILLISECONDS); | ||
| } catch (Exception e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| for (ServerPort serverPort : serverPorts) { | ||
| sb.port(serverPort); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Add Javadoc to public install method.
The install(ServerBuilder) method is public (from ServerPlugin interface) and lacks Javadoc. As per coding guidelines, all public methods should have Javadoc.
Add Javadoc describing:
- That this method blocks until the first xDS snapshot is resolved
- The behavior when the timeout is exceeded
- The registration of server ports and xDS policies
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java` around lines
131 - 142, Add Javadoc to the public install(ServerBuilder sb) method (in class
XdsServerPlugin) describing its behavior: explain that it blocks until the first
xDS snapshot is resolved by calling
watcher.whenReady().get(readyTimeout.toMillis(), TimeUnit.MILLISECONDS), state
what happens when the timeout is exceeded (throws RuntimeException wrapping the
caught exception), and note that after readiness it registers configured server
ports (serverPorts) with the provided ServerBuilder and installs xDS-related
policies/decorators; ensure the Javadoc mentions the method implements
ServerPlugin.install and documents parameters and thrown behavior concisely.
| @Override | ||
| public void close() { | ||
| listenerRoot.close(); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Add Javadoc to public close method.
The close() method is public and lacks Javadoc. As per coding guidelines, all public methods should have Javadoc.
Add Javadoc describing that this method closes the underlying xDS listener and cleans up resources.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java` around lines
187 - 190, The public close() method in XdsServerPlugin lacks Javadoc; add a
Javadoc comment above the close() method in class XdsServerPlugin that states
this method closes the underlying xDS listener and cleans up resources (e.g.,
"Closes the underlying xDS listener and releases any associated resources."),
mention any important behavior such as idempotence or exceptions if applicable,
and reference listenerRoot as the resource being closed.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #6797 +/- ##
============================================
+ Coverage 74.46% 75.12% +0.65%
- Complexity 22234 25261 +3027
============================================
Files 1963 2247 +284
Lines 82437 93766 +11329
Branches 10764 12258 +1494
============================================
+ Hits 61385 70438 +9053
- Misses 15918 17499 +1581
- Partials 5134 5829 +695 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java (1)
213-225:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftCleartext connections never honor per-connection max-age overrides.
The keep-alive handler is built before
DefaultConnectionAcceptorfinishes, so anyconnectionContext.setMaxConnectionAgeMillis(...)done during acceptance cannot affect H1C/H2C connection lifetime. HTTPS resolves max age after the accept/TLS phase, but the cleartext path hard-codesconfig.maxConnectionAgeMillis()here.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java` around lines 213 - 225, The cleartext HTTP keep-alive handler is created using config.maxConnectionAgeMillis() before DefaultConnectionAcceptor can apply per-connection overrides, so H1C/H2C never observe connectionContext.setMaxConnectionAgeMillis(...); change the flow in HttpServerPipelineConfigurator to defer creating the Http1ServerKeepAliveHandler (and the H2C equivalent) until after acceptance or to construct it using the resolved value from the ConnectionContext at accept time (e.g., read connectionContext.getMaxConnectionAgeMillis() or pass a supplier that queries the context) instead of using config.maxConnectionAgeMillis(); ensure needsKeepAliveHandler still uses the runtime values via needsKeepAliveHandler(..., connectionContext.getPingIntervalMillis(), connectionContext.getMaxConnectionAgeMillis(), ...) and replace direct newKeepAliveTimer/H1C-bound creation with a post-accept creation point referenced from DefaultConnectionAcceptor/connectionContext so per-connection overrides take effect.
♻️ Duplicate comments (2)
core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java (1)
283-285:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnforce the TLS-provider/SSL-factory pair invariant here.
HttpServerPipelineConfigurator.configureHttps()assumes these are either both set or both null and only protects that withassert. A partially populatedDefaultServerConfigwill survive construction and then fail later on the HTTPS path once assertions are off. Reject the XOR case in this constructor.Suggested fix
this.errorHandler = requireNonNull(errorHandler, "errorHandler"); + if ((serverTlsProvider == null) != (sslContextFactory == null)) { + throw new IllegalArgumentException( + "serverTlsProvider and sslContextFactory must be set together"); + } this.serverTlsProvider = serverTlsProvider; this.sslContextFactory = sslContextFactory;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java` around lines 283 - 285, Enforce the invariant in the DefaultServerConfig constructor that serverTlsProvider and sslContextFactory are either both non-null or both null: detect the XOR case (serverTlsProvider == null ^ sslContextFactory == null) and throw an IllegalArgumentException with a clear message, so construction fails fast instead of letting HttpServerPipelineConfigurator.configureHttps rely on an assert later.xds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.java (1)
182-202:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMirror
buildClientTlsSpec()'s trust handling here.
buildServerTlsSpec()still only appliestrustedCa()andClientAuth.REQUIRE. It dropspeerVerifierFactories(),system_root_certs, and the xDS no-verify fallback, so the sameCertificateValidationContextSnapshotcan produce different mTLS behavior on the downstream/server path than it does on the upstream/client path.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.java` around lines 182 - 202, buildServerTlsSpec currently only applies trustedCa() and ClientAuth.REQUIRE and therefore diverges from buildClientTlsSpec's trust handling; update buildServerTlsSpec to mirror buildClientTlsSpec by also honoring CertificateValidationContextSnapshot.peerVerifierFactories(), the system-root-certs flag (e.g., useSystemTrust()/systemRootCerts), and the no-verify fallback so downstream/server mTLS behavior matches upstream/client behavior, while still calling DownstreamTlsTransportSocketFactory.requireClientCertificate(...) for clientAuth; locate buildServerTlsSpec, buildClientTlsSpec, and CertificateValidationContextSnapshot methods (trustedCa(), peerVerifierFactories(), system root flag, and no-verify indicator) and apply the same trust-building logic and fallbacks used in buildClientTlsSpec when building the ServerTlsSpec.
🧹 Nitpick comments (10)
xds/docs/SERVER_DESIGN.md (6)
149-151: 💤 Low valueAdd language specifier to fenced code block.
The decorator ordering example should specify a language for proper rendering.
📝 Proposed fix
-``` +```text [xDS RBAC] → [xDS authn] → [user's service decorators] → service🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` around lines 149 - 151, The fenced code block containing the decorator ordering example ("[xDS RBAC] → [xDS authn] → [user's service decorators] → service") is missing a language specifier; update the triple-backtick fence to include a language (e.g., change ``` to ```text) so the block renders correctly, locating the fenced block that wraps that exact string in SERVER_DESIGN.md and adding the language token.
53-70: 💤 Low valueAdd language specifier to fenced code block.
The schema block should specify a language for proper syntax highlighting and rendering.
📝 Proposed fix
-``` +```text Listener (name: "inbound_0.0.0.0_8080")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` around lines 53 - 70, The fenced code block showing the Listener/FilterChain schema lacks a language specifier; update the opening fence for that block to include a language (e.g., "text" or "yaml") so it renders with proper highlighting—locate the block that begins with the Listener (name: "inbound_0.0.0.0_8080") and modify the opening ``` to ```text (or another appropriate language) while leaving the block contents unchanged.
72-72: 💤 Low valueRemove extra space after hash in heading.
📝 Proposed fix
-### Sample listener +### Sample listener🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` at line 72, The markdown heading "### Sample listener" contains an extra space after the hashes; update that heading to a single space as "### Sample listener" (search for the exact string "### Sample listener" in SERVER_DESIGN.md) and ensure other headings do not have double spaces after the hash characters.
289-295: 💤 Low valueAdd language specifier to fenced code block.
The connection/request time flow block should specify a language for proper rendering.
📝 Proposed fix
-``` +```text Connection time (pre-request):🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` around lines 289 - 295, Update the fenced code block that begins with "Connection time (pre-request):" so it includes a language specifier (e.g., change the opening ``` to ```text) to ensure proper rendering; locate the block containing "Connection time (pre-request):" and ":authority + port → VirtualHost → route → service" and add the specifier to the opening fence.
74-94: 💤 Low valueAdd language specifier to fenced code block.
The sample listener block should specify a language for proper rendering.
📝 Proposed fix
-``` +```text xDS Listener (port 8080)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` around lines 74 - 94, Update the fenced code block that begins with "xDS Listener (port 8080)" to include a language specifier so it renders correctly (e.g., replace the opening ``` with ```text); ensure only the opening fence is changed and the closing fence remains ``` so the diagram content and formatting (FilterChain: mTLS, match: transport_protocol="tls", alpn=["istio"], TLS: SDS certs + REQUIRE_CLIENT_CERT, http_filters, router, VirtualHost entries, routes, etc.) are preserved.
171-171: 💤 Low valueUse American English phrasing.
"In future" is British English; "In the future" is more common in technical documentation.
📝 Proposed fix
-In future, we could support dynamically binding ports to listeners via wildcard listener +In the future, we could support dynamically binding ports to listeners via wildcard listener🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` at line 171, Replace the British phrasing "In future" with the American English form "In the future" wherever it appears (specifically the sentence currently starting with "In future") so the technical documentation uses consistent American English phrasing.xds/docs/SERVER_PROPOSAL.md (4)
87-93: 💤 Low valueConsider showing
@UnstableApiannotation in code examples.The document states on line 4 that "All new APIs are annotated
@UnstableApi", but the code examples don't show these annotations. Including them would make the examples more accurate and educational.📝 Suggested enhancement
```java package com.linecorp.armeria.server; +@UnstableApi public interface ServerPlugin extends SafeCloseable { void install(ServerBuilder sb); }</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@xds/docs/SERVER_PROPOSAL.mdaround lines 87 - 93, Add the@UnstableApi
annotation to the API examples so they match the doc text: annotate the
ServerPlugin interface declaration with@UnstableApi(the example that declares
public interface ServerPlugin extends SafeCloseable { void install(ServerBuilder
sb); }) and ensure any necessary import or qualification for@UnstableApiis
present so the example compiles and accurately demonstrates the unstable API
marker.</details> <!-- cr-comment:v1:bfc05bf9e51f0f3c14f4b69f --> --- `10-15`: _💤 Low value_ **Add language specifier to fenced code block.** The builder example should specify a language for proper syntax highlighting. <details> <summary>📝 Proposed fix</summary> ```diff -``` +```java Server.builder()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_PROPOSAL.md` around lines 10 - 15, The fenced code block showing the Server.builder() example lacks a language specifier for syntax highlighting; update the triple-backtick fence before the Server.builder() snippet to include the language (e.g., "java") so the block begins with ```java; ensure the rest of the snippet (the Server.builder() chain, XdsServerPlugin(...) and the comment about plugin.install(sb)) remains unchanged.
151-155: 💤 Low valueAdd language specifier to fenced code block.
The TLS provider chain example should specify a language for proper syntax highlighting.
📝 Proposed fix
-``` +```java sb.tls(keyPair); // fallback — always evaluated last🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_PROPOSAL.md` around lines 151 - 155, The fenced code block showing the TLS provider chain lacks a language specifier; update the block to use a language tag (e.g., "java") so syntax highlighting applies. Locate the fenced block containing sb.tls(keyPair); sb.tlsProvider(tlsProvider); and sb.tlsProvider(serverTlsProvider); and add the language after the opening backticks (for example ```java) to the opening fence and keep the closing fence unchanged.
25-42: 💤 Low valueAdd language specifier to fenced code block.
The connection flow diagram should specify a language for proper rendering.
📝 Proposed fix
-``` +```text Connection arrives🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_PROPOSAL.md` around lines 25 - 42, The fenced code block in SERVER_PROPOSAL.md lacks a language specifier; update the block that contains the connection flow diagram to use a language tag (e.g., "text") so it renders correctly, i.e. change the opening triple backticks to include the specifier for the diagram showing ConnectionAcceptor.accept, ServerTlsProvider.serverTlsSpec, TLS handshake, and XdsRootDecorator.serve.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/src/main/java/com/linecorp/armeria/server/ConnectionContext.java`:
- Around line 177-181: The setter setMaxConnectionAgeMillis in ConnectionContext
should reject negative values (like other duration/age fields) instead of
allowing them to be silently ignored by resolveMaxConnectionAge; add a guard in
setMaxConnectionAgeMillis that validates maxConnectionAgeMillis >= 0 and throws
an IllegalArgumentException with a clear message when negative, so callers fail
fast and behavior matches resolveMaxConnectionAge and the config layer.
In
`@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java`:
- Around line 354-370: The connection-acceptor callback currently auto-unboxes
the boxed Boolean `accepted` inside the whenComplete lambda of
`connectionAcceptor.accept(connectionContext, ch.eventLoop())`, which can throw
a NPE instead of cleanly rejecting a connection; update the conditional that
checks `accepted` to use `Boolean.TRUE.equals(accepted)` (in both cleartext and
TLS acceptor lambdas where `accepted` is inspected) so the gate is fail-closed,
keep the existing handling of `timeoutFuture`, `t`, `ch.close()`, and
`ch.pipeline().remove(this)` unchanged otherwise.
- Around line 203-205: The newly created ConnectionContext (constructed in
HttpServerPipelineConfigurator where you call new ConnectionContext(HTTP, ...,
ch)) must be attached to the channel so ConnectionContext.get(ch) can later
retrieve it; modify the code after creating connectionContext to persist it on
the channel (e.g. call the ConnectionContext attach/set API with the channel
variable ch or otherwise store the instance in the channel attributes) so
H1C/H2C connections are visible to lookup-based features just like the HTTPS/SNI
path does.
In
`@it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.java`:
- Around line 1-15: Replace the file header in ServerConnectionConfigTest.java
to match the repository's canonical Java header used elsewhere (use "LY
Corporation" wording and the same static year/format used in this PR instead of
"2025 LINE Corporation"); update the top-of-file comment block so it exactly
matches the existing header template used across the repo (preserve the same
year/token format and license text) to avoid style/check failures.
---
Outside diff comments:
In
`@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java`:
- Around line 213-225: The cleartext HTTP keep-alive handler is created using
config.maxConnectionAgeMillis() before DefaultConnectionAcceptor can apply
per-connection overrides, so H1C/H2C never observe
connectionContext.setMaxConnectionAgeMillis(...); change the flow in
HttpServerPipelineConfigurator to defer creating the Http1ServerKeepAliveHandler
(and the H2C equivalent) until after acceptance or to construct it using the
resolved value from the ConnectionContext at accept time (e.g., read
connectionContext.getMaxConnectionAgeMillis() or pass a supplier that queries
the context) instead of using config.maxConnectionAgeMillis(); ensure
needsKeepAliveHandler still uses the runtime values via
needsKeepAliveHandler(..., connectionContext.getPingIntervalMillis(),
connectionContext.getMaxConnectionAgeMillis(), ...) and replace direct
newKeepAliveTimer/H1C-bound creation with a post-accept creation point
referenced from DefaultConnectionAcceptor/connectionContext so per-connection
overrides take effect.
---
Duplicate comments:
In `@core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java`:
- Around line 283-285: Enforce the invariant in the DefaultServerConfig
constructor that serverTlsProvider and sslContextFactory are either both
non-null or both null: detect the XOR case (serverTlsProvider == null ^
sslContextFactory == null) and throw an IllegalArgumentException with a clear
message, so construction fails fast instead of letting
HttpServerPipelineConfigurator.configureHttps rely on an assert later.
In `@xds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.java`:
- Around line 182-202: buildServerTlsSpec currently only applies trustedCa() and
ClientAuth.REQUIRE and therefore diverges from buildClientTlsSpec's trust
handling; update buildServerTlsSpec to mirror buildClientTlsSpec by also
honoring CertificateValidationContextSnapshot.peerVerifierFactories(), the
system-root-certs flag (e.g., useSystemTrust()/systemRootCerts), and the
no-verify fallback so downstream/server mTLS behavior matches upstream/client
behavior, while still calling
DownstreamTlsTransportSocketFactory.requireClientCertificate(...) for
clientAuth; locate buildServerTlsSpec, buildClientTlsSpec, and
CertificateValidationContextSnapshot methods (trustedCa(),
peerVerifierFactories(), system root flag, and no-verify indicator) and apply
the same trust-building logic and fallbacks used in buildClientTlsSpec when
building the ServerTlsSpec.
---
Nitpick comments:
In `@xds/docs/SERVER_DESIGN.md`:
- Around line 149-151: The fenced code block containing the decorator ordering
example ("[xDS RBAC] → [xDS authn] → [user's service decorators] → service") is
missing a language specifier; update the triple-backtick fence to include a
language (e.g., change ``` to ```text) so the block renders correctly, locating
the fenced block that wraps that exact string in SERVER_DESIGN.md and adding the
language token.
- Around line 53-70: The fenced code block showing the Listener/FilterChain
schema lacks a language specifier; update the opening fence for that block to
include a language (e.g., "text" or "yaml") so it renders with proper
highlighting—locate the block that begins with the Listener (name:
"inbound_0.0.0.0_8080") and modify the opening ``` to ```text (or another
appropriate language) while leaving the block contents unchanged.
- Line 72: The markdown heading "### Sample listener" contains an extra space
after the hashes; update that heading to a single space as "### Sample listener"
(search for the exact string "### Sample listener" in SERVER_DESIGN.md) and
ensure other headings do not have double spaces after the hash characters.
- Around line 289-295: Update the fenced code block that begins with "Connection
time (pre-request):" so it includes a language specifier (e.g., change the
opening ``` to ```text) to ensure proper rendering; locate the block containing
"Connection time (pre-request):" and ":authority + port → VirtualHost → route →
service" and add the specifier to the opening fence.
- Around line 74-94: Update the fenced code block that begins with "xDS Listener
(port 8080)" to include a language specifier so it renders correctly (e.g.,
replace the opening ``` with ```text); ensure only the opening fence is changed
and the closing fence remains ``` so the diagram content and formatting
(FilterChain: mTLS, match: transport_protocol="tls", alpn=["istio"], TLS: SDS
certs + REQUIRE_CLIENT_CERT, http_filters, router, VirtualHost entries, routes,
etc.) are preserved.
- Line 171: Replace the British phrasing "In future" with the American English
form "In the future" wherever it appears (specifically the sentence currently
starting with "In future") so the technical documentation uses consistent
American English phrasing.
In `@xds/docs/SERVER_PROPOSAL.md`:
- Around line 87-93: Add the `@UnstableApi` annotation to the API examples so they
match the doc text: annotate the ServerPlugin interface declaration with
`@UnstableApi` (the example that declares public interface ServerPlugin extends
SafeCloseable { void install(ServerBuilder sb); }) and ensure any necessary
import or qualification for `@UnstableApi` is present so the example compiles and
accurately demonstrates the unstable API marker.
- Around line 10-15: The fenced code block showing the Server.builder() example
lacks a language specifier for syntax highlighting; update the triple-backtick
fence before the Server.builder() snippet to include the language (e.g., "java")
so the block begins with ```java; ensure the rest of the snippet (the
Server.builder() chain, XdsServerPlugin(...) and the comment about
plugin.install(sb)) remains unchanged.
- Around line 151-155: The fenced code block showing the TLS provider chain
lacks a language specifier; update the block to use a language tag (e.g.,
"java") so syntax highlighting applies. Locate the fenced block containing
sb.tls(keyPair); sb.tlsProvider(tlsProvider); and
sb.tlsProvider(serverTlsProvider); and add the language after the opening
backticks (for example ```java) to the opening fence and keep the closing fence
unchanged.
- Around line 25-42: The fenced code block in SERVER_PROPOSAL.md lacks a
language specifier; update the block that contains the connection flow diagram
to use a language tag (e.g., "text") so it renders correctly, i.e. change the
opening triple backticks to include the specifier for the diagram showing
ConnectionAcceptor.accept, ServerTlsProvider.serverTlsSpec, TLS handshake, and
XdsRootDecorator.serve.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9b9c6bac-a731-4da5-9994-d843f2942475
📒 Files selected for processing (54)
benchmarks/jmh/benchmarks/jmh/build/results/jmh/aggregate-results.txtbenchmarks/jmh/run-benchmark.shcore/src/main/java/com/linecorp/armeria/server/ConnectionContext.javacore/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.javacore/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.javacore/src/main/java/com/linecorp/armeria/server/FallbackServerTlsProvider.javacore/src/main/java/com/linecorp/armeria/server/Http2ServerConnectionHandler.javacore/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.javacore/src/main/java/com/linecorp/armeria/server/HttpsConnectionAcceptHandler.javacore/src/main/java/com/linecorp/armeria/server/Server.javacore/src/main/java/com/linecorp/armeria/server/ServerBuilder.javacore/src/main/java/com/linecorp/armeria/server/ServerPlugin.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsConfig.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsConfigBuilder.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsProvider.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsSpec.javacore/src/main/java/com/linecorp/armeria/server/StaticTlsProvider.javacore/src/main/java/com/linecorp/armeria/server/TlsProviderAdapter.javacore/src/main/java/com/linecorp/armeria/server/TlsProviderMapping.javacore/src/main/java/com/linecorp/armeria/server/UpdatableServerConfig.javacore/src/main/java/com/linecorp/armeria/server/VirtualHost.javacore/src/main/java/com/linecorp/armeria/server/VirtualHostBuilder.javacore/src/test/java/com/linecorp/armeria/server/ServerTlsProviderTest.javacore/src/test/java/com/linecorp/armeria/server/TlsProviderMappingTest.javacore/src/test/java/com/linecorp/armeria/server/VirtualHostAnnotatedServiceBindingBuilderTest.javacore/src/test/java/com/linecorp/armeria/server/VirtualHostBuilderTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiPortTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.javait/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactoryit/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.javait/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.javaxds-api/src/main/proto/envoy/config/listener/v3/listener.protoxds-api/src/main/proto/envoy/config/listener/v3/listener_components.protoxds-api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.protoxds/docs/SERVER_DESIGN.mdxds/docs/SERVER_PROPOSAL.mdxds/src/main/java/com/linecorp/armeria/xds/DelegatingHttpService.javaxds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.javaxds/src/main/java/com/linecorp/armeria/xds/FilterChainSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/FilterUtil.javaxds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/ListenerStream.javaxds/src/main/java/com/linecorp/armeria/xds/ParsedFilterChain.javaxds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.javaxds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/XdsExtensionRegistry.javaxds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.javaxds/src/main/java/com/linecorp/armeria/xds/filter/XdsHttpFilter.java
💤 Files with no reviewable changes (2)
- core/src/main/java/com/linecorp/armeria/server/TlsProviderMapping.java
- core/src/test/java/com/linecorp/armeria/server/TlsProviderMappingTest.java
🚧 Files skipped from review as they are similar to previous changes (40)
- it/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactory
- xds/src/main/java/com/linecorp/armeria/xds/XdsExtensionRegistry.java
- xds-api/src/main/proto/envoy/config/listener/v3/listener.proto
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.java
- xds-api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto
- xds/src/main/java/com/linecorp/armeria/xds/DelegatingHttpService.java
- core/src/main/java/com/linecorp/armeria/server/ServerPlugin.java
- core/src/test/java/com/linecorp/armeria/server/VirtualHostAnnotatedServiceBindingBuilderTest.java
- xds/src/main/java/com/linecorp/armeria/xds/filter/XdsHttpFilter.java
- core/src/test/java/com/linecorp/armeria/server/ServerTlsProviderTest.java
- xds/src/main/java/com/linecorp/armeria/xds/FilterUtil.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.java
- core/src/main/java/com/linecorp/armeria/server/ServerTlsProvider.java
- core/src/main/java/com/linecorp/armeria/server/FallbackServerTlsProvider.java
- xds/src/main/java/com/linecorp/armeria/xds/FilterChainSnapshot.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.java
- core/src/main/java/com/linecorp/armeria/server/ServerTlsConfigBuilder.java
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.java
- xds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.java
- core/src/main/java/com/linecorp/armeria/server/UpdatableServerConfig.java
- core/src/main/java/com/linecorp/armeria/server/Server.java
- core/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.java
- core/src/test/java/com/linecorp/armeria/server/VirtualHostBuilderTest.java
- xds/src/main/java/com/linecorp/armeria/xds/ParsedFilterChain.java
- core/src/main/java/com/linecorp/armeria/server/StaticTlsProvider.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.java
- core/src/main/java/com/linecorp/armeria/server/ServerTlsSpec.java
- core/src/main/java/com/linecorp/armeria/server/TlsProviderAdapter.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiPortTest.java
- xds-api/src/main/proto/envoy/config/listener/v3/listener_components.proto
- xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.java
- core/src/main/java/com/linecorp/armeria/server/VirtualHost.java
- xds/src/main/java/com/linecorp/armeria/xds/ListenerStream.java
- core/src/main/java/com/linecorp/armeria/server/VirtualHostBuilder.java
- xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java
- xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java
- core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java (1)
213-225:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftCleartext connections never honor per-connection max-age overrides.
The keep-alive handler is built before
DefaultConnectionAcceptorfinishes, so anyconnectionContext.setMaxConnectionAgeMillis(...)done during acceptance cannot affect H1C/H2C connection lifetime. HTTPS resolves max age after the accept/TLS phase, but the cleartext path hard-codesconfig.maxConnectionAgeMillis()here.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java` around lines 213 - 225, The cleartext HTTP keep-alive handler is created using config.maxConnectionAgeMillis() before DefaultConnectionAcceptor can apply per-connection overrides, so H1C/H2C never observe connectionContext.setMaxConnectionAgeMillis(...); change the flow in HttpServerPipelineConfigurator to defer creating the Http1ServerKeepAliveHandler (and the H2C equivalent) until after acceptance or to construct it using the resolved value from the ConnectionContext at accept time (e.g., read connectionContext.getMaxConnectionAgeMillis() or pass a supplier that queries the context) instead of using config.maxConnectionAgeMillis(); ensure needsKeepAliveHandler still uses the runtime values via needsKeepAliveHandler(..., connectionContext.getPingIntervalMillis(), connectionContext.getMaxConnectionAgeMillis(), ...) and replace direct newKeepAliveTimer/H1C-bound creation with a post-accept creation point referenced from DefaultConnectionAcceptor/connectionContext so per-connection overrides take effect.
♻️ Duplicate comments (2)
core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java (1)
283-285:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnforce the TLS-provider/SSL-factory pair invariant here.
HttpServerPipelineConfigurator.configureHttps()assumes these are either both set or both null and only protects that withassert. A partially populatedDefaultServerConfigwill survive construction and then fail later on the HTTPS path once assertions are off. Reject the XOR case in this constructor.Suggested fix
this.errorHandler = requireNonNull(errorHandler, "errorHandler"); + if ((serverTlsProvider == null) != (sslContextFactory == null)) { + throw new IllegalArgumentException( + "serverTlsProvider and sslContextFactory must be set together"); + } this.serverTlsProvider = serverTlsProvider; this.sslContextFactory = sslContextFactory;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java` around lines 283 - 285, Enforce the invariant in the DefaultServerConfig constructor that serverTlsProvider and sslContextFactory are either both non-null or both null: detect the XOR case (serverTlsProvider == null ^ sslContextFactory == null) and throw an IllegalArgumentException with a clear message, so construction fails fast instead of letting HttpServerPipelineConfigurator.configureHttps rely on an assert later.xds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.java (1)
182-202:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMirror
buildClientTlsSpec()'s trust handling here.
buildServerTlsSpec()still only appliestrustedCa()andClientAuth.REQUIRE. It dropspeerVerifierFactories(),system_root_certs, and the xDS no-verify fallback, so the sameCertificateValidationContextSnapshotcan produce different mTLS behavior on the downstream/server path than it does on the upstream/client path.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.java` around lines 182 - 202, buildServerTlsSpec currently only applies trustedCa() and ClientAuth.REQUIRE and therefore diverges from buildClientTlsSpec's trust handling; update buildServerTlsSpec to mirror buildClientTlsSpec by also honoring CertificateValidationContextSnapshot.peerVerifierFactories(), the system-root-certs flag (e.g., useSystemTrust()/systemRootCerts), and the no-verify fallback so downstream/server mTLS behavior matches upstream/client behavior, while still calling DownstreamTlsTransportSocketFactory.requireClientCertificate(...) for clientAuth; locate buildServerTlsSpec, buildClientTlsSpec, and CertificateValidationContextSnapshot methods (trustedCa(), peerVerifierFactories(), system root flag, and no-verify indicator) and apply the same trust-building logic and fallbacks used in buildClientTlsSpec when building the ServerTlsSpec.
🧹 Nitpick comments (10)
xds/docs/SERVER_DESIGN.md (6)
149-151: 💤 Low valueAdd language specifier to fenced code block.
The decorator ordering example should specify a language for proper rendering.
📝 Proposed fix
-``` +```text [xDS RBAC] → [xDS authn] → [user's service decorators] → service🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` around lines 149 - 151, The fenced code block containing the decorator ordering example ("[xDS RBAC] → [xDS authn] → [user's service decorators] → service") is missing a language specifier; update the triple-backtick fence to include a language (e.g., change ``` to ```text) so the block renders correctly, locating the fenced block that wraps that exact string in SERVER_DESIGN.md and adding the language token.
53-70: 💤 Low valueAdd language specifier to fenced code block.
The schema block should specify a language for proper syntax highlighting and rendering.
📝 Proposed fix
-``` +```text Listener (name: "inbound_0.0.0.0_8080")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` around lines 53 - 70, The fenced code block showing the Listener/FilterChain schema lacks a language specifier; update the opening fence for that block to include a language (e.g., "text" or "yaml") so it renders with proper highlighting—locate the block that begins with the Listener (name: "inbound_0.0.0.0_8080") and modify the opening ``` to ```text (or another appropriate language) while leaving the block contents unchanged.
72-72: 💤 Low valueRemove extra space after hash in heading.
📝 Proposed fix
-### Sample listener +### Sample listener🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` at line 72, The markdown heading "### Sample listener" contains an extra space after the hashes; update that heading to a single space as "### Sample listener" (search for the exact string "### Sample listener" in SERVER_DESIGN.md) and ensure other headings do not have double spaces after the hash characters.
289-295: 💤 Low valueAdd language specifier to fenced code block.
The connection/request time flow block should specify a language for proper rendering.
📝 Proposed fix
-``` +```text Connection time (pre-request):🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` around lines 289 - 295, Update the fenced code block that begins with "Connection time (pre-request):" so it includes a language specifier (e.g., change the opening ``` to ```text) to ensure proper rendering; locate the block containing "Connection time (pre-request):" and ":authority + port → VirtualHost → route → service" and add the specifier to the opening fence.
74-94: 💤 Low valueAdd language specifier to fenced code block.
The sample listener block should specify a language for proper rendering.
📝 Proposed fix
-``` +```text xDS Listener (port 8080)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` around lines 74 - 94, Update the fenced code block that begins with "xDS Listener (port 8080)" to include a language specifier so it renders correctly (e.g., replace the opening ``` with ```text); ensure only the opening fence is changed and the closing fence remains ``` so the diagram content and formatting (FilterChain: mTLS, match: transport_protocol="tls", alpn=["istio"], TLS: SDS certs + REQUIRE_CLIENT_CERT, http_filters, router, VirtualHost entries, routes, etc.) are preserved.
171-171: 💤 Low valueUse American English phrasing.
"In future" is British English; "In the future" is more common in technical documentation.
📝 Proposed fix
-In future, we could support dynamically binding ports to listeners via wildcard listener +In the future, we could support dynamically binding ports to listeners via wildcard listener🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` at line 171, Replace the British phrasing "In future" with the American English form "In the future" wherever it appears (specifically the sentence currently starting with "In future") so the technical documentation uses consistent American English phrasing.xds/docs/SERVER_PROPOSAL.md (4)
87-93: 💤 Low valueConsider showing
@UnstableApiannotation in code examples.The document states on line 4 that "All new APIs are annotated
@UnstableApi", but the code examples don't show these annotations. Including them would make the examples more accurate and educational.📝 Suggested enhancement
```java package com.linecorp.armeria.server; +@UnstableApi public interface ServerPlugin extends SafeCloseable { void install(ServerBuilder sb); }</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@xds/docs/SERVER_PROPOSAL.mdaround lines 87 - 93, Add the@UnstableApi
annotation to the API examples so they match the doc text: annotate the
ServerPlugin interface declaration with@UnstableApi(the example that declares
public interface ServerPlugin extends SafeCloseable { void install(ServerBuilder
sb); }) and ensure any necessary import or qualification for@UnstableApiis
present so the example compiles and accurately demonstrates the unstable API
marker.</details> <!-- cr-comment:v1:bfc05bf9e51f0f3c14f4b69f --> --- `10-15`: _💤 Low value_ **Add language specifier to fenced code block.** The builder example should specify a language for proper syntax highlighting. <details> <summary>📝 Proposed fix</summary> ```diff -``` +```java Server.builder()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_PROPOSAL.md` around lines 10 - 15, The fenced code block showing the Server.builder() example lacks a language specifier for syntax highlighting; update the triple-backtick fence before the Server.builder() snippet to include the language (e.g., "java") so the block begins with ```java; ensure the rest of the snippet (the Server.builder() chain, XdsServerPlugin(...) and the comment about plugin.install(sb)) remains unchanged.
151-155: 💤 Low valueAdd language specifier to fenced code block.
The TLS provider chain example should specify a language for proper syntax highlighting.
📝 Proposed fix
-``` +```java sb.tls(keyPair); // fallback — always evaluated last🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_PROPOSAL.md` around lines 151 - 155, The fenced code block showing the TLS provider chain lacks a language specifier; update the block to use a language tag (e.g., "java") so syntax highlighting applies. Locate the fenced block containing sb.tls(keyPair); sb.tlsProvider(tlsProvider); and sb.tlsProvider(serverTlsProvider); and add the language after the opening backticks (for example ```java) to the opening fence and keep the closing fence unchanged.
25-42: 💤 Low valueAdd language specifier to fenced code block.
The connection flow diagram should specify a language for proper rendering.
📝 Proposed fix
-``` +```text Connection arrives🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_PROPOSAL.md` around lines 25 - 42, The fenced code block in SERVER_PROPOSAL.md lacks a language specifier; update the block that contains the connection flow diagram to use a language tag (e.g., "text") so it renders correctly, i.e. change the opening triple backticks to include the specifier for the diagram showing ConnectionAcceptor.accept, ServerTlsProvider.serverTlsSpec, TLS handshake, and XdsRootDecorator.serve.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/src/main/java/com/linecorp/armeria/server/ConnectionContext.java`:
- Around line 177-181: The setter setMaxConnectionAgeMillis in ConnectionContext
should reject negative values (like other duration/age fields) instead of
allowing them to be silently ignored by resolveMaxConnectionAge; add a guard in
setMaxConnectionAgeMillis that validates maxConnectionAgeMillis >= 0 and throws
an IllegalArgumentException with a clear message when negative, so callers fail
fast and behavior matches resolveMaxConnectionAge and the config layer.
In
`@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java`:
- Around line 354-370: The connection-acceptor callback currently auto-unboxes
the boxed Boolean `accepted` inside the whenComplete lambda of
`connectionAcceptor.accept(connectionContext, ch.eventLoop())`, which can throw
a NPE instead of cleanly rejecting a connection; update the conditional that
checks `accepted` to use `Boolean.TRUE.equals(accepted)` (in both cleartext and
TLS acceptor lambdas where `accepted` is inspected) so the gate is fail-closed,
keep the existing handling of `timeoutFuture`, `t`, `ch.close()`, and
`ch.pipeline().remove(this)` unchanged otherwise.
- Around line 203-205: The newly created ConnectionContext (constructed in
HttpServerPipelineConfigurator where you call new ConnectionContext(HTTP, ...,
ch)) must be attached to the channel so ConnectionContext.get(ch) can later
retrieve it; modify the code after creating connectionContext to persist it on
the channel (e.g. call the ConnectionContext attach/set API with the channel
variable ch or otherwise store the instance in the channel attributes) so
H1C/H2C connections are visible to lookup-based features just like the HTTPS/SNI
path does.
In
`@it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.java`:
- Around line 1-15: Replace the file header in ServerConnectionConfigTest.java
to match the repository's canonical Java header used elsewhere (use "LY
Corporation" wording and the same static year/format used in this PR instead of
"2025 LINE Corporation"); update the top-of-file comment block so it exactly
matches the existing header template used across the repo (preserve the same
year/token format and license text) to avoid style/check failures.
---
Outside diff comments:
In
`@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java`:
- Around line 213-225: The cleartext HTTP keep-alive handler is created using
config.maxConnectionAgeMillis() before DefaultConnectionAcceptor can apply
per-connection overrides, so H1C/H2C never observe
connectionContext.setMaxConnectionAgeMillis(...); change the flow in
HttpServerPipelineConfigurator to defer creating the Http1ServerKeepAliveHandler
(and the H2C equivalent) until after acceptance or to construct it using the
resolved value from the ConnectionContext at accept time (e.g., read
connectionContext.getMaxConnectionAgeMillis() or pass a supplier that queries
the context) instead of using config.maxConnectionAgeMillis(); ensure
needsKeepAliveHandler still uses the runtime values via
needsKeepAliveHandler(..., connectionContext.getPingIntervalMillis(),
connectionContext.getMaxConnectionAgeMillis(), ...) and replace direct
newKeepAliveTimer/H1C-bound creation with a post-accept creation point
referenced from DefaultConnectionAcceptor/connectionContext so per-connection
overrides take effect.
---
Duplicate comments:
In `@core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java`:
- Around line 283-285: Enforce the invariant in the DefaultServerConfig
constructor that serverTlsProvider and sslContextFactory are either both
non-null or both null: detect the XOR case (serverTlsProvider == null ^
sslContextFactory == null) and throw an IllegalArgumentException with a clear
message, so construction fails fast instead of letting
HttpServerPipelineConfigurator.configureHttps rely on an assert later.
In `@xds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.java`:
- Around line 182-202: buildServerTlsSpec currently only applies trustedCa() and
ClientAuth.REQUIRE and therefore diverges from buildClientTlsSpec's trust
handling; update buildServerTlsSpec to mirror buildClientTlsSpec by also
honoring CertificateValidationContextSnapshot.peerVerifierFactories(), the
system-root-certs flag (e.g., useSystemTrust()/systemRootCerts), and the
no-verify fallback so downstream/server mTLS behavior matches upstream/client
behavior, while still calling
DownstreamTlsTransportSocketFactory.requireClientCertificate(...) for
clientAuth; locate buildServerTlsSpec, buildClientTlsSpec, and
CertificateValidationContextSnapshot methods (trustedCa(),
peerVerifierFactories(), system root flag, and no-verify indicator) and apply
the same trust-building logic and fallbacks used in buildClientTlsSpec when
building the ServerTlsSpec.
---
Nitpick comments:
In `@xds/docs/SERVER_DESIGN.md`:
- Around line 149-151: The fenced code block containing the decorator ordering
example ("[xDS RBAC] → [xDS authn] → [user's service decorators] → service") is
missing a language specifier; update the triple-backtick fence to include a
language (e.g., change ``` to ```text) so the block renders correctly, locating
the fenced block that wraps that exact string in SERVER_DESIGN.md and adding the
language token.
- Around line 53-70: The fenced code block showing the Listener/FilterChain
schema lacks a language specifier; update the opening fence for that block to
include a language (e.g., "text" or "yaml") so it renders with proper
highlighting—locate the block that begins with the Listener (name:
"inbound_0.0.0.0_8080") and modify the opening ``` to ```text (or another
appropriate language) while leaving the block contents unchanged.
- Line 72: The markdown heading "### Sample listener" contains an extra space
after the hashes; update that heading to a single space as "### Sample listener"
(search for the exact string "### Sample listener" in SERVER_DESIGN.md) and
ensure other headings do not have double spaces after the hash characters.
- Around line 289-295: Update the fenced code block that begins with "Connection
time (pre-request):" so it includes a language specifier (e.g., change the
opening ``` to ```text) to ensure proper rendering; locate the block containing
"Connection time (pre-request):" and ":authority + port → VirtualHost → route →
service" and add the specifier to the opening fence.
- Around line 74-94: Update the fenced code block that begins with "xDS Listener
(port 8080)" to include a language specifier so it renders correctly (e.g.,
replace the opening ``` with ```text); ensure only the opening fence is changed
and the closing fence remains ``` so the diagram content and formatting
(FilterChain: mTLS, match: transport_protocol="tls", alpn=["istio"], TLS: SDS
certs + REQUIRE_CLIENT_CERT, http_filters, router, VirtualHost entries, routes,
etc.) are preserved.
- Line 171: Replace the British phrasing "In future" with the American English
form "In the future" wherever it appears (specifically the sentence currently
starting with "In future") so the technical documentation uses consistent
American English phrasing.
In `@xds/docs/SERVER_PROPOSAL.md`:
- Around line 87-93: Add the `@UnstableApi` annotation to the API examples so they
match the doc text: annotate the ServerPlugin interface declaration with
`@UnstableApi` (the example that declares public interface ServerPlugin extends
SafeCloseable { void install(ServerBuilder sb); }) and ensure any necessary
import or qualification for `@UnstableApi` is present so the example compiles and
accurately demonstrates the unstable API marker.
- Around line 10-15: The fenced code block showing the Server.builder() example
lacks a language specifier for syntax highlighting; update the triple-backtick
fence before the Server.builder() snippet to include the language (e.g., "java")
so the block begins with ```java; ensure the rest of the snippet (the
Server.builder() chain, XdsServerPlugin(...) and the comment about
plugin.install(sb)) remains unchanged.
- Around line 151-155: The fenced code block showing the TLS provider chain
lacks a language specifier; update the block to use a language tag (e.g.,
"java") so syntax highlighting applies. Locate the fenced block containing
sb.tls(keyPair); sb.tlsProvider(tlsProvider); and
sb.tlsProvider(serverTlsProvider); and add the language after the opening
backticks (for example ```java) to the opening fence and keep the closing fence
unchanged.
- Around line 25-42: The fenced code block in SERVER_PROPOSAL.md lacks a
language specifier; update the block that contains the connection flow diagram
to use a language tag (e.g., "text") so it renders correctly, i.e. change the
opening triple backticks to include the specifier for the diagram showing
ConnectionAcceptor.accept, ServerTlsProvider.serverTlsSpec, TLS handshake, and
XdsRootDecorator.serve.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9b9c6bac-a731-4da5-9994-d843f2942475
📒 Files selected for processing (54)
benchmarks/jmh/benchmarks/jmh/build/results/jmh/aggregate-results.txtbenchmarks/jmh/run-benchmark.shcore/src/main/java/com/linecorp/armeria/server/ConnectionContext.javacore/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.javacore/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.javacore/src/main/java/com/linecorp/armeria/server/FallbackServerTlsProvider.javacore/src/main/java/com/linecorp/armeria/server/Http2ServerConnectionHandler.javacore/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.javacore/src/main/java/com/linecorp/armeria/server/HttpsConnectionAcceptHandler.javacore/src/main/java/com/linecorp/armeria/server/Server.javacore/src/main/java/com/linecorp/armeria/server/ServerBuilder.javacore/src/main/java/com/linecorp/armeria/server/ServerPlugin.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsConfig.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsConfigBuilder.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsProvider.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsSpec.javacore/src/main/java/com/linecorp/armeria/server/StaticTlsProvider.javacore/src/main/java/com/linecorp/armeria/server/TlsProviderAdapter.javacore/src/main/java/com/linecorp/armeria/server/TlsProviderMapping.javacore/src/main/java/com/linecorp/armeria/server/UpdatableServerConfig.javacore/src/main/java/com/linecorp/armeria/server/VirtualHost.javacore/src/main/java/com/linecorp/armeria/server/VirtualHostBuilder.javacore/src/test/java/com/linecorp/armeria/server/ServerTlsProviderTest.javacore/src/test/java/com/linecorp/armeria/server/TlsProviderMappingTest.javacore/src/test/java/com/linecorp/armeria/server/VirtualHostAnnotatedServiceBindingBuilderTest.javacore/src/test/java/com/linecorp/armeria/server/VirtualHostBuilderTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiPortTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.javait/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactoryit/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.javait/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.javaxds-api/src/main/proto/envoy/config/listener/v3/listener.protoxds-api/src/main/proto/envoy/config/listener/v3/listener_components.protoxds-api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.protoxds/docs/SERVER_DESIGN.mdxds/docs/SERVER_PROPOSAL.mdxds/src/main/java/com/linecorp/armeria/xds/DelegatingHttpService.javaxds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.javaxds/src/main/java/com/linecorp/armeria/xds/FilterChainSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/FilterUtil.javaxds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/ListenerStream.javaxds/src/main/java/com/linecorp/armeria/xds/ParsedFilterChain.javaxds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.javaxds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/XdsExtensionRegistry.javaxds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.javaxds/src/main/java/com/linecorp/armeria/xds/filter/XdsHttpFilter.java
💤 Files with no reviewable changes (2)
- core/src/main/java/com/linecorp/armeria/server/TlsProviderMapping.java
- core/src/test/java/com/linecorp/armeria/server/TlsProviderMappingTest.java
🚧 Files skipped from review as they are similar to previous changes (40)
- it/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactory
- xds/src/main/java/com/linecorp/armeria/xds/XdsExtensionRegistry.java
- xds-api/src/main/proto/envoy/config/listener/v3/listener.proto
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.java
- xds-api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto
- xds/src/main/java/com/linecorp/armeria/xds/DelegatingHttpService.java
- core/src/main/java/com/linecorp/armeria/server/ServerPlugin.java
- core/src/test/java/com/linecorp/armeria/server/VirtualHostAnnotatedServiceBindingBuilderTest.java
- xds/src/main/java/com/linecorp/armeria/xds/filter/XdsHttpFilter.java
- core/src/test/java/com/linecorp/armeria/server/ServerTlsProviderTest.java
- xds/src/main/java/com/linecorp/armeria/xds/FilterUtil.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.java
- core/src/main/java/com/linecorp/armeria/server/ServerTlsProvider.java
- core/src/main/java/com/linecorp/armeria/server/FallbackServerTlsProvider.java
- xds/src/main/java/com/linecorp/armeria/xds/FilterChainSnapshot.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.java
- core/src/main/java/com/linecorp/armeria/server/ServerTlsConfigBuilder.java
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.java
- xds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.java
- core/src/main/java/com/linecorp/armeria/server/UpdatableServerConfig.java
- core/src/main/java/com/linecorp/armeria/server/Server.java
- core/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.java
- core/src/test/java/com/linecorp/armeria/server/VirtualHostBuilderTest.java
- xds/src/main/java/com/linecorp/armeria/xds/ParsedFilterChain.java
- core/src/main/java/com/linecorp/armeria/server/StaticTlsProvider.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.java
- core/src/main/java/com/linecorp/armeria/server/ServerTlsSpec.java
- core/src/main/java/com/linecorp/armeria/server/TlsProviderAdapter.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiPortTest.java
- xds-api/src/main/proto/envoy/config/listener/v3/listener_components.proto
- xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.java
- core/src/main/java/com/linecorp/armeria/server/VirtualHost.java
- xds/src/main/java/com/linecorp/armeria/xds/ListenerStream.java
- core/src/main/java/com/linecorp/armeria/server/VirtualHostBuilder.java
- xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java
- xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java
- core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java
🛑 Comments failed to post (4)
core/src/main/java/com/linecorp/armeria/server/ConnectionContext.java (1)
177-181:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winReject negative max-connection ages.
resolveMaxConnectionAge(...)in the HTTP/1 and HTTP/2 pipelines only honors values greater than0, so a negative value here is silently ignored instead of failing fast. Guard this setter the same way the config layer validates other duration/age fields.Suggested fix
/** * Sets the per-connection max connection age in milliseconds. */ public void setMaxConnectionAgeMillis(long maxConnectionAgeMillis) { + if (maxConnectionAgeMillis < 0) { + throw new IllegalArgumentException( + "maxConnectionAgeMillis: " + maxConnectionAgeMillis + " (expected: >= 0)"); + } this.maxConnectionAgeMillis = maxConnectionAgeMillis; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/main/java/com/linecorp/armeria/server/ConnectionContext.java` around lines 177 - 181, The setter setMaxConnectionAgeMillis in ConnectionContext should reject negative values (like other duration/age fields) instead of allowing them to be silently ignored by resolveMaxConnectionAge; add a guard in setMaxConnectionAgeMillis that validates maxConnectionAgeMillis >= 0 and throws an IllegalArgumentException with a clear message when negative, so callers fail fast and behavior matches resolveMaxConnectionAge and the config layer.core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java (2)
203-205:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winAttach the cleartext
ConnectionContextto the channel.
ConnectionContext.get(channel)is the new lookup contract for connection-level state, but the HTTP path never stores the instance it just created. That leaves H1C/H2C connections invisible to any later lookup-based feature or plugin, while the HTTPS path does store it during SNI processing.Suggested fix
final Channel ch = p.channel(); final ConnectionContext connectionContext = new ConnectionContext(HTTP, null, ImmutableList.of(), proxiedAddresses, ch); + ch.attr(ConnectionContext.ATTR).set(connectionContext);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.final Channel ch = p.channel(); final ConnectionContext connectionContext = new ConnectionContext(HTTP, null, ImmutableList.of(), proxiedAddresses, ch); ch.attr(ConnectionContext.ATTR).set(connectionContext);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java` around lines 203 - 205, The newly created ConnectionContext (constructed in HttpServerPipelineConfigurator where you call new ConnectionContext(HTTP, ..., ch)) must be attached to the channel so ConnectionContext.get(ch) can later retrieve it; modify the code after creating connectionContext to persist it on the channel (e.g. call the ConnectionContext attach/set API with the channel variable ch or otherwise store the instance in the channel attributes) so H1C/H2C connections are visible to lookup-based features just like the HTTPS/SNI path does.
354-370:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winThe connection-acceptor gate is duplicated without fail-closed handling. Both the cleartext and TLS paths auto-unbox a boxed
Boolean, sonullbecomes an exception instead of a clean rejection. UsingBoolean.TRUE.equals(accepted)in both sites keeps the gate fail-closed consistently.🧰 Tools
🪛 PMD (7.25.0)
[Low] 360-360: InvalidLogMessageFormat (Error Prone): Too many arguments, expected 1 argument but found 2
(InvalidLogMessageFormat (Error Prone))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.java` around lines 354 - 370, The connection-acceptor callback currently auto-unboxes the boxed Boolean `accepted` inside the whenComplete lambda of `connectionAcceptor.accept(connectionContext, ch.eventLoop())`, which can throw a NPE instead of cleanly rejecting a connection; update the conditional that checks `accepted` to use `Boolean.TRUE.equals(accepted)` (in both cleartext and TLS acceptor lambdas where `accepted` is inspected) so the gate is fail-closed, keep the existing handling of `timeoutFuture`, `t`, `ch.close()`, and `ch.pipeline().remove(this)` unchanged otherwise.it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.java (1)
1-15:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse the repository’s current copyright header.
This new file still uses
2025 LINE Corporation, while the current Java header in this PR already uses theLY Corporationform. New files should match the required header exactly to avoid style/check drift.As per coding guidelines, "use the required copyright header (avoid changing $today.year on every modified file)".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.java` around lines 1 - 15, Replace the file header in ServerConnectionConfigTest.java to match the repository's canonical Java header used elsewhere (use "LY Corporation" wording and the same static year/format used in this PR instead of "2025 LINE Corporation"); update the top-of-file comment block so it exactly matches the existing header template used across the repo (preserve the same year/token format and license text) to avoid style/check failures.Source: Coding guidelines
6bab726 to
8b6320c
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java (1)
36-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd
@UnstableApiat class level to cover new public methods.This class introduces new
publicmethods in a non-.internalpackage; annotate the class so the API-stability contract is explicit and method-level duplication is avoided.Suggested patch
import com.linecorp.armeria.common.annotation.Nullable; +import com.linecorp.armeria.common.annotation.UnstableApi; import com.linecorp.armeria.xds.stream.SnapshotStream; @@ +@UnstableApi final class DownstreamTlsTransportSocketFactory implements TransportSocketFactory {As per path instructions, "Review all newly added public classes and methods to ensure they have the
@UnstableApiannotation."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java` around lines 36 - 60, The DownstreamTlsTransportSocketFactory API is exposed through new public methods in a non-internal package, so the stability contract should be explicit. Add `@UnstableApi` at the class level on DownstreamTlsTransportSocketFactory to cover name(), typeUrls(), and create() instead of annotating each method individually, and keep the existing INSTANCE and constructor unchanged.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/src/main/java/com/linecorp/armeria/server/Server.java`:
- Around line 725-737: In Server.shutdown handling, each ServerPlugin is being
closed twice: once directly in the plugin.close() loop and again when the same
plugins are wrapped with ShutdownSupport.of(plugin). Update the shutdown flow in
Server so there is only one close path for plugins, either by removing the
direct close loop or by not adding already-closed plugins to the ShutdownSupport
builder, and keep the existing logger.warn handling in the chosen path.
In `@xds/docs/SERVER_DESIGN.md`:
- Around line 161-174: Update the Port Selection section in XdsServerPlugin’s
design notes to describe a managed set of ports rather than a single definitive
port. Reword the text around XdsServerPlugin, listener address.port, and xDS
policy application so it reflects multi-port support, while preserving the
distinction between the plugin’s managed ports and the listener port validation
behavior. Adjust the forward-looking API note to fit the new multi-port-oriented
design language.
In `@xds/docs/SERVER_PROPOSAL.md`:
- Around line 10-17: Use a single plugin-registration method name throughout the
proposal by updating the Server.builder example and the API table to match the
Java snippets in this PR. Replace the inconsistent addPlugin(...) reference with
the chosen entry point used elsewhere (the builder/plugin registration API
around Server.builder and XdsServerPlugin), so all examples and docs point to
the same method name and copied snippets stay consistent.
In `@xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java`:
- Around line 135-139: The startup wait in XdsServerPlugin’s whenReady block
swallows interrupt handling by catching Exception and rethrowing it, so update
this catch path to specifically detect InterruptedException, restore the
thread’s interrupt flag before wrapping or propagating it, and keep the existing
timeout/ready wait behavior unchanged.
- Around line 158-162: The xDS match path in XdsServerPlugin currently returns
success without consulting the previously configured ConnectionAcceptor, which
bypasses any existing port-level connection policy. Update the matched branch in
the connection handling logic to invoke or chain through existingAcceptor before
accepting the connection, while still setting
ServerSnapshotWatcher.MATCHED_FILTER_CHAIN and preserving the xDS match
behavior.
---
Nitpick comments:
In
`@xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java`:
- Around line 36-60: The DownstreamTlsTransportSocketFactory API is exposed
through new public methods in a non-internal package, so the stability contract
should be explicit. Add `@UnstableApi` at the class level on
DownstreamTlsTransportSocketFactory to cover name(), typeUrls(), and create()
instead of annotating each method individually, and keep the existing INSTANCE
and constructor unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6d9045e2-f124-4418-941c-cac43a43a8be
📒 Files selected for processing (23)
benchmarks/jmh/benchmarks/jmh/build/results/jmh/aggregate-results.txtbenchmarks/jmh/run-benchmark.shcore/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.javacore/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.javacore/src/main/java/com/linecorp/armeria/server/Server.javacore/src/main/java/com/linecorp/armeria/server/ServerBuilder.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiPortTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.javait/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactoryit/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.javait/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.javaxds/docs/SERVER_DESIGN.mdxds/docs/SERVER_PROPOSAL.mdxds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.javaxds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.javaxds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java
✅ Files skipped from review due to trivial changes (3)
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.java
- it/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactory
- core/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.java
🚧 Files skipped from review as they are similar to previous changes (6)
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.java
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.java
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 5
🧹 Nitpick comments (1)
xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java (1)
36-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd
@UnstableApiat class level to cover new public methods.This class introduces new
publicmethods in a non-.internalpackage; annotate the class so the API-stability contract is explicit and method-level duplication is avoided.Suggested patch
import com.linecorp.armeria.common.annotation.Nullable; +import com.linecorp.armeria.common.annotation.UnstableApi; import com.linecorp.armeria.xds.stream.SnapshotStream; @@ +@UnstableApi final class DownstreamTlsTransportSocketFactory implements TransportSocketFactory {As per path instructions, "Review all newly added public classes and methods to ensure they have the
@UnstableApiannotation."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java` around lines 36 - 60, The DownstreamTlsTransportSocketFactory API is exposed through new public methods in a non-internal package, so the stability contract should be explicit. Add `@UnstableApi` at the class level on DownstreamTlsTransportSocketFactory to cover name(), typeUrls(), and create() instead of annotating each method individually, and keep the existing INSTANCE and constructor unchanged.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/src/main/java/com/linecorp/armeria/server/Server.java`:
- Around line 725-737: In Server.shutdown handling, each ServerPlugin is being
closed twice: once directly in the plugin.close() loop and again when the same
plugins are wrapped with ShutdownSupport.of(plugin). Update the shutdown flow in
Server so there is only one close path for plugins, either by removing the
direct close loop or by not adding already-closed plugins to the ShutdownSupport
builder, and keep the existing logger.warn handling in the chosen path.
In `@xds/docs/SERVER_DESIGN.md`:
- Around line 161-174: Update the Port Selection section in XdsServerPlugin’s
design notes to describe a managed set of ports rather than a single definitive
port. Reword the text around XdsServerPlugin, listener address.port, and xDS
policy application so it reflects multi-port support, while preserving the
distinction between the plugin’s managed ports and the listener port validation
behavior. Adjust the forward-looking API note to fit the new multi-port-oriented
design language.
In `@xds/docs/SERVER_PROPOSAL.md`:
- Around line 10-17: Use a single plugin-registration method name throughout the
proposal by updating the Server.builder example and the API table to match the
Java snippets in this PR. Replace the inconsistent addPlugin(...) reference with
the chosen entry point used elsewhere (the builder/plugin registration API
around Server.builder and XdsServerPlugin), so all examples and docs point to
the same method name and copied snippets stay consistent.
In `@xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java`:
- Around line 135-139: The startup wait in XdsServerPlugin’s whenReady block
swallows interrupt handling by catching Exception and rethrowing it, so update
this catch path to specifically detect InterruptedException, restore the
thread’s interrupt flag before wrapping or propagating it, and keep the existing
timeout/ready wait behavior unchanged.
- Around line 158-162: The xDS match path in XdsServerPlugin currently returns
success without consulting the previously configured ConnectionAcceptor, which
bypasses any existing port-level connection policy. Update the matched branch in
the connection handling logic to invoke or chain through existingAcceptor before
accepting the connection, while still setting
ServerSnapshotWatcher.MATCHED_FILTER_CHAIN and preserving the xDS match
behavior.
---
Nitpick comments:
In
`@xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java`:
- Around line 36-60: The DownstreamTlsTransportSocketFactory API is exposed
through new public methods in a non-internal package, so the stability contract
should be explicit. Add `@UnstableApi` at the class level on
DownstreamTlsTransportSocketFactory to cover name(), typeUrls(), and create()
instead of annotating each method individually, and keep the existing INSTANCE
and constructor unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6d9045e2-f124-4418-941c-cac43a43a8be
📒 Files selected for processing (23)
benchmarks/jmh/benchmarks/jmh/build/results/jmh/aggregate-results.txtbenchmarks/jmh/run-benchmark.shcore/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.javacore/src/main/java/com/linecorp/armeria/server/HttpServerPipelineConfigurator.javacore/src/main/java/com/linecorp/armeria/server/Server.javacore/src/main/java/com/linecorp/armeria/server/ServerBuilder.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiPortTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.javait/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactoryit/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.javait/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.javaxds/docs/SERVER_DESIGN.mdxds/docs/SERVER_PROPOSAL.mdxds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.javaxds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.javaxds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java
✅ Files skipped from review due to trivial changes (3)
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.java
- it/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactory
- core/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.java
🚧 Files skipped from review as they are similar to previous changes (6)
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.java
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.java
🛑 Comments failed to post (5)
core/src/main/java/com/linecorp/armeria/server/Server.java (1)
725-737: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Avoid closing each plugin twice.
Line 728 calls
plugin.close(), then Line 736 adds the same plugin toShutdownSupport, which can invoke the close path again. Keep one shutdown path so non-idempotent plugins are not double-closed.🐛 Proposed fix
- // Close plugins first so they can clean up their resources. - for (ServerPlugin plugin : plugins) { - try { - plugin.close(); - } catch (Exception e) { - logger.warn("Failed to close plugin: {}", plugin, e); - } - } - final Builder<ShutdownSupport> builder = ImmutableList.builder(); for (ServerPlugin plugin : plugins) { builder.add(ShutdownSupport.of(plugin)); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.final Builder<ShutdownSupport> builder = ImmutableList.builder(); for (ServerPlugin plugin : plugins) { builder.add(ShutdownSupport.of(plugin)); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/src/main/java/com/linecorp/armeria/server/Server.java` around lines 725 - 737, In Server.shutdown handling, each ServerPlugin is being closed twice: once directly in the plugin.close() loop and again when the same plugins are wrapped with ShutdownSupport.of(plugin). Update the shutdown flow in Server so there is only one close path for plugins, either by removing the direct close loop or by not adding already-closed plugins to the ShutdownSupport builder, and keep the existing logger.warn handling in the chosen path.xds/docs/SERVER_DESIGN.md (1)
161-174: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Describe the managed port set here, not a single port.
This section reads as if an
XdsServerPluginowns exactly one port, but this PR also adds multi-port support. Reword it around the plugin's managed ports so the design doc matches the new API surface.🧰 Tools
🪛 LanguageTool
[locale-violation] ~171-~171: The phrase ‘In future’ is British English. Did you mean: “In the future”?
Context: ...fers from the application port (8080). In future, we could support dynamically binding p...(IN_FUTURE)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_DESIGN.md` around lines 161 - 174, Update the Port Selection section in XdsServerPlugin’s design notes to describe a managed set of ports rather than a single definitive port. Reword the text around XdsServerPlugin, listener address.port, and xDS policy application so it reflects multi-port support, while preserving the distinction between the plugin’s managed ports and the listener port validation behavior. Adjust the forward-looking API note to fit the new multi-port-oriented design language.xds/docs/SERVER_PROPOSAL.md (1)
10-17: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use one plugin-registration API name throughout the proposal.
This document says
addPlugin(...), while the Java examples in this PR useplugin(...). Pick one name here so copied snippets and the API table do not point readers at conflicting entry points.Also applies to: 46-49, 163-169
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 10-10: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/docs/SERVER_PROPOSAL.md` around lines 10 - 17, Use a single plugin-registration method name throughout the proposal by updating the Server.builder example and the API table to match the Java snippets in this PR. Replace the inconsistent addPlugin(...) reference with the chosen entry point used elsewhere (the builder/plugin registration API around Server.builder and XdsServerPlugin), so all examples and docs point to the same method name and copied snippets stay consistent.xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java (2)
135-139: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Restore the interrupt flag before wrapping
InterruptedException.Line 137 catches
InterruptedExceptionthroughException, so server startup loses the interrupt signal.Proposed fix
try { watcher.whenReady().get(readyTimeout.toMillis(), TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for the first xDS snapshot.", e); } catch (Exception e) { - throw new RuntimeException(e); + throw new RuntimeException("Failed to wait for the first xDS snapshot.", e); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { watcher.whenReady().get(readyTimeout.toMillis(), TimeUnit.MILLISECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("Interrupted while waiting for the first xDS snapshot.", e); } catch (Exception e) { throw new RuntimeException("Failed to wait for the first xDS snapshot.", e); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java` around lines 135 - 139, The startup wait in XdsServerPlugin’s whenReady block swallows interrupt handling by catching Exception and rethrowing it, so update this catch path to specifically detect InterruptedException, restore the thread’s interrupt flag before wrapping or propagating it, and keep the existing timeout/ready wait behavior unchanged.
158-162: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Preserve the previously configured
ConnectionAcceptoron managed ports.Line 161 accepts matched xDS connections without invoking
existingAcceptor, bypassing any user-configured ACL, throttling, or connection policy on xDS-managed ports.Proposed fix
final ResolvedFilterChain matched = watcher.match(ctx); if (matched != null) { ctx.setAttr(ServerSnapshotWatcher.MATCHED_FILTER_CHAIN, matched); - return UnmodifiableFuture.completedFuture(true); + return existingAcceptor.accept(ctx); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.final ResolvedFilterChain matched = watcher.match(ctx); if (matched != null) { ctx.setAttr(ServerSnapshotWatcher.MATCHED_FILTER_CHAIN, matched); return existingAcceptor.accept(ctx); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java` around lines 158 - 162, The xDS match path in XdsServerPlugin currently returns success without consulting the previously configured ConnectionAcceptor, which bypasses any existing port-level connection policy. Update the matched branch in the connection handling logic to invoke or chain through existingAcceptor before accepting the connection, while still setting ServerSnapshotWatcher.MATCHED_FILTER_CHAIN and preserving the xDS match behavior.
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
xds/src/main/java/com/linecorp/armeria/xds/VirtualHostMatcher.java (1)
85-122: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winNormalize
authoritybefore host lookup.Configured domains are lower-cased in the constructor, but
find()compares them against the raw request authority. A mixed-caseHost/:authorityvalue will miss exact/prefix/suffix matches and can fall back to the wrong virtual host.Suggested fix
`@Nullable` VirtualHostSnapshot find(`@Nullable` String authority) { if (exactMatch.isEmpty() && prefixMatch.isEmpty() && suffixMatch.isEmpty()) { return defaultVirtualHost; } if (authority == null) { return defaultVirtualHost; } if (ignorePortInHostMatching) { final int colonIdx = authority.lastIndexOf(':'); final int v6EndIdx = authority.lastIndexOf(']'); if (colonIdx != -1 && colonIdx > v6EndIdx) { // An ipv6 address in the host header must be enclosed in square brackets // https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2 authority = authority.substring(0, colonIdx); } } + authority = Ascii.toLowerCase(authority); final VirtualHostSnapshot virtualHostSnapshot = exactMatch.get(authority);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/src/main/java/com/linecorp/armeria/xds/VirtualHostMatcher.java` around lines 85 - 122, Normalize the incoming authority in VirtualHostMatcher.find before doing exactMatch, prefixMatch, and suffixMatch lookups, since the configured hostnames are already lower-cased but the request authority is compared raw. Update the find(`@Nullable` String authority) flow to canonicalize the non-null authority consistently (including the ignorePortInHostMatching branch) so mixed-case :authority/Host values still match the same VirtualHostSnapshot entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@xds/src/main/java/com/linecorp/armeria/xds/FilterChainMatcher.java`:
- Around line 158-179: Selection of filter chains is happening too early in
FilterChainMatcher.narrow, before TLS metadata like sniHostname() and
alpnProtocols() is available from ConnectionContext. Update
XdsServerPlugin/FilterChainMatcher so server_names and application_protocols are
evaluated only after ClientHello is parsed, or split matching into a pre-TLS
phase and a handshake-aware phase; keep the existing wildcard handling as the
fallback. Use the narrow(...) logic and any related matchers in the 241-264
range to relocate the SNI/ALPN-dependent checks to the correct post-handshake
point.
- Around line 68-79: The FilterChainMatcher currently omits several
FilterChainMatch dimensions, so unsupported matches can be silently misrouted.
Update the matching flow in FilterChainMatcher to either implement narrowing for
prefix_ranges, direct_source_prefix_ranges, source_type, source_prefix_ranges,
and source_ports alongside the existing DestinationPortStep, ServerNamesStep,
TransportProtocolStep, and ApplicationProtocolsStep, or explicitly reject
snapshots containing any of those fields before building the steps list. Ensure
the behavior is enforced where the matcher is constructed so unsupported
dimensions cannot fall through unnoticed.
In `@xds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.java`:
- Around line 111-113: The public API method matchFilterChain currently accepts
ctx without an explicit null check, so add a requireNonNull(ctx, "ctx") at the
start of ListenerSnapshot.matchFilterChain before delegating to
filterChainMatcher.match; keep the check in this method itself so the public
contract is enforced directly and the error is immediate and descriptive.
In `@xds/src/main/java/com/linecorp/armeria/xds/RouteSnapshot.java`:
- Around line 68-76: Add an explicit public-API null check for the
select(RequestContext ctx) parameter before any dereference, so invalid calls
fail with an actionable argument error instead of a generic NPE. Update the
RouteSnapshot.select method to validate ctx at the start, then continue with the
existing authority resolution logic for ClientRequestContext and HttpRequest.
In `@xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java`:
- Around line 1-4: Update the Java source header in ServerSnapshotWatcher to use
the repository’s required LY copyright header instead of LINE Corporation.
Replace the existing top-of-file comment in this new class with the standard LY
header used by other Java files in the repo, keeping the rest of the license
block consistent. Use the file’s opening comment and the ServerSnapshotWatcher
class as the location to apply the header change.
---
Outside diff comments:
In `@xds/src/main/java/com/linecorp/armeria/xds/VirtualHostMatcher.java`:
- Around line 85-122: Normalize the incoming authority in
VirtualHostMatcher.find before doing exactMatch, prefixMatch, and suffixMatch
lookups, since the configured hostnames are already lower-cased but the request
authority is compared raw. Update the find(`@Nullable` String authority) flow to
canonicalize the non-null authority consistently (including the
ignorePortInHostMatching branch) so mixed-case :authority/Host values still
match the same VirtualHostSnapshot entries.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 65d2a652-c855-44ae-a3ef-4e6b7096eeef
📒 Files selected for processing (24)
core/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.javacore/src/main/java/com/linecorp/armeria/server/ServerBuilder.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiPortTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.javait/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactoryit/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.javait/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.javaxds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.javaxds/src/main/java/com/linecorp/armeria/xds/FilterChainMatcher.javaxds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/RouteEntry.javaxds/src/main/java/com/linecorp/armeria/xds/RouteEntryMatcher.javaxds/src/main/java/com/linecorp/armeria/xds/RouteSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.javaxds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/VirtualHostMatcher.javaxds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.javaxds/src/main/java/com/linecorp/armeria/xds/client/endpoint/RouteConfig.java
✅ Files skipped from review due to trivial changes (1)
- it/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactory
🚧 Files skipped from review as they are similar to previous changes (11)
- xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.java
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.java
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.java
- xds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.java
- xds/src/main/java/com/linecorp/armeria/xds/XdsServerPlugin.java
| // Steps are in priority order. Skipped upstream levels (2, 6-9) are omitted. | ||
| // 2. prefix_ranges (destination IP) — skipped. Envoy narrows by longest CIDR prefix match. | ||
| // 6. direct_source_prefix_ranges — skipped. Envoy narrows by CIDR match on direct remote address. | ||
| // 7. source_type — skipped. Envoy narrows by ANY/SAME_IP_OR_LOOPBACK/EXTERNAL. | ||
| // 8. source_prefix_ranges — skipped. Envoy narrows by CIDR match on remote address. | ||
| // 9. source_ports — skipped. Envoy narrows by exact match on remote port. | ||
| steps = ImmutableList.of( | ||
| new DestinationPortStep(filterChains), // 1 | ||
| new ServerNamesStep(filterChains), // 3 | ||
| new TransportProtocolStep(filterChains), // 4 | ||
| new ApplicationProtocolsStep(filterChains) // 5 | ||
| ); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Don't silently ignore unsupported FilterChainMatch dimensions.
prefix_ranges, direct_source_prefix_ranges, source_type, source_prefix_ranges, and source_ports are dropped entirely here. A listener that sets any of those fields can resolve to the wrong filter chain, which then drives both per-connection TLS selection and xDS route dispatch. Either implement these narrowing steps or reject snapshots that contain them.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@xds/src/main/java/com/linecorp/armeria/xds/FilterChainMatcher.java` around
lines 68 - 79, The FilterChainMatcher currently omits several FilterChainMatch
dimensions, so unsupported matches can be silently misrouted. Update the
matching flow in FilterChainMatcher to either implement narrowing for
prefix_ranges, direct_source_prefix_ranges, source_type, source_prefix_ranges,
and source_ports alongside the existing DestinationPortStep, ServerNamesStep,
TransportProtocolStep, and ApplicationProtocolsStep, or explicitly reject
snapshots containing any of those fields before building the steps list. Ensure
the behavior is enforced where the matcher is constructed so unsupported
dimensions cannot fall through unnoticed.
| /* | ||
| * Copyright 2025 LINE Corporation | ||
| * | ||
| * LINE Corporation licenses this file to you under the Apache License, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use the repository's LY copyright header here.
This new file still says LINE Corporation, which diverges from the required Java source header and can trip header validation. As per path instructions, modified Java sources should use the required LY copyright header.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@xds/src/main/java/com/linecorp/armeria/xds/ServerSnapshotWatcher.java` around
lines 1 - 4, Update the Java source header in ServerSnapshotWatcher to use the
repository’s required LY copyright header instead of LINE Corporation. Replace
the existing top-of-file comment in this new class with the standard LY header
used by other Java files in the repo, keeping the rest of the license block
consistent. Use the file’s opening comment and the ServerSnapshotWatcher class
as the location to apply the header change.
Source: Path instructions
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
xds/src/main/java/com/linecorp/armeria/xds/client/endpoint/DefaultXdsLoadBalancerFactory.java (1)
96-102: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUpdate the unsupported-type error message to include
ORIGINAL_DST.Line 102 is now inconsistent with the supported switch cases, which can mislead debugging.
Suggested patch
default: throw new UnsupportedOperationException( "Cluster (" + cluster.getName() + ") is attempting to use an " + "unsupported cluster type: (" + cluster.getType() + "). " + - "Only (STATIC, STRICT_DNS, EDS) are supported."); + "Only (STATIC, STRICT_DNS, EDS, ORIGINAL_DST) are supported."); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xds/src/main/java/com/linecorp/armeria/xds/client/endpoint/DefaultXdsLoadBalancerFactory.java` around lines 96 - 102, The unsupported-cluster error message in DefaultXdsLoadBalancerFactory should match the switch cases by including ORIGINAL_DST in the list of supported types. Update the UnsupportedOperationException text in the cluster type handling logic so it reflects all accepted values, using the DefaultXdsLoadBalancerFactory and cluster.getType() branch as the location to adjust.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In
`@xds/src/main/java/com/linecorp/armeria/xds/client/endpoint/DefaultXdsLoadBalancerFactory.java`:
- Around line 96-102: The unsupported-cluster error message in
DefaultXdsLoadBalancerFactory should match the switch cases by including
ORIGINAL_DST in the list of supported types. Update the
UnsupportedOperationException text in the cluster type handling logic so it
reflects all accepted values, using the DefaultXdsLoadBalancerFactory and
cluster.getType() branch as the location to adjust.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fa83ddd8-4a8c-4ca1-893a-dc2dda05e874
📒 Files selected for processing (4)
xds/src/main/java/com/linecorp/armeria/xds/FilterChainMatcher.javaxds/src/main/java/com/linecorp/armeria/xds/OriginalDstClusterTypeFactory.javaxds/src/main/java/com/linecorp/armeria/xds/XdsExtensionRegistry.javaxds/src/main/java/com/linecorp/armeria/xds/client/endpoint/DefaultXdsLoadBalancerFactory.java
🚧 Files skipped from review as they are similar to previous changes (1)
- xds/src/main/java/com/linecorp/armeria/xds/FilterChainMatcher.java
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@xds/src/main/java/com/linecorp/armeria/xds/server/ServerSnapshotWatcher.java`:
- Around line 36-40: The ServerSnapshotWatcher currently stores only a single
ServiceConfig, so later service additions overwrite earlier ones and snapshot
refreshes replay invokeServiceAdded(...) for only the last service. Update
ServerSnapshotWatcher.serviceAdded() and the listener refresh path to retain all
registered ServiceConfig instances, then replay serviceAdded for each stored
config when listenerSnapshot changes; use the existing readyFuture,
listenerSnapshot, and serviceConfig state as the starting point for locating the
affected logic.
- Around line 95-100: The replay is happening against the previous listener
snapshot because invokeServiceAdded(cfg) runs before listenerSnapshot is updated
in ServerSnapshotWatcher. Update this flow so the new listenerSnapshot is
assigned before any replay logic, then invoke service-added replay using the new
snapshot state in the same update path. Use the existing ServerSnapshotWatcher
update sequence around listenerSnapshot, readyFuture.complete, and
invokeServiceAdded to keep the callback replay aligned with the latest snapshot.
In `@xds/src/main/java/com/linecorp/armeria/xds/server/XdsServerPlugin.java`:
- Around line 153-170: Filter-chain matching in XdsServerPlugin.accept is
happening too early, before TLS negotiation has populated SNI/ALPN information.
Update the accept path so it only does xDS filter-chain selection when the
needed connection attributes are already available, or defer the
watcher.match(ctx) lookup until the TLS handshake phase for listeners that
depend on server names, transport_protocol, or application protocols. Keep the
existing managed-port check and existingAcceptor fallback, but ensure the
selection logic in accept and any related matching entry points only runs when
the connection context can reliably expose those values.
- Around line 164-170: The xDS-managed branch in XdsServerPlugin.shouldAccept
currently short-circuits to true after watcher.match(ctx), which bypasses the
existingAcceptor policy entirely. Update the match handling so that a matched
FilterChainSnapshot still delegates to existingAcceptor.accept(ctx) and only
returns true when both the filter-chain match and the existing connection policy
allow it, while preserving the MATCHED_FILTER_CHAIN attribute set on the
context.
In `@xds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.java`:
- Around line 156-157: The public
TransportSocketSnapshot.serverTlsSpec(ConnectionContext) API should reject a
null ctx explicitly instead of relying on a downstream NPE. Add an
Objects.requireNonNull(ctx, "ctx") check at the start of serverTlsSpec so the
method fails fast with the standard argument error before delegating to
serverTlsSpecSelector.select(ctx).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a39cc5e0-e867-4572-b532-5ba8ae7d5fe6
📒 Files selected for processing (33)
core/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.javacore/src/main/java/com/linecorp/armeria/server/ServerBuilder.javacore/src/main/java/com/linecorp/armeria/server/ServerTlsProvider.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiPortTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerMultiplePluginTest.javait/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.javait/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactoryit/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.javait/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.javait/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.javaxds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.javaxds/src/main/java/com/linecorp/armeria/xds/FilterChainMatcher.javaxds/src/main/java/com/linecorp/armeria/xds/FilterUtil.javaxds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/OriginalDstClusterTypeFactory.javaxds/src/main/java/com/linecorp/armeria/xds/RouteEntry.javaxds/src/main/java/com/linecorp/armeria/xds/RouteEntryMatcher.javaxds/src/main/java/com/linecorp/armeria/xds/RouteSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/ServerTlsSpecSelector.javaxds/src/main/java/com/linecorp/armeria/xds/TransportSocketSnapshot.javaxds/src/main/java/com/linecorp/armeria/xds/VirtualHostMatcher.javaxds/src/main/java/com/linecorp/armeria/xds/XdsExtensionRegistry.javaxds/src/main/java/com/linecorp/armeria/xds/client/endpoint/DefaultXdsLoadBalancerFactory.javaxds/src/main/java/com/linecorp/armeria/xds/client/endpoint/RouteConfig.javaxds/src/main/java/com/linecorp/armeria/xds/internal/DelegatingHttpService.javaxds/src/main/java/com/linecorp/armeria/xds/server/ServerSnapshotWatcher.javaxds/src/main/java/com/linecorp/armeria/xds/server/XdsServerPlugin.javaxds/src/main/java/com/linecorp/armeria/xds/server/XdsServerPluginBuilder.javaxds/src/main/java/com/linecorp/armeria/xds/server/package-info.java
✅ Files skipped from review due to trivial changes (4)
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioPodCustomizer.java
- it/xds-client/src/test/resources/META-INF/services/com.linecorp.armeria.xds.filter.HttpFilterFactory
- xds/src/main/java/com/linecorp/armeria/xds/server/package-info.java
- xds/src/main/java/com/linecorp/armeria/xds/FilterUtil.java
🚧 Files skipped from review as they are similar to previous changes (20)
- core/src/main/java/com/linecorp/armeria/server/ConnectionLevelSetters.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsResourceReader.java
- xds/src/main/java/com/linecorp/armeria/xds/DownstreamTlsTransportSocketFactory.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerConnectionConfigTest.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/TestHeaderFilterFactory.java
- it/xds-client/src/test/java/com/linecorp/armeria/xds/it/ServerDecoratorTest.java
- xds/src/main/java/com/linecorp/armeria/xds/XdsExtensionRegistry.java
- xds/src/main/java/com/linecorp/armeria/xds/RouteEntry.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsClientToServerTest.java
- xds/src/main/java/com/linecorp/armeria/xds/client/endpoint/RouteConfig.java
- xds/src/main/java/com/linecorp/armeria/xds/client/endpoint/DefaultXdsLoadBalancerFactory.java
- xds/src/main/java/com/linecorp/armeria/xds/RouteEntryMatcher.java
- xds/src/main/java/com/linecorp/armeria/xds/OriginalDstClusterTypeFactory.java
- xds/src/main/java/com/linecorp/armeria/xds/ListenerSnapshot.java
- it/xds-istio/src/test/java/com/linecorp/armeria/it/xds/XdsEchoConfigurator.java
- it/xds-istio/src/main/java/com/linecorp/armeria/it/istio/testing/IstioServerExtension.java
- core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java
- xds/src/main/java/com/linecorp/armeria/xds/RouteSnapshot.java
- xds/src/main/java/com/linecorp/armeria/xds/VirtualHostMatcher.java
- xds/src/main/java/com/linecorp/armeria/xds/FilterChainMatcher.java
| private final CompletableFuture<Void> readyFuture = new CompletableFuture<>(); | ||
| @Nullable | ||
| private volatile ListenerSnapshot listenerSnapshot; | ||
| @Nullable | ||
| private volatile ServiceConfig serviceConfig; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Don't overwrite previously registered ServiceConfigs.
serviceAdded() keeps only the last ServiceConfig. After the second decorated service is added, later listener updates replay invokeServiceAdded(...) for that one config only, so xDS route/filter services tied to earlier user services stop receiving serviceAdded on snapshot refresh.
Also applies to: 46-48, 95-99
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@xds/src/main/java/com/linecorp/armeria/xds/server/ServerSnapshotWatcher.java`
around lines 36 - 40, The ServerSnapshotWatcher currently stores only a single
ServiceConfig, so later service additions overwrite earlier ones and snapshot
refreshes replay invokeServiceAdded(...) for only the last service. Update
ServerSnapshotWatcher.serviceAdded() and the listener refresh path to retain all
registered ServiceConfig instances, then replay serviceAdded for each stored
config when listenerSnapshot changes; use the existing readyFuture,
listenerSnapshot, and serviceConfig state as the starting point for locating the
affected logic.
| public CompletableFuture<Boolean> accept(ConnectionContext ctx) { | ||
| // Only apply xDS policy to connections on xDS-managed ports. | ||
| // actualPort() resolves ephemeral ports (0) to the real bound port. | ||
| final int port = ctx.localAddress().getPort(); | ||
| boolean managed = false; | ||
| for (ServerPort sp : serverPorts) { | ||
| if (sp.actualPort() == port) { | ||
| managed = true; | ||
| break; | ||
| } | ||
| } | ||
| if (!managed) { | ||
| return existingAcceptor.accept(ctx); | ||
| } | ||
| final FilterChainSnapshot matched = watcher.match(ctx); | ||
| if (matched != null) { | ||
| ctx.setAttr(MATCHED_FILTER_CHAIN, matched); | ||
| return UnmodifiableFuture.completedFuture(true); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Filter-chain matching is happening before SNI/ALPN are available.
ConnectionAcceptor runs before TLS negotiation, but watcher.match(ctx) delegates to filter-chain matching that narrows on server names / transport protocol / application protocols. On TLS listeners those values are unresolved here, so server_names, transport_protocol: tls, and ALPN-based chains cannot be selected reliably.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@xds/src/main/java/com/linecorp/armeria/xds/server/XdsServerPlugin.java`
around lines 153 - 170, Filter-chain matching in XdsServerPlugin.accept is
happening too early, before TLS negotiation has populated SNI/ALPN information.
Update the accept path so it only does xDS filter-chain selection when the
needed connection attributes are already available, or defer the
watcher.match(ctx) lookup until the TLS handshake phase for listeners that
depend on server names, transport_protocol, or application protocols. Keep the
existing managed-port check and existingAcceptor fallback, but ensure the
selection logic in accept and any related matching entry points only runs when
the connection context can reliably expose those values.
456feea to
26487ea
Compare
… xDS (#6837) Motivation: This is a subset of #6797 that adds server-side filter chain matching and SNI-based TLS certificate selection to the xDS module. When Armeria acts as an xDS-managed server, incoming connections need to be matched against the listener's `filter_chains` to determine which TLS configuration and routing to apply — replicating Envoy's [filter chain matching](https://github.com/envoyproxy/envoy/blob/74ef415825d391edc129afd17d2cb640abe785e9/source/common/listener_manager/filter_chain_manager_impl.cc#L543) semantics. Modifications: - Added `FilterChainMatcher` which implements Envoy's BFS-style multi-pass narrowing algorithm. Supported match dimensions (in priority order): `destination_port`, `server_names`, `transport_protocol`, `application_protocols`. Each level precomputes specific/wildcard partitions to avoid redundant iteration. - Added `ServerTlsSpecSelector` which implements SNI-based certificate selection: exact DNS SAN match → wildcard match (e.g. `*.example.com`) → fallback to first certificate. Follows Envoy's `DefaultTlsCertificateSelector` behavior. - Added `ListenerSnapshot.matchFilterChain(ConnectionContext)` that delegates to `FilterChainMatcher`. - Added `TransportSocketSnapshot.serverTlsSpec(ConnectionContext)` that delegates to `ServerTlsSpecSelector`. The downstream constructor builds a `ServerTlsSpec` per certificate using the shared `applyCommonTlsConfig` method (same trust/verifier logic as the client path). - Marked `destination_port`, `server_names`, `transport_protocol`, and `application_protocols` fields as supported in `listener_components.proto`. - Added `ServerFilterChainMatchTest` — verifies transport protocol matching, default filter chain fallback, and unmatched connection rejection. - Added `ServerTlsSpecSelectorTest` — verifies exact SNI match, wildcard fallback, and no-SNI fallback. Result: - `ListenerSnapshot` can now select the correct filter chain for an incoming connection based on destination port, SNI hostname, transport protocol, and ALPN. - `TransportSocketSnapshot` can select the correct server TLS certificate based on SNI, supporting multi-certificate downstream listeners.
Motivation:
Explain why you're making this change and what problem you're trying to solve.
Modifications:
Result: