diff --git a/Sources/tart/OCI/Registry.swift b/Sources/tart/OCI/Registry.swift index 4a4abf5..670244d 100644 --- a/Sources/tart/OCI/Registry.swift +++ b/Sources/tart/OCI/Registry.swift @@ -61,15 +61,11 @@ class Registry { throw RegistryError.MissingLocationHeader } - var uploadLocation = URL(string: uploadLocationRaw)! - - // If the URL provided in the Location header - // is relative — make it absolute. - if uploadLocation.absoluteString == uploadLocation.relativeString { - uploadLocation = URL(string: uploadLocation.path, relativeTo: baseURL)! + guard let uploadLocation = URL(string: uploadLocationRaw) else { + throw RegistryError.MalformedHeader(why: "Location header contains invalid URL: \"\(uploadLocationRaw)\"") } - return URLComponents(url: uploadLocation, resolvingAgainstBaseURL: true)! + return URLComponents(url: uploadLocation.absolutize(baseURL), resolvingAgainstBaseURL: true)! } public func pushBlob(fromData: Data, chunkSize: Int = 5 * 1024 * 1024) async throws -> String { @@ -137,8 +133,8 @@ class Registry { ) async throws -> (Data, HTTPURLResponse) { var urlComponents = urlComponents - if !parameters.isEmpty { - urlComponents.queryItems = Array() + if urlComponents.queryItems == nil { + urlComponents.queryItems = [] } urlComponents.queryItems?.append(contentsOf: parameters.map { key, value -> URLQueryItem in URLQueryItem(name: key, value: value) diff --git a/Sources/tart/OCI/URL+Absolutize.swift b/Sources/tart/OCI/URL+Absolutize.swift new file mode 100644 index 0000000..adb4d44 --- /dev/null +++ b/Sources/tart/OCI/URL+Absolutize.swift @@ -0,0 +1,7 @@ +import Foundation + +extension URL { + func absolutize(_ baseURL: URL) -> Self { + URL(string: absoluteString, relativeTo: baseURL)! + } +} diff --git a/Tests/TartTests/URLAbsolutizationTests.swift b/Tests/TartTests/URLAbsolutizationTests.swift new file mode 100644 index 0000000..446d855 --- /dev/null +++ b/Tests/TartTests/URLAbsolutizationTests.swift @@ -0,0 +1,18 @@ +import XCTest +@testable import tart + +final class URLAbsolutizationTets: XCTestCase { + func testNeedsAbsolutization() throws { + let url = URL(string: "/v2/some/path?some=query")! + .absolutize(URL(string: "https://example.com/v2/")!) + + XCTAssertEqual(url.absoluteString, "https://example.com/v2/some/path?some=query") + } + + func testDoesntNeedAbsolutization() throws { + let url = URL(string: "https://example.org/v2/some/path?some=query")! + .absolutize(URL(string: "https://example.com/v2/")!) + + XCTAssertEqual(url.absoluteString, "https://example.org/v2/some/path?some=query") + } +}