Skip to content

build: update OkHttp to 5.3.0 stable#9

Merged
hawkff merged 2 commits into
mainfrom
maintenance/update-okhttp
Jun 15, 2026
Merged

build: update OkHttp to 5.3.0 stable#9
hawkff merged 2 commits into
mainfrom
maintenance/update-okhttp

Conversation

@hawkff

@hawkff hawkff commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Summary

Moves OkHttp off the pre-release 5.0.0-alpha.3 to stable 5.3.0, and removes an
unstable OkHttp-internal API usage.

Before After
com.squareup.okhttp3:okhttp 5.0.0-alpha.3 5.3.0

Why 5.3.0 and not 5.4.0

OkHttp 5.4.0's okhttp-android artifact declares minCompileSdk=36, but this
project compiles against android-35. Verified from the published AAR metadata:

  • okhttp-android 5.0.0–5.3.0: minCompileSdk=1
  • okhttp-android 5.4.0: minCompileSdk=36

5.3.0 is the latest stable that works with the current compileSdk 35. Moving to 5.4.0
is deferred until a separate compileSdk 36 bump in the build-stack track (out of scope
for a dependency update).

API compatibility

The OkHttp surface used here is stable across 5.x: OkHttpClient/Builder,
newCall().execute(), Request.Builder, Credentials.basic, toMediaType/
toRequestBody, HttpUrl. No source changes needed for the bump itself.

Internal API cleanup (commit 2)

Replaced okhttp3.internal.closeQuietly (an unstable okhttp3.internal API used on a
ZipInputStream and a Socket in ConfigurationFragment.kt) with a small private
Closeable.closeQuietly() extension of identical semantics — so future OkHttp upgrades
can't break on an internal API removal. Flagged by review; in scope as OkHttp-robustness.

Verification (AWS Linux builder)

  • ./gradlew app:assembleOssDebug app:assembleOssRelease — BUILD SUCCESSFUL.
    Release exercises R8 shrinking (OkHttp consumer ProGuard rules) and lintVital with
    warningsAsErrors=true. The checkAarMetadata task (which rejected 5.4.0) passes for 5.3.0.
  • Local CodeRabbit review: 0 findings.

Scope

  • app/build.gradle.kts (1 line) + ConfigurationFragment.kt (import swap + tiny helper).
    No other dependencies, no compileSdk change.

Runtime testing note

Build-verified only (emulator blocked by EC2 vCPU quota; increase pending). OkHttp powers
subscription fetch, WebDAV backup/restore, and asset downloads — batched runtime QA planned.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The com.squareup.okhttp3:okhttp dependency is upgraded from 5.0.0-alpha.3 to 5.3.0, and the code removes reliance on OkHttp's internal closeQuietly method. A local Closeable.closeQuietly() extension function is added to ConfigurationFragment to provide safe resource closure without external internal API dependencies.

Changes

OkHttp Version Upgrade with Internal API Migration

Layer / File(s) Summary
okhttp version update
app/build.gradle.kts
com.squareup.okhttp3:okhttp dependency version upgraded from 5.0.0-alpha.3 to 5.3.0.
Remove internal API dependency
app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt
Import changed from OkHttp's internal okhttp3.internal.closeQuietly to java.io.Closeable, and a local private fun Closeable.closeQuietly() extension added that closes resources and silently ignores exceptions.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐇 From alpha.3 to stable ground we bound,
OkHttp 5.3.0, a newer release found!
Internal APIs must go, so we write our own way,
A closeQuietly extension saves the day.
One bump, one fix — the rabbit's work is done! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 'build: update OkHttp to 5.3.0 stable' directly and accurately summarizes the main change: upgrading OkHttp from 5.0.0-alpha.3 to 5.3.0 stable.
Description check ✅ Passed The description comprehensively covers the pull request changes, including the OkHttp version upgrade, the internal API cleanup with closeQuietly replacement, and detailed rationale for choosing 5.3.0 over 5.4.0 based on compileSdk constraints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@hawkff hawkff marked this pull request as ready for review June 15, 2026 18:51
@hawkff

