beta.22: manual cookie join, anthropic-client-platform header, ephemeral session, expose usage 403 body

This commit is contained in:
superdooper86
2026-05-11 12:52:46 +02:00
parent 2cfd7d56a1
commit 4378463600
2 changed files with 10 additions and 7 deletions
+2 -2
View File
@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.2.1-beta.21</string> <string>1.2.1-beta.22</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>69</string> <string>70</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>13.0</string> <string>13.0</string>
<key>LSUIElement</key> <key>LSUIElement</key>
+8 -5
View File
@@ -87,9 +87,10 @@ class UsageViewModel: ObservableObject {
var req = URLRequest(url: URL(string: "https://claude.ai\(path)")!) var req = URLRequest(url: URL(string: "https://claude.ai\(path)")!)
req.httpShouldHandleCookies = false req.httpShouldHandleCookies = false
if let cookieHeader = HTTPCookie.requestHeaderFields(with: claudeCookies)["Cookie"] { // Build cookie header manually (same format as Windows HttpClient) to avoid
req.setValue(cookieHeader, forHTTPHeaderField: "Cookie") // any encoding differences from HTTPCookie.requestHeaderFields(with:)
} let cookieHeader = claudeCookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ")
req.setValue(cookieHeader, forHTTPHeaderField: "Cookie")
req.setValue("application/json", forHTTPHeaderField: "Accept") req.setValue("application/json", forHTTPHeaderField: "Accept")
req.setValue("https://claude.ai", forHTTPHeaderField: "Origin") req.setValue("https://claude.ai", forHTTPHeaderField: "Origin")
req.setValue("https://claude.ai/", forHTTPHeaderField: "Referer") req.setValue("https://claude.ai/", forHTTPHeaderField: "Referer")
@@ -104,9 +105,11 @@ class UsageViewModel: ObservableObject {
forHTTPHeaderField: "sec-ch-ua") forHTTPHeaderField: "sec-ch-ua")
req.setValue("?0", forHTTPHeaderField: "sec-ch-ua-mobile") req.setValue("?0", forHTTPHeaderField: "sec-ch-ua-mobile")
req.setValue("\"macOS\"", forHTTPHeaderField: "sec-ch-ua-platform") req.setValue("\"macOS\"", forHTTPHeaderField: "sec-ch-ua-platform")
req.setValue("web", forHTTPHeaderField: "anthropic-client-platform")
let session = URLSession(configuration: .ephemeral)
do { do {
let (data, response) = try await URLSession.shared.data(for: req) let (data, response) = try await session.data(for: req)
guard let http = response as? HTTPURLResponse else { throw AppError.networkError } guard let http = response as? HTTPURLResponse else { throw AppError.networkError }
let body = String(data: data, encoding: .utf8) ?? "" let body = String(data: data, encoding: .utf8) ?? ""
diagLastStatus = http.statusCode diagLastStatus = http.statusCode
@@ -257,7 +260,7 @@ class UsageViewModel: ObservableObject {
private func fetchUsage(orgId: String) async throws -> UsageResponse { private func fetchUsage(orgId: String) async throws -> UsageResponse {
let (status, body) = try await urlFetch("/api/organizations/\(orgId)/usage") let (status, body) = try await urlFetch("/api/organizations/\(orgId)/usage")
if status == 401 || status == 403 { throw AppError.notAuthenticated } if status == 401 || status == 403 { throw AppError.detail("usage \(status): \(body.prefix(200))") }
guard status == 200 else { throw AppError.networkError } guard status == 200 else { throw AppError.networkError }
guard let data = body.data(using: .utf8) else { throw AppError.networkError } guard let data = body.data(using: .utf8) else { throw AppError.networkError }
return try JSONDecoder().decode(UsageResponse.self, from: data) return try JSONDecoder().decode(UsageResponse.self, from: data)