Skip to content

Add SessionProtocol.withTls()/withoutTls() and per-endpoint TLS/cleartext switching#6850

Draft
jrhee17 wants to merge 2 commits into
line:mainfrom
jrhee17:bugfix/xds-mixed-protocol
Draft

Add SessionProtocol.withTls()/withoutTls() and per-endpoint TLS/cleartext switching#6850
jrhee17 wants to merge 2 commits into
line:mainfrom
jrhee17:bugfix/xds-mixed-protocol

Conversation

@jrhee17

@jrhee17 jrhee17 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Motivation:

I found this bug while debugging the xDS integration with Istio.

When a cluster has mixed TLS and plaintext endpoints (via transport_socket_matches), the session protocol must switch dynamically per endpoint. Previously, ClusterFilterFactory picked a fixed session protocol at cluster level based on whether a default transport_socket was present. This meant all endpoints in a cluster used the same TLS/cleartext setting, which broke mixed clusters where some endpoints use UpstreamTlsContext and others use raw_buffer.

Modifications:

  • Added SessionProtocol.withTls() and withoutTls() methods that switch between TLS and non-TLS variants while preserving the HTTP version (e.g., H2CH2, H1CH1, HTTPHTTPS).
  • Added ClientRequestContext.setClientTlsSpec() and clearClientTlsSpec() methods. setClientTlsSpec() automatically switches the session protocol to its TLS variant; clearClientTlsSpec() switches to the non-TLS variant.
  • Changed ClusterFilterFactory to always default to a TLS session protocol (based on HttpProtocolOptions), and defer per-endpoint TLS decisions to the applyClusterSettings decorator which inspects TransportSocketSnapshot: if the endpoint's transport socket has a ClientTlsSpec, it is set; if it is a raw_buffer (null spec), the TLS spec is cleared and the protocol switches to cleartext.
  • Removed the transportSocket parameter from the ClusterFilterFactory constructor since TLS is no longer decided at cluster level.
  • Added MixedTransportSocketSessionProtocolTest verifying that a round-robin cluster with one TLS endpoint and one plaintext endpoint uses the correct session protocol for each.
  • Added MixedTransportSocketRetryTest verifying that retry-created derived contexts also get the correct per-endpoint session protocol when retrying across mixed endpoints through real server connections.

Result:

  • Clusters with transport_socket_matches containing both TLS and raw_buffer entries now correctly switch between TLS and cleartext per endpoint.
  • Retry attempts across mixed endpoints preserve the correct session protocol in each derived context.

@jrhee17 jrhee17 added this to the 1.41.0 milestone Jul 9, 2026
@jrhee17 jrhee17 added the defect label Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds clearClientTlsSpec() and SessionProtocol.withoutTls(), refactors client request-context header/session-protocol updates, changes xDS cluster session-protocol derivation, and adds unit and integration tests for mixed TLS/plaintext endpoint handling.

Changes

Client TLS spec clear API and session protocol switching

Layer / File(s) Summary
SessionProtocol.withoutTls() and ClientRequestContext API additions
core/src/main/java/com/linecorp/armeria/common/SessionProtocol.java, core/src/main/java/com/linecorp/armeria/client/ClientRequestContext.java, core/src/main/java/com/linecorp/armeria/client/ClientRequestContextWrapper.java
Adds withoutTls() mapping TLS variants to cleartext equivalents; declares and documents clearClientTlsSpec() and updated setClientTlsSpec javadoc; wrapper delegates the new method.
DefaultClientRequestContext refactor
core/src/main/java/com/linecorp/armeria/internal/client/DefaultClientRequestContext.java
Introduces updateInternalHeaders() helper used by updateEndpoint and setSessionProtocol, removes the post-init guard blocking protocol changes, and implements setClientTlsSpec and clearClientTlsSpec to switch sessionProtocol accordingly.
Session protocol tests
core/src/test/java/com/linecorp/armeria/internal/client/DefaultClientRequestContextTest.java
Adds tests for scheme/header updates, Origin header updates, derived context inheritance, and HTTP/HTTPS toggling before and after init().

