fix: 修复签名不匹配的根本原因,改用手动拼接 URL 替代 URLComponents,增加加载重试机制
CI / lint-and-build (push) Has been cancelled
CI / lint-and-build (push) Has been cancelled
This commit is contained in:
@@ -66,15 +66,12 @@ actor VODClient {
|
||||
params["Signature"] = signature
|
||||
|
||||
let host = endpoint()
|
||||
var components = URLComponents()
|
||||
components.scheme = "https"
|
||||
components.host = host
|
||||
components.path = "/"
|
||||
components.queryItems = params.sorted(by: { $0.key < $1.key }).map {
|
||||
URLQueryItem(name: $0.key, value: $0.value)
|
||||
}
|
||||
let query = params.sorted(by: { $0.key < $1.key })
|
||||
.map { "\(VODSignature.percentEncodePublic($0.key))=\(VODSignature.percentEncodePublic($0.value))" }
|
||||
.joined(separator: "&")
|
||||
let urlString = "https://\(host)/?\(query)"
|
||||
|
||||
guard let url = components.url else {
|
||||
guard let url = URL(string: urlString) else {
|
||||
throw VODClientError.invalidResponse
|
||||
}
|
||||
return url
|
||||
@@ -93,7 +90,17 @@ actor VODClient {
|
||||
}
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
do {
|
||||
return try decoder.decode(T.self, from: data)
|
||||
} catch {
|
||||
if action == "GetPlayInfo" {
|
||||
print("[VODClient] GetPlayInfo 解码失败: \(error)")
|
||||
if let raw = String(data: data, encoding: .utf8) {
|
||||
print("[VODClient] GetPlayInfo 原始响应: \(raw)")
|
||||
}
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
func searchMedia(
|
||||
|
||||
@@ -26,8 +26,6 @@ struct VODSignature {
|
||||
|
||||
let stringToSign = "\(method)&%2F&\(percentEncode(canonicalQuery))"
|
||||
|
||||
print("[VODSignature] stringToSign: \(stringToSign)")
|
||||
|
||||
guard let keyData = "\(accessKeySecret)&".data(using: .utf8) else {
|
||||
throw VODSignatureError.invalidKey
|
||||
}
|
||||
@@ -41,6 +39,10 @@ struct VODSignature {
|
||||
return signatureData.base64EncodedString()
|
||||
}
|
||||
|
||||
static func percentEncodePublic(_ value: String) -> String {
|
||||
percentEncode(value)
|
||||
}
|
||||
|
||||
private static func percentEncode(_ value: String) -> String {
|
||||
let allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~"
|
||||
var result = ""
|
||||
|
||||
@@ -243,7 +243,9 @@ struct VideoListView: View {
|
||||
private func refreshFromAPI() async {
|
||||
isLoading = true
|
||||
errorMessage = nil
|
||||
loadingStatus = "正在加载视频列表..."
|
||||
let maxRetries = 3
|
||||
for attempt in 1...maxRetries {
|
||||
loadingStatus = attempt == 1 ? "正在加载视频列表..." : "重试中... (第 \(attempt)/\(maxRetries) 次)"
|
||||
var collected: [VideoItem] = []
|
||||
var page = 1
|
||||
let size = 100
|
||||
@@ -262,12 +264,21 @@ struct VideoListView: View {
|
||||
break
|
||||
}
|
||||
page += 1
|
||||
try? await Task.sleep(for: .milliseconds(200))
|
||||
}
|
||||
allVideos = collected
|
||||
applyFilter()
|
||||
loadingStatus = ""
|
||||
isLoading = false
|
||||
return
|
||||
} catch {
|
||||
errorMessage = "加载失败:\(error.localizedDescription)"
|
||||
if attempt < maxRetries {
|
||||
let delay = UInt64(attempt) * 1_000_000_000
|
||||
try? await Task.sleep(nanoseconds: delay)
|
||||
} else {
|
||||
errorMessage = "加载失败(已重试 \(maxRetries) 次):\(error.localizedDescription)"
|
||||
}
|
||||
}
|
||||
}
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user