hawkff commented Jun 15, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

Please focus on OkHttp 5.x API compatibility and ProGuard/R8 behavior.

Note on the timeout-API suggestion: OkHttp 5.x retains the (long, TimeUnit) timeout overloads, so the existing TimeUnit.SECONDS calls compile and run fine. Verified by clean debug AND release builds (R8 shrinking included). Migrating to kotlin.time.Duration is optional and would touch unrelated files, so it's intentionally out of scope for this dependency bump.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== app/build.gradle.kts (OkHttp dependency line) ==="
grep -n -i "okhttp" app/build.gradle.kts || echo "Not found"

echo ""
echo "=== All OkHttp imports across the codebase ==="
rg -n "okhttp3" --type kotlin --type java -A1

echo ""
echo "=== All files that import OkHttp ==="
rg -l "okhttp3" --type kotlin --type java

echo ""
echo "=== OkHttpClient builder usages ==="
rg -n "OkHttpClient" --type kotlin --type java -C3

echo ""
echo "=== Timeout usages ==="
rg -n "Timeout\|connectTimeout\|readTimeout\|writeTimeout\|callTimeout" --type kotlin --type java -C2

echo ""
echo "=== Credentials.basic usages ==="
rg -n "Credentials" --type kotlin --type java -C3

echo ""
echo "=== MediaType usages ==="
rg -n "MediaType\|toMediaType\|toMediaTypeOrNull" --type kotlin --type java -C3

echo ""
echo "=== RequestBody usages ==="
rg -n "RequestBody\|toRequestBody" --type kotlin --type java -C3

echo ""
echo "=== HttpUrl usages ==="
rg -n "HttpUrl" --type kotlin --type java -C3

echo ""
echo "=== Any deprecated API usages ==="
rg -n "\.url\(|\.get\(\)\|\.post\(\)\|\.patch\(\)\|\.delete\(\)\|\.put\(\)" --type kotlin --type java -C2

echo ""
echo "=== ProGuard / R8 rules ==="
fd -e pro -e txt -e rules | head -20
fd "proguard" | head -20

echo ""
echo "=== ProGuard rules content ==="
fd "proguard" | xargs cat 2>/dev/null || echo "No proguard files found via fd"

echo ""
echo "=== consumer-rules and other R8 config ==="
fd "consumer-rules\|proguard-rules\|r8" | xargs cat 2>/dev/null || echo "none"

echo ""
echo "=== build.gradle.kts R8/minify config ==="
grep -n -i "minif\|proguard\|r8\|shrink\|obfuscat" app/build.gradle.kts || echo "Not found"

echo ""
echo "=== Full app/build.gradle.kts ==="
cat app/build.gradle.kts

Length of output: 13396


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== ConfigurationFragment.kt closeQuietly usage ==="
grep -n "closeQuietly\|internal" app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt -A3 -B3

echo ""
echo "=== Helpers.kt okhttp3 keep rule context ==="
sed -n '75,100p' buildSrc/src/main/kotlin/Helpers.kt

echo ""
echo "=== BackupFragment.kt OkHttpClient usage (full context) ==="
sed -n '190,280p' app/src/main/java/io/nekohasekai/sagernet/ui/BackupFragment.kt

echo ""
echo "=== BackupFragment.kt restore section ==="
sed -n '325,400p' app/src/main/java/io/nekohasekai/sagernet/ui/BackupFragment.kt

echo ""
echo "=== WebDAVSettingsActivity.kt OkHttpClient builder full context ==="
sed -n '125,180p' app/src/main/java/io/nekohasekai/sagernet/ui/WebDAVSettingsActivity.kt

echo ""
echo "=== Full Helpers.kt (R8/keep/proguard section) ==="
cat buildSrc/src/main/kotlin/Helpers.kt

echo ""
echo "=== app/build.gradle.kts full content ==="
cat app/build.gradle.kts

echo ""
echo "=== Any proguard-rules.pro files ==="
fd "proguard-rules" | xargs cat 2>/dev/null || echo "none"

echo ""
echo "=== consumer-rules.pro files ==="
fd "consumer-rules" | xargs cat 2>/dev/null || echo "none"

Length of output: 26285



@hawkff: Noted on the timeout-API — acknowledged and recorded below.


Full Review: OkHttp 5.0.0-alpha.3 → 5.4.0

✅ API Compatibility — All Public APIs

Every OkHttp symbol used across the 22 affected files is part of the stable public surface and unchanged across the 5.x line:

API Files Status
OkHttpClient / OkHttpClient.Builder WebDAVSettingsActivity.kt, BackupFragment.kt ✅ Stable
Request.Builder, newCall().execute() BackupFragment.kt, WebDAVSettingsActivity.kt ✅ Stable
Credentials.basic BackupFragment.kt, WebDAVSettingsActivity.kt ✅ Stable
MediaType.Companion.toMediaType BackupFragment.kt, WebDAVSettingsActivity.kt ✅ Stable
RequestBody.Companion.toRequestBody BackupFragment.kt, WebDAVSettingsActivity.kt ✅ Stable
HttpUrl, toHttpUrl, toHttpUrlOrNull 13 format/ktx files ✅ Stable
connectTimeout(long, TimeUnit) WebDAVSettingsActivity.kt ✅ Retained in 5.x (as noted)

⚠️ Internal API Usage — okhttp3.internal.closeQuietly

app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt, Line 119:

import okhttp3.internal.closeQuietly

Used at Line 340 on a ZipInputStream and Line 859 on a Socket. This compiled successfully against 5.4.0 — the extension function still exists in okhttp3.internal as a Closeable extension — but it is an unsupported internal API with no stability guarantees. Any future OkHttp patch could remove it without a deprecation cycle.

This is not introduced by this PR (it predates the bump), but the upgrade is a good moment to flag it. The fix is a one-liner replacement with stdlib:

// Replace:
import okhttp3.internal.closeQuietly
//
zip.closeQuietly()
socket.closeQuietly()

// With (Kotlin stdlib, no OkHttp dependency):
fun Closeable.closeQuietly() = try { close() } catch (_: Exception) {}
// or simply use the try/catch inline, or use .use {} at the call site

Would you like to open a follow-up issue to track this?


✅ ProGuard / R8 Behavior

Consumer rules are applied correctly. OkHttp 5.4.0 ships its consumer ProGuard rules inside the AAR at META-INF/proguard/okhttp3.pro. The packaging.resources.excludes entry "okhttp3/**" in Helpers.kt strips JAR resource files (e.g., okhttp3/internal/publicsuffix/publicsuffix.gz) — it does not affect consumer rules under META-INF/proguard/, which R8 processes from the AAR manifest before packaging. The consumer rules cover OkHttp's own keep requirements.

Your proguard-rules.pro is also correct: -dontobfuscate prevents renaming, and there is no need to add manual -keep rules for OkHttp classes — the library's own consumer rules handle that.

One note on the Public Suffix List: "okhttp3/**" strips publicsuffix.gz from the APK. OkHttp 5.x handles this gracefully with a built-in fallback, so there's no crash risk. This is pre-existing and low-impact for a proxy client.


Pre-existing observations (not introduced by this PR)

  1. BackupFragment.kt Lines 198 and 331OkHttpClient() is constructed with no explicit timeouts. OkHttp 5.x defaults (10 s connect / 10 s read / 10 s write) apply, which is acceptable, but large ZIP uploads could hit the write timeout on slow connections. Consider applying the same builder pattern used in WebDAVSettingsActivity.kt.

  2. WebDAVSettingsActivity.kt Line 155client.newCall(authRequest).execute() response is not wrapped in .use { }, risking a connection leak if an exception is thrown before response.close(). Both items are scope-appropriate for a follow-up.


Summary

The version bump is clean. No source changes are required for 5.4.0 compatibility. The only actionable finding specific to this PR's focus is the okhttp3.internal.closeQuietly import — it works today but carries future-upgrade risk. Everything else is pre-existing or expected behavior.


✏️ Learnings added
Learnt from: hawkff
URL: https://github.com/hawkff/NekoBoxForAndroid/pull/9

