summaryrefslogtreecommitdiff
path: root/Hutch/Networking
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-07-16 01:29:06 -0500
committerGitHub <[email protected]>2026-07-16 01:29:06 -0500
commit8e585a709d8979d493fef3ed4015db93687f48e8 (patch)
treefaebe598a4c6f7a5f3db92d465ed693aab594252 /Hutch/Networking
parentf100206cc6d6784563d8eb905c9feb15c58bcc1e (diff)
parent21be03e6ca54c1a15607faab905b119eda9a548f (diff)
downloadhutch-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')
-rw-r--r--Hutch/Networking/SRHTClient.swift37
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 {