Skip to content

Comments

feat(network): Implement dynamic proxy support for Ktor client#262

Open
rainxchzed wants to merge 1 commit intomainfrom
custom-proxy-impl
Open

feat(network): Implement dynamic proxy support for Ktor client#262
rainxchzed wants to merge 1 commit intomainfrom
custom-proxy-impl

Conversation

@rainxchzed
Copy link
Owner

@rainxchzed rainxchzed commented Feb 24, 2026

This commit introduces support for HTTP and SOCKS proxies in the application's network layer. It allows the HttpClient to be dynamically reconfigured at runtime when proxy settings change.

The implementation creates a GitHubClientProvider that observes a ProxyConfig flow. When the proxy configuration is updated, it closes the existing Ktor HttpClient and creates a new one with the updated proxy settings. Platform-specific Ktor engines are used for proxy implementation: OkHttp on Android and CIO on JVM (desktop).

  • feat(network): Added ProxyConfig data class to model proxy settings.
  • feat(network): Introduced ProxyManager to hold and update the global proxy configuration.
  • feat(network): Implemented GitHubClientProvider to manage the lifecycle of HttpClient and recreate it when proxy settings change.
  • feat(network): Added platform-specific HttpClientFactory implementations for Android (OkHttp) and JVM (CIO) to handle proxy configuration.
  • chore(deps): Added Ktor client engine dependencies: ktor-client-okhttp for Android and ktor-client-cio for JVM.

Summary by CodeRabbit

Release Notes

  • New Features
    • Added HTTP and SOCKS proxy configuration support with optional authentication credentials
    • Proxy settings can be dynamically updated at runtime without restarting the application
    • Enhanced HTTP client architecture for improved network request handling

This commit introduces support for HTTP and SOCKS proxies in the application's network layer. It allows the `HttpClient` to be dynamically reconfigured at runtime when proxy settings change.

The implementation creates a `GitHubClientProvider` that observes a `ProxyConfig` flow. When the proxy configuration is updated, it closes the existing Ktor `HttpClient` and creates a new one with the updated proxy settings. Platform-specific Ktor engines are used for proxy implementation: `OkHttp` on Android and `CIO` on JVM (desktop).

- **feat(network)**: Added `ProxyConfig` data class to model proxy settings.
- **feat(network)**: Introduced `ProxyManager` to hold and update the global proxy configuration.
- **feat(network)**: Implemented `GitHubClientProvider` to manage the lifecycle of `HttpClient` and recreate it when proxy settings change.
- **feat(network)**: Added platform-specific `HttpClientFactory` implementations for Android (`OkHttp`) and JVM (`CIO`) to handle proxy configuration.
- **chore(deps)**: Added Ktor client engine dependencies: `ktor-client-okhttp` for Android and `ktor-client-cio` for JVM.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

Walkthrough

The pull request introduces proxy configuration support across the codebase. A new ProxyConfig data model and ProxyManager singleton enable runtime proxy management. The HTTP client factory is restructured to use an expect/actual pattern with platform-specific implementations for Android (OkHttp) and JVM (CIO). A new GitHubClientProvider class manages cached HTTP client instances and reactively rebuilds them when proxy configuration changes. Dependency injection wiring and build configuration are updated accordingly.

Changes

Cohort / File(s) Summary
Proxy Configuration Model
core/domain/src/commonMain/kotlin/.../ProxyConfig.kt
New data class representing HTTP/SOCKS proxy settings with optional credentials and nested ProxyType enum.
Proxy State Management
core/data/src/commonMain/kotlin/.../ProxyManager.kt
New singleton object managing proxy state via a MutableStateFlow with a public API for updating and reading current proxy configuration.
HTTP Client Factory
core/data/src/commonMain/kotlin/.../HttpClientFactory.kt, core/data/src/androidMain/kotlin/.../HttpClientFactory.android.kt, core/data/src/jvmMain/kotlin/.../HttpClientFactory.jvm.kt
Introduced expect/actual pattern for platform-specific HTTP client creation. Common factory now accepts optional proxyConfig parameter; Android implementation uses OkHttp engine with proxy-authentication support; JVM implementation uses CIO engine with HTTP/SOCKS proxy routing.
GitHub Client Provider
core/data/src/commonMain/kotlin/.../GitHubClientProvider.kt
New class managing cached HttpClient lifecycle with reactive proxy configuration updates. Rebuilds client and closes previous instance when proxy config changes via Flow subscription.
Dependency Injection Wiring
core/data/src/commonMain/kotlin/.../SharedModule.kt
Updated module to instantiate GitHubClientProvider as singleton with tokenStore, rateLimitRepository, and ProxyManager.currentProxyConfig; updated createGitHubHttpClient invocation to include rateLimitRepository parameter.
Build Configuration
core/data/build.gradle.kts, gradle/libs.versions.toml
Added ktor-client-okhttp dependency for androidMain and ktor-client-cio for jvmMain; added ktor-client-cio library version entry in libs.versions.toml.

Sequence Diagram

sequenceDiagram
    participant PM as ProxyManager
    participant GCP as GitHubClientProvider
    participant HCF as HttpClientFactory
    participant Android as Android<br/>HttpClient
    participant JVM as JVM<br/>HttpClient

    actor User

    User->>PM: setProxyConfig(newConfig)
    activate PM
    PM->>PM: _proxyConfig.update()
    PM-->>GCP: emits via currentProxyConfig flow
    deactivate PM

    activate GCP
    GCP->>GCP: closes previous HttpClient
    GCP->>HCF: createGitHubHttpClient(tokenStore, rateLimitRepository, newConfig)
    
    alt Android Platform
        activate Android
        HCF->>Android: createPlatformHttpClient(newConfig)
        Android->>Android: configure OkHttp engine with proxy
        Android-->>HCF: HttpClient instance
        deactivate Android
    else JVM Platform
        activate JVM
        HCF->>JVM: createPlatformHttpClient(newConfig)
        JVM->>JVM: configure CIO engine with proxy
        JVM-->>HCF: HttpClient instance
        deactivate JVM
    end

    HCF->>HCF: apply RateLimitInterceptor<br/>ContentNegotiation, Timeout, Retry
    HCF-->>GCP: configured HttpClient
    GCP->>GCP: store in _client flow
    GCP-->>User: new client ready via client flow
    deactivate GCP
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 Through networks vast, I hop along,
Where proxies guide my path so strong,
When configs shift, the client's born anew,
Reactive flows ensure all paths ring true! 🌐

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: implementing dynamic proxy support for the Ktor client, which is the core feature across all modifications in this changeset.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch custom-proxy-impl

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/data/src/commonMain/kotlin/zed/rainxch/core/data/di/SharedModule.kt (1)

98-110: ⚠️ Potential issue | 🟠 Major

Dynamic proxy updates are bypassed by the HttpClient singleton.

