ani icon indicating copy to clipboard operation
ani copied to clipboard

自定义代理设置,Authorization 无效

Open WoLeo-Z opened this issue 10 months ago • 1 comments

问题描述

(我相信其实也没多少人用这个功能,所以 P2)

附一个 Patch: Move toClientProxyConfig and toHeader and modify ProxyAuthorization.toHeader()

移动了两个函数到正确位置。

ProxyAuthorization.toHeader() 不应该是 Basic $username:$password

Subject: [PATCH] Move `toClientProxyConfig` and `toHeader` and modify `ProxyAuthorization.toHeader()`
---
Index: app/shared/app-data/src/commonMain/kotlin/data/models/preference/ProxyConfig.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/app/shared/app-data/src/commonMain/kotlin/data/models/preference/ProxyConfig.kt b/app/shared/app-data/src/commonMain/kotlin/data/models/preference/ProxyConfig.kt
--- a/app/shared/app-data/src/commonMain/kotlin/data/models/preference/ProxyConfig.kt	(revision 18f6bfb0139a118ae08a76292671c24959a57b2d)
+++ b/app/shared/app-data/src/commonMain/kotlin/data/models/preference/ProxyConfig.kt	(revision c4a26dd127f645d798d8c6b0faff92a91c356ce5)
@@ -9,9 +9,13 @@
 
 package me.him188.ani.app.data.models.preference
 