Timestamp: 2026-06-15T18:53:49.648Z
Learning: In the NekoBoxForAndroid repo (`app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt`), `okhttp3.internal.closeQuietly` (an internal OkHttp extension on `Closeable`) is imported and used on `ZipInputStream` (line 340) and `Socket` (line 859). This compiles against OkHttp 5.4.0 but is an unstable internal API and should eventually be replaced with a stdlib equivalent.

Learnt from: hawkff
URL: https://github.com/hawkff/NekoBoxForAndroid/pull/9

Timestamp: 2026-06-15T18:53:49.648Z
Learning: In NekoBoxForAndroid, `buildSrc/src/main/kotlin/Helpers.kt` includes `"okhttp3/**"` in `packaging.resources.excludes`. This strips OkHttp's JAR resources (including the Public Suffix List `publicsuffix.gz`) from the APK, but does NOT affect OkHttp's consumer ProGuard/R8 rules (which live at `META-INF/proguard/` in the AAR and are processed separately by R8). OkHttp 5.x falls back gracefully when the Public Suffix List resource is absent.

Learnt from: hawkff
URL: https://github.com/hawkff/NekoBoxForAndroid/pull/9

Timestamp: 2026-06-15T18:53:49.648Z
Learning: In NekoBoxForAndroid `BackupFragment.kt`, `OkHttpClient()` is instantiated with the default no-arg constructor at lines 198 and 331 (no explicit timeouts), unlike `WebDAVSettingsActivity.kt` which uses `OkHttpClient.Builder()` with explicit 10-second connect/read/write timeouts. The defaults in OkHttp 5.x are 10s/10s/10s, so there's no crash risk, but large uploads on slow connections could time out.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Action performed

Full review finished.

hawkff added 2 commits June 15, 2026 14:58
Move off the pre-release alpha to the current stable OkHttp 5.x line.
5.3.0 is the latest stable whose okhttp-android artifact still supports
compileSdk 35 (5.4.0 requires minCompileSdk=36). The network-client API used
(OkHttpClient, newCall/execute, Request.Builder, Credentials.basic,
toMediaType/toRequestBody, HttpUrl) is stable across 5.x; no source changes.
okhttp3.internal.closeQuietly is an unstable internal API. Replace it with a
small private Closeable.closeQuietly() extension (same semantics) so the
OkHttp upgrade path stays robust.
@hawkff hawkff force-pushed the maintenance/update-okhttp branch from 3c311e7 to 97efe89 Compare June 15, 2026 18:58

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt`:
- Around line 2060-2064: The closeQuietly() extension function currently catches
and suppresses all Exception types, which masks RuntimeException and other
programmer errors. Modify the exception handling in closeQuietly() to explicitly
catch and re-throw RuntimeException instances while continuing to silently
suppress checked exceptions like IOException. This matches OkHttp's safer
behavior by allowing real programming errors to surface while safely suppressing
recoverable IO errors.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fb8e6676-a986-4e2d-9fb6-c1df0b20f729

📥 Commits

Reviewing files that changed from the base of the PR and between eb31d36 and 3c311e7.

📒 Files selected for processing (1)
  • app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@app/build.gradle.kts`:
- Line 68: Update the OkHttp dependency version in the implementation
declaration from 5.3.0 to 5.4.0. Locate the com.squareup.okhttp3:okhttp
dependency line and change the version number at the end from 5.3.0 to 5.4.0 to
align with the PR objective of upgrading to the latest OkHttp release.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 75904c3e-277b-4054-afff-f1ea1ee7be4b

📥 Commits

Reviewing files that changed from the base of the PR and between 3c311e7 and 97efe89.

📒 Files selected for processing (2)
  • app/build.gradle.kts
  • app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt

Comment thread app/build.gradle.kts
@hawkff hawkff changed the title build: update OkHttp to 5.4.0 stable build: update OkHttp to 5.3.0 stable Jun 15, 2026
@hawkff