xDS cluster session protocol simplification and integration tests

Layer / File(s) Summary
ClusterFilterFactory and ClusterStream wiring
xds/src/main/java/com/linecorp/armeria/xds/ClusterFilterFactory.java, xds/src/main/java/com/linecorp/armeria/xds/ClusterStream.java
Removes TLS-based session protocol derivation from TransportSocketSnapshot; derives sessionProtocol from HttpProtocolOptions only; clears ClientTlsSpec when absent; updates ClusterFilterFactory constructor call.
Mixed transport socket integration tests
it/xds-client/src/test/java/com/linecorp/armeria/xds/it/MixedTransportSocketRetryTest.java, it/xds-client/src/test/java/com/linecorp/armeria/xds/it/MixedTransportSocketSessionProtocolTest.java
Adds integration tests validating child and derived request contexts select correct TLS/plaintext SessionProtocol per resolved endpoint, including retry scenarios and base64 cert helpers.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ClientRequestContext
  participant SessionProtocol
  participant ClientRequestContextWrapper

  ClientRequestContext->>SessionProtocol: withoutTls()
  ClientRequestContextWrapper->>ClientRequestContext: clearClientTlsSpec()
Loading
sequenceDiagram
  participant ClusterStream
  participant ClusterFilterFactory
  participant RequestContext

  ClusterStream->>ClusterFilterFactory: new ClusterFilterFactory(lb, httpProtocolOptions)
  ClusterFilterFactory->>ClusterFilterFactory: sessionProtocol(httpProtocolOptions)
  ClusterFilterFactory->>RequestContext: applyClusterSettings(endpoint)
  ClusterFilterFactory->>RequestContext: clearClientTlsSpec() when absent
Loading

Possibly related PRs

  • line/armeria#6542: Both PRs evolve client TLS/session-protocol handling around ClientTlsSpec, including TLS/non-TLS protocol switching.
  • line/armeria#6551: Both PRs extend per-request TLS customization via ClientRequestContext and setClientTlsSpec handling.
  • line/armeria#6843: Both PRs touch xDS ClusterFilterFactory/ClusterStream session-protocol selection from cluster configuration.

Suggested labels: new feature

Suggested reviewers: trustin, ikhoon, minwoox

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title names the new SessionProtocol methods and the endpoint-level TLS/cleartext switching, matching the main change.
Description check ✅ Passed The description accurately describes the xDS mixed TLS/plaintext behavior changes and added tests, so it is clearly related.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
it/xds-client/src/test/java/com/linecorp/armeria/xds/it/MixedTransportSocketRetryTest.java (1)

195-197: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting base64Cert to a shared utility.

The base64Cert method is duplicated verbatim in MixedTransportSocketSessionProtocolTest. Consider extracting it (and XdsCertificateExtension if co-located) to a shared test helper in the same package to reduce duplication.

🤖 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/MixedTransportSocketRetryTest.java`
around lines 195 - 197, The `base64Cert` helper is duplicated in
`MixedTransportSocketRetryTest` and `MixedTransportSocketSessionProtocolTest`;
move it into a shared test utility in the same package and update both tests to
call that shared helper. If `XdsCertificateExtension` belongs with it, co-locate
that logic in the same helper so the duplicated certificate-loading code is
centralized and easier to maintain.
core/src/test/java/com/linecorp/armeria/internal/client/DefaultClientRequestContextTest.java (1)

447-552: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

LGTM on the new setSessionProtocol tests — they're logically consistent with the implementation. One gap: this file doesn't directly test setClientTlsSpec()/clearClientTlsSpec() driving the sessionProtocol TLS/cleartext switch (lines 1112-1126 in DefaultClientRequestContext.java), only setSessionProtocol() itself. Consider adding a test mirroring the existing pattern to cover that path directly.

🤖 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/internal/client/DefaultClientRequestContextTest.java`
around lines 447 - 552, The new tests cover setSessionProtocol() directly, but
they do not exercise the TLS/cleartext transition triggered by
setClientTlsSpec() and clearClientTlsSpec(). Add a test in
DefaultClientRequestContextTest that follows the existing init/update assertions
and verifies that calling setClientTlsSpec() switches sessionProtocol() and
URI/header scheme to HTTPS, and clearClientTlsSpec() switches them back to HTTP.
Use the existing DefaultClientRequestContext, sessionProtocol(), uri(), and
internalRequestHeaders() patterns to keep the coverage aligned with the current
tests.
🤖 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.