GitHubClientProvider is registered with proxy awareness, but the HttpClient singleton binding calls createGitHubHttpClient(...) without passing proxyConfig, defaulting to null. All repositories injecting HttpClient directly—including InstalledAppsRepositoryImpl, StarredRepositoryImpl, SearchRepositoryImpl, HomeRepositoryImpl, DetailsRepositoryImpl, and others—receive the static client and never observe proxy changes. Source HttpClient from GitHubClientProvider (via its currentClient() or client Flow) or remove the direct singleton binding so all consumers get the proxy-aware client.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/data/src/commonMain/kotlin/zed/rainxch/core/data/di/SharedModule.kt`
around lines 98 - 110, The HttpClient singleton is created without proxyConfig
so it never observes dynamic proxy changes; instead, make consumers receive the
proxy-aware client from GitHubClientProvider by removing the direct
single<HttpClient> binding and returning the provider's client (e.g., use
GitHubClientProvider.currentClient() or its client Flow/ currentClient()
accessor) so all repositories (InstalledAppsRepositoryImpl,
StarredRepositoryImpl, SearchRepositoryImpl, HomeRepositoryImpl,
DetailsRepositoryImpl, etc.) inject the proxy-aware HttpClient; alternatively,
if a single HttpClient instance must be provided, construct it via
GitHubClientProvider (calling its client-producing API) so
ProxyManager.currentProxyConfig is honored.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@core/data/src/commonMain/kotlin/zed/rainxch/core/data/network/GitHubClientProvider.kt`:
- Around line 24-41: The current stateIn initialValue creates a leaked
HttpClient and _client stays null, and closing the old client before creating
the new one can drop the last working client; fix by eagerly creating the
initial client once (call createGitHubHttpClient(tokenStore,
rateLimitRepository)), assign it to _client.value before building the Flow, then
change the map handler to first create the replacement client (using
createGitHubHttpClient with proxyConfig), only after successful creation set
_client.value = newClient and then close the previous client (old =
_client.value before assignment), and make stateIn use the cached _client.value
(or the already-created initial client) as its initialValue so no client is
leaked; reference symbols: client (Flow<HttpClient>), proxyConfigFlow, _client,
createGitHubHttpClient, stateIn, initialValue.
- Around line 43-48: currentClient() can create a client without the latest
proxy settings because it uses _client.value ?: createGitHubHttpClient(...) —
fix by ensuring createGitHubHttpClient is called with the current proxy
configuration (read proxyConfigFlow.value) when creating and assigning _client
in currentClient(), or alternatively expose client as a StateFlow and return
client.value so callers always see updates; update currentClient(), _client
assignment, and the createGitHubHttpClient invocation to consume
proxyConfigFlow.value (or switch callers to the new client StateFlow).

In
`@core/data/src/jvmMain/kotlin/zed/rainxch/core/data/network/HttpClientFactory.jvm.kt`:
- Around line 9-20: The JVM CIO proxy setup in createPlatformHttpClient ignores
ProxyConfig.username/password; fix by detecting when proxyConfig?.username or
.password is present and install a process-wide java.net.Authenticator via
Authenticator.setDefault that returns a PasswordAuthentication using those
credentials for requests to the proxy host/port; keep the existing
ProxyBuilder.http(...) and ProxyBuilder.socks(...) usage for the engine, and
ensure the Authenticator references proxyConfig.host and proxyConfig.port so
authenticated HTTP/SOCKS proxies work across the JVM process (or alternatively,
if you prefer not to modify global state, throw/return an error when credentials
are provided to ProxyConfig to document the limitation).

---

Outside diff comments:
In `@core/data/src/commonMain/kotlin/zed/rainxch/core/data/di/SharedModule.kt`:
- Around line 98-110: The HttpClient singleton is created without proxyConfig so
it never observes dynamic proxy changes; instead, make consumers receive the
proxy-aware client from GitHubClientProvider by removing the direct
single<HttpClient> binding and returning the provider's client (e.g., use
GitHubClientProvider.currentClient() or its client Flow/ currentClient()
accessor) so all repositories (InstalledAppsRepositoryImpl,
StarredRepositoryImpl, SearchRepositoryImpl, HomeRepositoryImpl,
DetailsRepositoryImpl, etc.) inject the proxy-aware HttpClient; alternatively,
if a single HttpClient instance must be provided, construct it via
GitHubClientProvider (calling its client-producing API) so
ProxyManager.currentProxyConfig is honored.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39e788f and 110b854.