hawkff commented Jun 15, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Branch updated since last review:

  1. OkHttp pinned to 5.3.0 (not 5.4.0): okhttp-android 5.4.0 requires minCompileSdk=36 but this project is compileSdk 35. Verified from AAR metadata that 5.3.0 is the latest stable supporting compileSdk 35. checkAarMetadata now passes.
  2. Replaced okhttp3.internal.closeQuietly with a local private Closeable.closeQuietly() extension (your prior finding).

Both debug and release builds pass on the builder.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== app/build.gradle.kts OkHttp dependency ==="
grep -n -i "okhttp\|compileSdk\|minSdk" app/build.gradle.kts

echo ""
echo "=== ConfigurationFragment.kt closeQuietly implementation ==="
grep -n "closeQuietly\|Closeable\|import okhttp3" app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt -A2 -B2

echo ""
echo "=== ConfigurationFragment.kt lines around new extension function ==="
# Find the new local closeQuietly definition
grep -n "fun Closeable\|closeQuietly\|private fun\|Exception\|ignore" app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt | head -30

echo ""
echo "=== Verify no remaining okhttp3.internal imports anywhere ==="
rg -n "okhttp3.internal" --type kotlin --type java

echo ""
echo "=== Full build.gradle.kts compileSdk / minSdk section ==="
grep -n "compileSdk\|minSdk\|targetSdk\|buildToolsVersion" app/build.gradle.kts

Length of output: 4385



@hawkff: Both changes verify cleanly against the branch.


Review: OkHttp bump + closeQuietly remediation

✅ OkHttp 5.3.0 — app/build.gradle.kts Line 68

implementation("com.squareup.okhttp3:okhttp:5.3.0")

Correct call. okhttp-android 5.4.0 raises minCompileSdk to 36 in its AAR metadata, so 5.3.0 is the right ceiling for compileSdk 35. All public APIs reviewed previously (OkHttpClient, Request.Builder, Credentials.basic, MediaType.toMediaType, RequestBody.toRequestBody, HttpUrl) are identical across 5.3.x and 5.4.x.


okhttp3.internal.closeQuietlyConfigurationFragment.kt

Import (Line 119): java.io.Closeable — stdlib only, no OkHttp internal. ✅

Extension (Lines 2056–2062):

/**
 * Closes this resource, ignoring any exception. Replacement for OkHttp's internal
 * `closeQuietly()` extension so we don't depend on an unstable `okhttp3.internal` API.
 */
private fun Closeable.closeQuietly() {
    try {
        close()

Three points worth noting:

  • Scoped private — won't leak into the module's API surface. ✅
  • Inline comment captures the why, which is exactly the right level of documentation for a one-liner. ✅
  • rg confirms zero remaining okhttp3.internal imports across the entire codebase (the single grep hit is inside the Javadoc comment text, not an actual import). ✅

Summary

Both actionable findings from the prior review are fully addressed. The PR is clean: no unstable internal APIs, correct version ceiling for the project's compileSdk, and passing R8/debug builds. No further changes needed on this scope.


✏️ Learnings added
Learnt from: hawkff
URL: https://github.com/hawkff/NekoBoxForAndroid/pull/9

Timestamp: 2026-06-15T19:03:27.347Z
Learning: In NekoBoxForAndroid, `okhttp3.internal.closeQuietly` usage in `app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt` has been remediated (PR `#9`). It was replaced with a local `private fun Closeable.closeQuietly()` extension at the bottom of the file that simply calls `close()` in a try/catch, with no dependency on OkHttp internals.

Learnt from: hawkff
URL: https://github.com/hawkff/NekoBoxForAndroid/pull/9

Timestamp: 2026-06-15T19:03:27.347Z
Learning: In NekoBoxForAndroid, `okhttp-android` 5.4.0 requires `minCompileSdk=36` (enforced via AAR metadata / checkAarMetadata). The project uses `compileSdk=35`, so `com.squareup.okhttp3:okhttp:5.3.0` is the correct latest stable version for this project until the compile SDK is raised to 36.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@hawkff hawkff merged commit 27af635 into main Jun 15, 2026
3 checks passed
@hawkff hawkff deleted the maintenance/update-okhttp branch June 15, 2026 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant