diff options
| author | Christian Cleberg <[email protected]> | 2026-07-16 01:29:06 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-07-16 01:29:06 -0500 |
| commit | 8e585a709d8979d493fef3ed4015db93687f48e8 (patch) | |
| tree | faebe598a4c6f7a5f3db92d465ed693aab594252 /Hutch/Networking/SRHTClient.swift | |
| parent | f100206cc6d6784563d8eb905c9feb15c58bcc1e (diff) | |
| parent | 21be03e6ca54c1a15607faab905b119eda9a548f (diff) | |
| download | hutch-8e585a709d8979d493fef3ed4015db93687f48e8.tar.gz hutch-8e585a709d8979d493fef3ed4015db93687f48e8.tar.bz2 hutch-8e585a709d8979d493fef3ed4015db93687f48e8.zip | |
Merge pull request #6 from zerolabsco/phase-3-api-features
Phase 3: API features
Diffstat (limited to 'Hutch/Networking/SRHTClient.swift')
| -rw-r--r-- | Hutch/Networking/SRHTClient.swift | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/Hutch/Networking/SRHTClient.swift b/Hutch/Networking/SRHTClient.swift index 94531f4..8aaa4aa 100644 --- a/Hutch/Networking/SRHTClient.swift +++ b/Hutch/Networking/SRHTClient.swift @@ -276,6 +276,43 @@ final class SRHTClient: Sendable { // MARK: - Plain-text fetch + /// Fetch the bytes at a URL using the same authorization header. + /// + /// sr.ht serves some resources from the API origin rather than the web one — + /// `Artifact.url` is `https://git.sr.ht/query/artifact/<checksum>/<filename>` + /// — and those return an auth error to anything without a bearer token. They + /// cannot be handed to a browser; they have to be fetched here. + func fetchData(url: URL) async throws -> Data { + guard let token = tokenLock.withLock({ $0 }), !token.isEmpty else { + throw SRHTError.unauthorized + } + guard Self.isTrustedAuthenticatedTextURL(url) else { + throw SRHTError.invalidAuthenticatedURL(url) + } + + var request = URLRequest(url: url) + request.setValue(Bundle.main.hutchUserAgent, forHTTPHeaderField: "User-Agent") + request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") + + let (data, response): (Data, URLResponse) + do { + (data, response) = try await session.data(for: request) + } catch { + throw SRHTError.networkError(error) + } + + if let http = response as? HTTPURLResponse { + if http.statusCode == 401 { + throw SRHTError.unauthorized + } + if !(200...299).contains(http.statusCode) { + throw SRHTError.httpError(http.statusCode) + } + } + + return data + } + /// Fetch the contents of a URL as plain text, using the same authorization header. /// Used for build logs and other non-GraphQL resources. func fetchText(url: URL) async throws -> String { |