Nitpick comments:
In
`@core/src/test/java/com/linecorp/armeria/internal/client/DefaultClientRequestContextTest.java`:
- Around line 447-552: The new tests cover setSessionProtocol() directly, but
they do not exercise the TLS/cleartext transition triggered by
setClientTlsSpec() and clearClientTlsSpec(). Add a test in
DefaultClientRequestContextTest that follows the existing init/update assertions
and verifies that calling setClientTlsSpec() switches sessionProtocol() and
URI/header scheme to HTTPS, and clearClientTlsSpec() switches them back to HTTP.
Use the existing DefaultClientRequestContext, sessionProtocol(), uri(), and
internalRequestHeaders() patterns to keep the coverage aligned with the current
tests.

In
`@it/xds-client/src/test/java/com/linecorp/armeria/xds/it/MixedTransportSocketRetryTest.java`:
- Around line 195-197: The `base64Cert` helper is duplicated in
`MixedTransportSocketRetryTest` and `MixedTransportSocketSessionProtocolTest`;
move it into a shared test utility in the same package and update both tests to
call that shared helper. If `XdsCertificateExtension` belongs with it, co-locate
that logic in the same helper so the duplicated certificate-loading code is
centralized and easier to maintain.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8870940b-b434-4f1e-96ba-66b192801121

📥 Commits

Reviewing files that changed from the base of the PR and between fe73b6c and b9813b3.

📒 Files selected for processing (9)
  • core/src/main/java/com/linecorp/armeria/client/ClientRequestContext.java
  • core/src/main/java/com/linecorp/armeria/client/ClientRequestContextWrapper.java
  • core/src/main/java/com/linecorp/armeria/common/SessionProtocol.java
  • core/src/main/java/com/linecorp/armeria/internal/client/DefaultClientRequestContext.java
  • core/src/test/java/com/linecorp/armeria/internal/client/DefaultClientRequestContextTest.java
  • it/xds-client/src/test/java/com/linecorp/armeria/xds/it/MixedTransportSocketRetryTest.java
  • it/xds-client/src/test/java/com/linecorp/armeria/xds/it/MixedTransportSocketSessionProtocolTest.java
  • xds/src/main/java/com/linecorp/armeria/xds/ClusterFilterFactory.java
  • xds/src/main/java/com/linecorp/armeria/xds/ClusterStream.java

@jrhee17 jrhee17 added cleanup and removed defect labels Jul 9, 2026
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.00000% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.05%. Comparing base (8150425) to head (60c0406).
⚠️ Report is 529 commits behind head on main.

Files with missing lines Patch % Lines
...a/com/linecorp/armeria/common/SessionProtocol.java 62.50% 1 Missing and 2 partials ⚠️
...a/internal/client/DefaultClientRequestContext.java 66.66% 1 Missing and 2 partials ⚠️
...rp/armeria/client/ClientRequestContextWrapper.java 0.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #6850      +/-   ##
============================================
+ Coverage     74.46%   75.05%   +0.59%     
- Complexity    22234    25326    +3092     
============================================
  Files          1963     2252     +289     
  Lines         82437    94112   +11675     
  Branches      10764    12307    +1543     
============================================
+ Hits          61385    70636    +9251     
- Misses        15918    17625    +1707     
- Partials       5134     5851     +717     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jrhee17 jrhee17 marked this pull request as ready for review July 9, 2026 22:51
@jrhee17 jrhee17 requested review from ikhoon and minwoox as code owners July 9, 2026 22:51
@mergify

mergify Bot commented Jul 9, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@jrhee17 jrhee17 marked this pull request as draft July 9, 2026 23:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant