diff --git a/CHANGELOG.md b/CHANGELOG.md index 62cf35c..1dd84b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Changed + +- skip the Coder TLS alternate hostname when fetching IDE metadata from JetBrains + ## 0.9.0 - 2026-05-14 ### Added diff --git a/src/main/kotlin/com/coder/toolbox/feed/IdeFeedManager.kt b/src/main/kotlin/com/coder/toolbox/feed/IdeFeedManager.kt index 985c11c..6cfcc80 100644 --- a/src/main/kotlin/com/coder/toolbox/feed/IdeFeedManager.kt +++ b/src/main/kotlin/com/coder/toolbox/feed/IdeFeedManager.kt @@ -1,11 +1,14 @@ package com.coder.toolbox.feed import com.coder.toolbox.CoderToolboxContext -import com.coder.toolbox.sdk.CoderHttpClientBuilder +import com.coder.toolbox.plugin.PluginManager +import com.coder.toolbox.sdk.interceptors.Interceptors +import com.coder.toolbox.sdk.proxy.applyProxySettings import com.squareup.moshi.Moshi import com.squareup.moshi.Types import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory import java.nio.file.Path @@ -40,7 +43,12 @@ class IdeFeedManager( private val feedService: JetBrainsFeedService by lazy { if (feedService != null) return@lazy feedService - val okHttpClient = CoderHttpClientBuilder.default(context) + val okHttpClient = OkHttpClient.Builder() + .applyProxySettings(context) + .addInterceptor(Interceptors.userAgent(PluginManager.pluginInfo.version)) + .addInterceptor(Interceptors.logging(context)) + .retryOnConnectionFailure(true) + .build() val retrofit = Retrofit.Builder() .baseUrl("https://data.services.jetbrains.com/") diff --git a/src/main/kotlin/com/coder/toolbox/sdk/CoderHttpClientBuilder.kt b/src/main/kotlin/com/coder/toolbox/sdk/CoderHttpClientBuilder.kt index 67d70c2..594587b 100644 --- a/src/main/kotlin/com/coder/toolbox/sdk/CoderHttpClientBuilder.kt +++ b/src/main/kotlin/com/coder/toolbox/sdk/CoderHttpClientBuilder.kt @@ -3,10 +3,9 @@ package com.coder.toolbox.sdk import com.coder.toolbox.CoderToolboxContext import com.coder.toolbox.plugin.PluginManager import com.coder.toolbox.sdk.interceptors.Interceptors +import com.coder.toolbox.sdk.proxy.applyProxySettings import com.coder.toolbox.util.CoderHostnameVerifier import com.coder.toolbox.util.ReloadableTlsContext -import com.jetbrains.toolbox.api.remoteDev.connection.ProxyAuth -import okhttp3.Credentials import okhttp3.Interceptor import okhttp3.OkHttpClient @@ -17,36 +16,13 @@ object CoderHttpClientBuilder { tlsContext: ReloadableTlsContext ): OkHttpClient { val builder = OkHttpClient.Builder() - - context.proxySettings.getProxy()?.let { proxy -> - context.logger.info("proxy: $proxy") - builder.proxy(proxy) - } ?: context.proxySettings.getProxySelector()?.let { proxySelector -> - context.logger.info("proxy selector: $proxySelector") - builder.proxySelector(proxySelector) - } - - // Note: This handles only HTTP/HTTPS proxy authentication. - // SOCKS5 proxy authentication is currently not supported due to limitations described in: - // https://youtrack.jetbrains.com/issue/TBX-14532/Missing-proxy-authentication-settings#focus=Comments-27-12265861.0-0 - builder.proxyAuthenticator { _, response -> - val proxyAuth = context.proxySettings.getProxyAuth() - if (proxyAuth == null || proxyAuth !is ProxyAuth.Basic) { - return@proxyAuthenticator null - } - val credentials = Credentials.basic(proxyAuth.username, proxyAuth.password) - response.request.newBuilder() - .header("Proxy-Authorization", credentials) - .build() - } - - builder.sslSocketFactory(tlsContext.sslSocketFactory, tlsContext.trustManager) + .applyProxySettings(context) + .sslSocketFactory(tlsContext.sslSocketFactory, tlsContext.trustManager) .hostnameVerifier(CoderHostnameVerifier(context.settingsStore.tls.altHostname)) .retryOnConnectionFailure(true) interceptors.forEach { interceptor -> builder.addInterceptor(interceptor) - } return builder.build() } @@ -62,4 +38,4 @@ object CoderHttpClientBuilder { ReloadableTlsContext(context.settingsStore.readOnly().tls) ) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/coder/toolbox/sdk/proxy/Proxies.kt b/src/main/kotlin/com/coder/toolbox/sdk/proxy/Proxies.kt new file mode 100644 index 0000000..90476ab --- /dev/null +++ b/src/main/kotlin/com/coder/toolbox/sdk/proxy/Proxies.kt @@ -0,0 +1,36 @@ +package com.coder.toolbox.sdk.proxy + +import com.coder.toolbox.CoderToolboxContext +import com.jetbrains.toolbox.api.remoteDev.connection.ProxyAuth +import okhttp3.Credentials +import okhttp3.OkHttpClient + +/** + * Applies the user's Toolbox proxy and proxy authentication settings to this builder. + * + * Note: This handles only HTTP/HTTPS proxy authentication. SOCKS5 proxy authentication is currently + * not supported due to limitations described in: + * https://youtrack.jetbrains.com/issue/TBX-14532/Missing-proxy-authentication-settings#focus=Comments-27-12265861.0-0 + */ +fun OkHttpClient.Builder.applyProxySettings(context: CoderToolboxContext): OkHttpClient.Builder { + context.proxySettings.getProxy()?.let { proxy -> + context.logger.info("proxy: $proxy") + proxy(proxy) + } ?: context.proxySettings.getProxySelector()?.let { proxySelector -> + context.logger.info("proxy selector: $proxySelector") + proxySelector(proxySelector) + } + + proxyAuthenticator { _, response -> + val proxyAuth = context.proxySettings.getProxyAuth() + if (proxyAuth == null || proxyAuth !is ProxyAuth.Basic) { + return@proxyAuthenticator null + } + val credentials = Credentials.basic(proxyAuth.username, proxyAuth.password) + response.request.newBuilder() + .header("Proxy-Authorization", credentials) + .build() + } + + return this +}