diff --git a/Sources/FoundationEssentials/URL/URLComponents.swift b/Sources/FoundationEssentials/URL/URLComponents.swift index 127f9a90e..c3aabffaf 100644 --- a/Sources/FoundationEssentials/URL/URLComponents.swift +++ b/Sources/FoundationEssentials/URL/URLComponents.swift @@ -480,7 +480,7 @@ public struct URLComponents: Hashable, Equatable, Sendable { } else { result += percentEncodedPath } - if let percentEncodedQuery { + if let percentEncodedQuery, !percentEncodedQuery.isEmpty { result += "?\(percentEncodedQuery)" } if let percentEncodedFragment { @@ -526,9 +526,9 @@ public struct URLComponents: Hashable, Equatable, Sendable { } else { result += percentEncodedPath } - if componentsToDecode.contains(.query), let query { + if componentsToDecode.contains(.query), let query, !query.isEmpty { result += "?\(query)" - } else if let percentEncodedQuery { + } else if let percentEncodedQuery, !percentEncodedQuery.isEmpty { result += "?\(percentEncodedQuery)" } if componentsToDecode.contains(.fragment), let fragment { diff --git a/Sources/FoundationEssentials/URL/URLParser.swift b/Sources/FoundationEssentials/URL/URLParser.swift index 17e4cd272..991e15fc9 100644 --- a/Sources/FoundationEssentials/URL/URLParser.swift +++ b/Sources/FoundationEssentials/URL/URLParser.swift @@ -711,7 +711,7 @@ internal struct RFC3986Parser { finalURLString += path } - if let query = parseInfo.query { + if let query = parseInfo.query, !query.isEmpty { if invalidComponents.contains(.query) { finalURLString += "?\(percentEncode(query, component: .query)!)" } else { @@ -1322,7 +1322,7 @@ extension RFC3986Parser { finalURLString += path } - if let query = parseInfo.query { + if let query = parseInfo.query, !query.isEmpty { if invalidComponents.contains(.query) { finalURLString += "?\(percentEncode(query, component: .query, skipAlreadyEncoded: true)!)" } else { diff --git a/Sources/FoundationEssentials/URL/URL_ObjC.swift b/Sources/FoundationEssentials/URL/URL_ObjC.swift index 3b3f836b5..e38f493c0 100644 --- a/Sources/FoundationEssentials/URL/URL_ObjC.swift +++ b/Sources/FoundationEssentials/URL/URL_ObjC.swift @@ -486,7 +486,7 @@ extension _NSSwiftURL { return String(relativeString[start...]) } var result: String? - if let query = url._parseInfo.query { + if let query = url._parseInfo.query, !query.isEmpty { result = "?\(query)" } if let fragment = url._parseInfo.fragment { diff --git a/Sources/FoundationEssentials/URL/URL_Swift.swift b/Sources/FoundationEssentials/URL/URL_Swift.swift index 0507990ce..6a67052ae 100644 --- a/Sources/FoundationEssentials/URL/URL_Swift.swift +++ b/Sources/FoundationEssentials/URL/URL_Swift.swift @@ -1115,7 +1115,7 @@ internal final class _SwiftURL: Sendable, Hashable, Equatable { result += ":\(portString)" } result += path - if let query { + if let query, !query.isEmpty { result += "?\(query)" } if let fragment { diff --git a/Tests/FoundationEssentialsTests/URLTests.swift b/Tests/FoundationEssentialsTests/URLTests.swift index 344454a67..85759ec22 100644 --- a/Tests/FoundationEssentialsTests/URLTests.swift +++ b/Tests/FoundationEssentialsTests/URLTests.swift @@ -666,6 +666,12 @@ private struct URLTests { ) // Append queryItems + let emptyQueryItems = [URLQueryItem]() + #expect( + base.appending(queryItems: emptyQueryItems).absoluteString == + "https://www.example.com" + ) + let queryItems = [ URLQueryItem(name: "id", value: "42"), URLQueryItem(name: "color", value: "blue")