Skip to content

Commit 6623791

Browse files
Send registry User-Agent header
1 parent 1437c67 commit 6623791

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

Sources/ContainerizationOCI/Client/RegistryClient.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ public final class RegistryClient: ContentClient {
167167
request.headers.add(name: "Authorization", value: "\(token)")
168168
}
169169

170-
// Add any arbitrary headers
171-
headers?.forEach { (k, v) in request.headers.add(name: k, value: v) }
170+
// Add any arbitrary headers.
171+
requestHeaders(merging: headers).forEach { (k, v) in request.headers.add(name: k, value: v) }
172172
var retryCount = 0
173173
var response: HTTPClientResponse?
174174
while true {
@@ -258,6 +258,17 @@ public final class RegistryClient: ContentClient {
258258
return try await closure(response)
259259
}
260260

261+
internal func requestHeaders(merging headers: [(String, String)]?) -> [(String, String)] {
262+
var merged: [(String, String)] = []
263+
if headers?.contains(where: { $0.0.caseInsensitiveCompare("User-Agent") == .orderedSame }) != true {
264+
merged.append(("User-Agent", clientID))
265+
}
266+
if let headers {
267+
merged.append(contentsOf: headers)
268+
}
269+
return merged
270+
}
271+
261272
internal func requestData(
262273
components: URLComponents,
263274
headers: [(String, String)]? = nil

Tests/ContainerizationOCITests/RegistryClientTests.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,25 @@ struct OCIClientTests: ~Copyable {
100100
try await client.ping()
101101
}
102102

103+
@Test func requestHeadersAddDefaultUserAgent() async throws {
104+
let client = RegistryClient(host: "ghcr.io", clientID: "containerization-tests")
105+
let headers = client.requestHeaders(merging: [("Accept", "*/*")])
106+
107+
#expect(headers.contains { $0.0 == "User-Agent" && $0.1 == "containerization-tests" })
108+
#expect(headers.contains { $0.0 == "Accept" && $0.1 == "*/*" })
109+
}
110+
111+
@Test func requestHeadersKeepExplicitUserAgent() async throws {
112+
let client = RegistryClient(host: "ghcr.io", clientID: "containerization-tests")
113+
let headers = client.requestHeaders(merging: [
114+
("Accept", "*/*"),
115+
("user-agent", "custom-client"),
116+
])
117+
118+
#expect(!headers.contains { $0.0 == "User-Agent" && $0.1 == "containerization-tests" })
119+
#expect(headers.contains { $0.0 == "user-agent" && $0.1 == "custom-client" })
120+
}
121+
103122
@Test func resolve() async throws {
104123
let client = RegistryClient(host: "ghcr.io")
105124
let descriptor = try await client.resolve(name: "apple/containerization/dockermanifestimage", tag: "0.0.2")

0 commit comments

Comments
 (0)