+import io.ktor.util.encodeBase64
+import io.ktor.utils.io.charsets.Charsets
+import io.ktor.utils.io.core.toByteArray
 import kotlinx.serialization.SerialName
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.Transient
+import me.him188.ani.utils.ktor.ClientProxyConfig
 import me.him188.ani.utils.platform.annotations.SerializationOnly
 
 /**
@@ -83,10 +87,21 @@
     companion object {
         val Default = ProxyConfig()
     }
+
+    fun toClientProxyConfig(): ClientProxyConfig = ClientProxyConfig(
+        url = url,
+        authorization = authorization?.toHeader(),
+    )
 }
 
 @Serializable
 data class ProxyAuthorization(
     val username: String,
     val password: String,
-)
+) {
+    fun toHeader(): String {
+        val base64 = "${username}:${password}".toByteArray(Charsets.UTF_8).encodeBase64()
+
+        return "Basic $base64"
+    }
+}
Index: app/shared/app-data/src/commonMain/kotlin/domain/foundation/HttpClientProvider.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/app/shared/app-data/src/commonMain/kotlin/domain/foundation/HttpClientProvider.kt b/app/shared/app-data/src/commonMain/kotlin/domain/foundation/HttpClientProvider.kt
--- a/app/shared/app-data/src/commonMain/kotlin/domain/foundation/HttpClientProvider.kt	(revision 18f6bfb0139a118ae08a76292671c24959a57b2d)
+++ b/app/shared/app-data/src/commonMain/kotlin/domain/foundation/HttpClientProvider.kt	(revision c4a26dd127f645d798d8c6b0faff92a91c356ce5)
@@ -27,7 +27,6 @@
 import kotlinx.coroutines.job
 import kotlinx.coroutines.launch
 import me.him188.ani.app.data.models.preference.ProxyConfig
-import me.him188.ani.app.domain.media.fetch.toClientProxyConfig
 import me.him188.ani.app.domain.settings.ProxyProvider
 import me.him188.ani.utils.coroutines.childScope
 import me.him188.ani.utils.ktor.ScopedHttpClient
Index: app/shared/app-data/src/commonMain/kotlin/domain/media/fetch/MediaSourceManager.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/app/shared/app-data/src/commonMain/kotlin/domain/media/fetch/MediaSourceManager.kt b/app/shared/app-data/src/commonMain/kotlin/domain/media/fetch/MediaSourceManager.kt
--- a/app/shared/app-data/src/commonMain/kotlin/domain/media/fetch/MediaSourceManager.kt	(revision 18f6bfb0139a118ae08a76292671c24959a57b2d)
+++ b/app/shared/app-data/src/commonMain/kotlin/domain/media/fetch/MediaSourceManager.kt	(revision c4a26dd127f645d798d8c6b0faff92a91c356ce5)
@@ -23,7 +23,6 @@
 import kotlinx.coroutines.flow.shareIn
 import kotlinx.serialization.SerializationStrategy
 import kotlinx.serialization.json.JsonElement
-import me.him188.ani.app.data.models.preference.ProxyAuthorization
 import me.him188.ani.app.data.models.preference.ProxyConfig
 import me.him188.ani.app.data.repository.media.MediaSourceInstanceRepository
 import me.him188.ani.app.data.repository.media.MikanIndexCacheRepository
@@ -51,7 +50,6 @@
 import me.him188.ani.datasources.mikan.MikanCNMediaSource
 import me.him188.ani.datasources.mikan.MikanMediaSource
 import me.him188.ani.utils.coroutines.onReplacement
-import me.him188.ani.utils.ktor.ClientProxyConfig
 import me.him188.ani.utils.ktor.ScopedHttpClient
 import me.him188.ani.utils.logging.error
 import me.him188.ani.utils.logging.logger
@@ -333,10 +331,3 @@
         private val logger = logger<MediaSourceManager>()
     }
 }
-
-fun ProxyConfig.toClientProxyConfig() = ClientProxyConfig(
-    url = url,
-    authorization = authorization?.toHeader(),
-)
-
-fun ProxyAuthorization.toHeader(): String = "Basic ${"$username:$password"}"
Index: app/shared/app-data/src/commonMain/kotlin/domain/settings/ProxyProvider.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/app/shared/app-data/src/commonMain/kotlin/domain/settings/ProxyProvider.kt b/app/shared/app-data/src/commonMain/kotlin/domain/settings/ProxyProvider.kt
--- a/app/shared/app-data/src/commonMain/kotlin/domain/settings/ProxyProvider.kt	(revision 18f6bfb0139a118ae08a76292671c24959a57b2d)
+++ b/app/shared/app-data/src/commonMain/kotlin/domain/settings/ProxyProvider.kt	(revision c4a26dd127f645d798d8c6b0faff92a91c356ce5)
@@ -28,7 +28,6 @@
 import me.him188.ani.app.data.models.preference.ProxyConfig
 import me.him188.ani.app.data.models.preference.ProxyMode
 import me.him188.ani.app.data.repository.user.SettingsRepository
-import me.him188.ani.app.domain.media.fetch.toClientProxyConfig
 import me.him188.ani.app.platform.SystemProxyDetector
 import me.him188.ani.utils.ktor.setProxy
 import me.him188.ani.utils.logging.info

复现步骤

No response

Ani 版本号

991f59d9086f17f5c756d8b772261de1d668571a

操作系统

No response

应用日志

Image

图片上半部分是服务端日志。

2025-02-12 16:33:12,879 [ERROR] HttpClientProvider:   GET https://api.bgm.tv/v0/users/-/collections/302189 : IO_EXCEPTION in 10.663200ms
2025-02-12 16:33:12,888 [WARN ] HttpClientProvider:   GET https://s1.animeko.openani.org/v1/schedule/subjects?ids=302189 : CANCELLED in 34.094900ms
java.io.IOException: Failed to authenticate with proxy
	at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt:42)
	at io.ktor.client.engine.okhttp.OkHttpEngine.executeHttpRequest(OkHttpEngine.kt:103)
	at io.ktor.client.engine.okhttp.OkHttpEngine.execute(OkHttpEngine.kt:70)
	at io.ktor.client.engine.HttpClientEngine$executeWithinCallContext$2.invokeSuspend(HttpClientEngine.kt:99)
	at io.ktor.client.engine.HttpClientEngine$DefaultImpls.executeWithinCallContext(HttpClientEngine.kt:100)
	at io.ktor.client.engine.HttpClientEngine$install$1.invokeSuspend(HttpClientEngine.kt:70)
	at io.ktor.client.plugins.HttpSend$DefaultSender.execute(HttpSend.kt:138)
	at me.him188.ani.app.domain.foundation.ServerListFeatureHandler$applyToClient$1.invokeSuspend(ScopedHttpClientFeature.kt:211)
	at me.him188.ani.app.domain.foundation.UseBangumiTokenFeatureHandler$applyToClient$1.invokeSuspend(ScopedHttpClientFeature.kt:155)
	at me.him188.ani.utils.ktor.DefaultClientKt$registerLogging$1.invokeSuspend(DefaultClient.kt:86)
	at io.ktor.client.plugins.auth.Auth$Plugin$install$2.invokeSuspend(Auth.kt:67)
	at io.ktor.client.plugins.HttpTimeout$Plugin$install$1.invokeSuspend(HttpTimeout.kt:174)
	at io.ktor.client.plugins.HttpRequestRetry$intercept$1.invokeSuspend(HttpRequestRetry.kt:298)
	at io.ktor.client.plugins.HttpRedirect$Plugin$install$1.invokeSuspend(HttpRedirect.kt:64)
	at io.ktor.client.plugins.HttpCallValidator$Companion$install$3.invokeSuspend(HttpCallValidator.kt:151)
	at io.ktor.client.plugins.HttpSend$Plugin$install$1.invokeSuspend(HttpSend.kt:104)
	at io.ktor.client.plugins.HttpCallValidator$Companion$install$1.invokeSuspend(HttpCallValidator.kt:130)
	at io.ktor.client.plugins.HttpRequestLifecycle$Plugin$install$1.invokeSuspend(HttpRequestLifecycle.kt:38)
	at io.ktor.client.HttpClient.execute$ktor_client_core(HttpClient.kt:191)
	at io.ktor.client.statement.HttpStatement.executeUnsafe(HttpStatement.kt:108)
	at io.ktor.client.statement.HttpStatement.execute(HttpStatement.kt:47)
	at me.him188.ani.datasources.bangumi.apis.DefaultApi.getUserCollection$suspendImpl(DefaultApi.kt:1369)
	at me.him188.ani.app.data.network.RemoteBangumiSubjectService$subjectCollectionById$1$1.invokeSuspend(BangumiSubjectService.kt:424)
	at me.him188.ani.utils.ktor.ApiInvokerKt$ApiInvoker$1.invoke(ApiInvoker.kt:25)
	at me.him188.ani.app.data.network.RemoteBangumiSubjectService$subjectCollectionById$1.invokeSuspend(BangumiSubjectService.kt:424)
	at kotlinx.coroutines.flow.AbstractFlow.collect(Flow.kt:226)
	at kotlinx.coroutines.flow.internal.ChannelFlow$collectToFun$1.invokeSuspend(ChannelFlow.kt:56)
	at kotlinx.coroutines.flow.FlowKt__ReduceKt.first(Reduce.kt:179)
	at me.him188.ani.app.data.network.RemoteBangumiSubjectService.getSubjectCollection(BangumiSubjectService.kt:188)
	at me.him188.ani.app.data.repository.subject.SubjectCollectionRepositoryImpl$subjectCollectionFlow$1$1$subjectCollectionDeferred$1.invokeSuspend(SubjectCollectionRepository.kt:226)
	at me.him188.ani.app.data.repository.subject.SubjectCollectionRepositoryImpl$subjectCollectionFlow$1.invokeSuspend(SubjectCollectionRepository.kt:225)
	at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit(Transform.kt:50)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt.emitAllImpl$FlowKt__ChannelsKt(Channels.kt:33)
	at kotlinx.coroutines.flow.internal.ChannelFlow$collect$2.invokeSuspend(ChannelFlow.kt:119)
	at kotlinx.coroutines.flow.internal.CombineKt$combineInternal$2$1.invokeSuspend(Combine.kt:28)
	at kotlinx.coroutines.flow.FlowKt__ShareKt$launchSharingDeferred$1.invokeSuspend(Share.kt:336)
	at me.him188.ani.app.ui.subject.details.state.DefaultSubjectDetailsStateFactory$create$3.invokeSuspend(SubjectDetailsStateFactory.kt:192)
	at kotlinx.coroutines.flow.AbstractFlow.collect(Flow.kt:226)
	at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3.invokeSuspend(Merge.kt:23)
	at me.him188.ani.app.ui.subject.details.state.SubjectDetailsStateLoader$load$1.invokeSuspend(SubjectDetailsStateLoader.kt:53)
Caused by: java.io.IOException: Failed to authenticate with proxy
	at okhttp3.internal.connection.RealConnection.createTunnel(RealConnection.kt:476)
	at okhttp3.internal.connection.RealConnection.connectTunnel(RealConnection.kt:262)
	at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:201)
	at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
	at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
	at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
	at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)

看不出来什么,因为 Client 是之前创建好的

WoLeo-Z avatar Feb 12 '25 08:02 WoLeo-Z

应该大部分代理都是无账号密码的 (clash 局域网)

Him188 avatar Feb 12 '25 11:02 Him188