📒 Files selected for processing (9)
  • core/data/build.gradle.kts
  • core/data/src/androidMain/kotlin/zed/rainxch/core/data/network/HttpClientFactory.android.kt
  • core/data/src/commonMain/kotlin/zed/rainxch/core/data/di/SharedModule.kt
  • core/data/src/commonMain/kotlin/zed/rainxch/core/data/network/GitHubClientProvider.kt
  • core/data/src/commonMain/kotlin/zed/rainxch/core/data/network/HttpClientFactory.kt
  • core/data/src/commonMain/kotlin/zed/rainxch/core/data/network/ProxyManager.kt
  • core/data/src/jvmMain/kotlin/zed/rainxch/core/data/network/HttpClientFactory.jvm.kt
  • core/domain/src/commonMain/kotlin/zed/rainxch/core/domain/model/ProxyConfig.kt
  • gradle/libs.versions.toml

Comment on lines +24 to +41
val client: Flow<HttpClient> = proxyConfigFlow
.distinctUntilChanged()
.map { proxyConfig ->
_client.value?.close()

val newClient = createGitHubHttpClient(
tokenStore = tokenStore,
rateLimitRepository = rateLimitRepository,
proxyConfig = proxyConfig
)
_client.value = newClient
newClient
}
.stateIn(
scope = CoroutineScope(SupervisorJob() + Dispatchers.Default),
started = SharingStarted.Lazily,
initialValue = createGitHubHttpClient(tokenStore, rateLimitRepository)
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Prevent leaked initial HttpClient and keep a single cached instance

The stateIn initialValue creates a client that never gets stored in _client, so _client stays null and you can end up with two live clients (and the initial one is never closed). Also, closing before successfully creating the replacement can drop the last working client if construction fails.

🛠️ Proposed fix
     val client: Flow<HttpClient> = proxyConfigFlow
         .distinctUntilChanged()
         .map { proxyConfig ->
-            _client.value?.close()
-
-            val newClient = createGitHubHttpClient(
+            val oldClient = _client.value
+            val newClient = createGitHubHttpClient(
                 tokenStore = tokenStore,
                 rateLimitRepository = rateLimitRepository,
                 proxyConfig = proxyConfig
             )
             _client.value = newClient
+            oldClient?.close()
             newClient
         }
         .stateIn(
             scope = CoroutineScope(SupervisorJob() + Dispatchers.Default),
             started = SharingStarted.Lazily,
-            initialValue = createGitHubHttpClient(tokenStore, rateLimitRepository)
+            initialValue = createGitHubHttpClient(tokenStore, rateLimitRepository)
+                .also { _client.value = it }
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/data/src/commonMain/kotlin/zed/rainxch/core/data/network/GitHubClientProvider.kt`
around lines 24 - 41, The current stateIn initialValue creates a leaked
HttpClient and _client stays null, and closing the old client before creating
the new one can drop the last working client; fix by eagerly creating the
initial client once (call createGitHubHttpClient(tokenStore,
rateLimitRepository)), assign it to _client.value before building the Flow, then
change the map handler to first create the replacement client (using
createGitHubHttpClient with proxyConfig), only after successful creation set
_client.value = newClient and then close the previous client (old =
_client.value before assignment), and make stateIn use the cached _client.value
(or the already-created initial client) as its initialValue so no client is
leaked; reference symbols: client (Flow<HttpClient>), proxyConfigFlow, _client,
createGitHubHttpClient, stateIn, initialValue.

Comment on lines +43 to +48
fun currentClient(): HttpClient {
return _client.value
?: createGitHubHttpClient(tokenStore, rateLimitRepository).also {
_client.value = it
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

currentClient() can bypass active proxy settings

Because client is lazily started, _client can remain null even when proxy settings are already set; currentClient() then creates a no‑proxy client and proxy updates never apply for callers that only use currentClient().

🛠️ Possible fix (use latest proxy config for eager creation)
     fun currentClient(): HttpClient {
         return _client.value
-            ?: createGitHubHttpClient(tokenStore, rateLimitRepository).also {
-                _client.value = it
-            }
+            ?: createGitHubHttpClient(
+                tokenStore = tokenStore,
+                rateLimitRepository = rateLimitRepository,
+                proxyConfig = proxyConfigFlow.value
+            ).also { _client.value = it }
     }

Additional change needed outside this range (to make proxyConfigFlow.value available):

-    proxyConfigFlow: Flow<ProxyConfig?>
+    private val proxyConfigFlow: StateFlow<ProxyConfig?>

(Alternatively, expose client as a StateFlow and return client.value.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/data/src/commonMain/kotlin/zed/rainxch/core/data/network/GitHubClientProvider.kt`
around lines 43 - 48, currentClient() can create a client without the latest
proxy settings because it uses _client.value ?: createGitHubHttpClient(...) —
fix by ensuring createGitHubHttpClient is called with the current proxy
configuration (read proxyConfigFlow.value) when creating and assigning _client
in currentClient(), or alternatively expose client as a StateFlow and return
client.value so callers always see updates; update currentClient(), _client
assignment, and the createGitHubHttpClient invocation to consume
proxyConfigFlow.value (or switch callers to the new client StateFlow).

Comment on lines +9 to +20
actual fun createPlatformHttpClient(proxyConfig: ProxyConfig?): HttpClient {
return HttpClient(CIO) {
engine {
proxy = proxyConfig?.let { config ->
when (config.type) {
ProxyConfig.ProxyType.HTTP -> ProxyBuilder.http(
Url("http://${config.host}:${config.port}")
)
ProxyConfig.ProxyType.SOCKS -> ProxyBuilder.socks(
config.host, config.port
)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find ProxyConfig definition
fd -t f "ProxyConfig" --extension kt

Repository: rainxchzed/Github-Store

Length of output: 145


🏁 Script executed:

# Examine the full HttpClientFactory.jvm.kt file
find . -path "*core/data*" -name "HttpClientFactory.jvm.kt" -type f

Repository: rainxchzed/Github-Store

Length of output: 152


🏁 Script executed:

# Search for ProxyConfig class definition
rg -t kt "class ProxyConfig|data class ProxyConfig" -A 10

Repository: rainxchzed/Github-Store

Length of output: 93


🌐 Web query:

Ktor 3.2.3 CIO ProxyBuilder userinfo credentials support Url

💡 Result:

In Ktor 3.2.3, ProxyBuilder.http(url: Url) does not support proxy credentials via URL userinfo (for example http://user:pass@proxy:8080). On JVM it builds a java.net.Proxy using only url.host and url.port, so url.user / url.password are ignored. (raw.githubusercontent.com)

Relevant docs/source:

API docs (3.2.x): https://api.ktor.io/3.2.x/ktor-client-core/io.ktor.client.engine/-proxy-builder/index.html
JVM implementation (3.2.3): https://raw.githubusercontent.com/ktorio/ktor/3.2.3/ktor-client/ktor-client-core/jvm/src/io/ktor/client/engine/ProxyConfigJvm.kt
``` ([api.ktor.io](https://api.ktor.io/3.2.x/ktor-client-core/io.ktor.client.engine/-proxy-builder/index.html))

Citations:

- 1: https://raw.githubusercontent.com/ktorio/ktor/3.2.3/ktor-client/ktor-client-core/jvm/src/io/ktor/client/engine/ProxyConfigJvm.kt
- 2: https://api.ktor.io/3.2.x/ktor-client-core/io.ktor.client.engine/-proxy-builder/index.html

---

🏁 Script executed:

```shell
cat -n "core/domain/src/commonMain/kotlin/zed/rainxch/core/domain/model/ProxyConfig.kt"

Repository: rainxchzed/Github-Store

Length of output: 387


🏁 Script executed:

cat -n "./core/data/src/jvmMain/kotlin/zed/rainxch/core/data/network/HttpClientFactory.jvm.kt"

Repository: rainxchzed/Github-Store

Length of output: 1019


🏁 Script executed:

# Search for all usages of ProxyConfig to understand how credentials are handled elsewhere
rg -t kotlin "ProxyConfig" -B 2 -A 5

Repository: rainxchzed/Github-Store

Length of output: 11474


🏁 Script executed:

cat -n "core/data/src/androidMain/kotlin/zed/rainxch/core/data/network/HttpClientFactory.android.kt"

Repository: rainxchzed/Github-Store

Length of output: 1718


🏁 Script executed:

# Check if ProxyBuilder.socks supports credentials
web_search Ktor 3.2.3 ProxyBuilder.socks credentials SOCKS5 authentication

Repository: rainxchzed/Github-Store

Length of output: 117


🌐 Web query:

Ktor 3.2.3 ProxyBuilder.socks credentials SOCKS5 authentication

💡 Result:

In Ktor 3.2.3, ProxyBuilder.socks(host, port) does not accept credentials—it only builds a SOCKS proxy from host+port. In JVM, it’s literally a java.net.Proxy(Proxy.Type.SOCKS, InetSocketAddress(host, port)), so SOCKS5 username/password auth (if your proxy requires it) must be provided via the JVM’s java.net.Authenticator (global). [1] [2]

JVM example (works with engines that use java.net.Proxy, e.g. OkHttp)

import io.ktor.client.*
import io.ktor.client.engine.okhttp.*
import io.ktor.client.engine.*
import java.net.Authenticator
import java.net.PasswordAuthentication

val proxyHost = "proxy.example.com"
val proxyPort = 1080
val proxyUser = "user"
val proxyPass = "pass"

Authenticator.setDefault(object : Authenticator() {
    override fun getPasswordAuthentication(): PasswordAuthentication? =
        if (requestingHost.equals(proxyHost, ignoreCase = true))
            PasswordAuthentication(proxyUser, proxyPass.toCharArray())
        else null
})

val client = HttpClient(OkHttp) {
    engine {
        proxy = ProxyBuilder.socks(proxyHost, proxyPort)
    }
}

This pattern (set a Proxy(Type.SOCKS, …) + Authenticator) is the typical way to do SOCKS5 auth on JVM. [3]

Note: Authenticator.setDefault(...) is process-wide, not per-client/per-request. [3]

Sources:
[1] Ktor API: ProxyBuilder.socks(host, port) (no credentials) (api.ktor.io)
[2] Ktor 3.2.3 JVM implementation: SOCKS proxy is java.net.Proxy(Type.SOCKS, InetSocketAddress(...)) (raw.githubusercontent.com)
[3] Example using SOCKS Proxy + Authenticator (same approach) (git.inmo.dev)

Citations:


Proxy credentials are ignored on JVM with CIO engine.

ProxyConfig supports username and password, but the JVM CIO proxy setup does not use them. Unlike the Android implementation (which handles credentials via proxyAuthenticator), the JVM code silently ignores these fields. Authenticated HTTP/SOCKS proxies will fail.

Ktor's ProxyBuilder.http() and ProxyBuilder.socks() do not support per-request proxy credentials. To fix this, either:

  1. Document this as a known limitation and reject authenticated proxies with a clear error, or
  2. Use java.net.Authenticator.setDefault() (process-wide) to handle proxy auth (note: this affects the entire JVM process), or
  3. Consider switching to an HTTP engine with better proxy auth support.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/data/src/jvmMain/kotlin/zed/rainxch/core/data/network/HttpClientFactory.jvm.kt`
around lines 9 - 20, The JVM CIO proxy setup in createPlatformHttpClient ignores
ProxyConfig.username/password; fix by detecting when proxyConfig?.username or
.password is present and install a process-wide java.net.Authenticator via
Authenticator.setDefault that returns a PasswordAuthentication using those
credentials for requests to the proxy host/port; keep the existing
ProxyBuilder.http(...) and ProxyBuilder.socks(...) usage for the engine, and
ensure the Authenticator references proxyConfig.host and proxyConfig.port so
authenticated HTTP/SOCKS proxies work across the JVM process (or alternatively,
if you prefer not to modify global state, throw/return an error when credentials
are provided to ProxyConfig to document the limitation).

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