Parcourir la source

feat(network): 更新 API Base URL 并优化 TLS 错误与超时配置

bob.yuxinyang il y a 1 mois
Parent
commit
d67dd66dfc

+ 1 - 1
CelestiaTrace/Resources/Info.plist

@@ -5,7 +5,7 @@
 	<key>CFBundleDevelopmentRegion</key>
 	<string>$(DEVELOPMENT_LANGUAGE)</string>
 	<key>APIBaseURL</key>
-	<string>https://celestia-trace.ccdw.life/v1</string>
+	<string>https://api.ccdw.life/celestia-trace/v1</string>
 	<key>CFBundleDisplayName</key>
 	<string>星痕</string>
 	<key>CFBundleExecutable</key>

+ 26 - 4
CelestiaTrace/Services/Network/APIClient.swift

@@ -19,6 +19,7 @@ struct EmptyAPIData: Decodable { }
 enum APIError: LocalizedError {
     case invalidConfiguration
     case invalidResponse
+    case secureConnection
     case unauthorized
     case server(code: Int, message: String)
     case transport(String)
@@ -29,6 +30,7 @@ enum APIError: LocalizedError {
         switch self {
         case .invalidConfiguration: return "服务地址配置无效"
         case .invalidResponse: return "服务器返回了无效响应"
+        case .secureConnection: return "无法安全连接登录服务器,请检查服务器 HTTPS 证书配置"
         case .unauthorized: return "登录状态已失效,请重新登录"
         case .server(_, let message): return message
         case .transport(let message): return "网络连接失败:\(message)"
@@ -116,14 +118,16 @@ actor APIClient {
         tokenStore: TokenStore = .shared
     ) {
         let configured = baseURL ?? (Bundle.main.object(forInfoDictionaryKey: "APIBaseURL") as? String).flatMap(URL.init(string:))
-        self.baseURL = configured ?? URL(string: "https://celestia-trace.ccdw.life/v1")!
+        self.baseURL = configured ?? URL(string: "https://api.ccdw.life/celestia-trace/v1")!
         if let session {
             self.session = session
         } else {
             let configuration = URLSessionConfiguration.default
-            configuration.waitsForConnectivity = true
-            configuration.timeoutIntervalForRequest = 30
-            configuration.timeoutIntervalForResource = 300
+            // Authentication is user-initiated. Fail promptly when the device is
+            // offline or TLS negotiation fails instead of leaving the UI waiting.
+            configuration.waitsForConnectivity = false
+            configuration.timeoutIntervalForRequest = 15
+            configuration.timeoutIntervalForResource = 60
             self.session = URLSession(configuration: configuration)
         }
         self.tokenStore = tokenStore
@@ -213,6 +217,8 @@ actor APIClient {
         let response: URLResponse
         do {
             (data, response) = try await session.data(for: request)
+        } catch let error as URLError where Self.isSecureConnectionError(error.code) {
+            throw APIError.secureConnection
         } catch {
             throw APIError.transport(error.localizedDescription)
         }
@@ -368,4 +374,20 @@ actor APIClient {
         }
         return decoder
     }()
+
+    private static func isSecureConnectionError(_ code: URLError.Code) -> Bool {
+        switch code {
+        case .secureConnectionFailed,
+             .serverCertificateHasBadDate,
+             .serverCertificateUntrusted,
+             .serverCertificateHasUnknownRoot,
+             .serverCertificateNotYetValid,
+             .clientCertificateRejected,
+             .clientCertificateRequired,
+             .appTransportSecurityRequiresSecureConnection:
+            return true
+        default:
+            return false
+        }
+    }
 }