When using URLComponents
's queryItems
I've found that if you have a query item whose value contains some percent encoded characters, in my case a /
being encoded as %2F
, then if you construct a URLComponents
object from a String
URL that contains such a query item, then mutate the list of query items for the URLComponents
object, then if you try to get a URL
by calling .url
on the URLComponents
object, then the query items lose their percent encoding.
Here's the code I've been testing this with in a playground:
import UIKit
// --- Part 1 ---
print("--- Part 1 ---\n")
let startURL = "https://test.com/test.jpg?X-Test-Token=FQdzEPH%2F%2F%2F"
var components = URLComponents(string: startURL)!
if let compURL = components.url {
print(URL(string: startURL)! == compURL) // True
print(startURL)
print(compURL)
}
// --- Part 2 ---
print("\n--- Part 2 ---\n")
let startURLTwo = "https://test.com/test.jpg?X-Test-Token=FQdzEPH%2F%2F%2F"
let finalURL = "https://test.com/test.jpg?X-Test-Token=FQdzEPH%2F%2F%2F&foo=bar"
var componentsTwo = URLComponents(string: startURLTwo)!
let extraQueryItem = URLQueryItem(name: "foo", value: "bar")
componentsTwo.queryItems!.append(extraQueryItem)
if let compURLTwo = componentsTwo.url {
print(URL(string: finalURL)! == compURLTwo) // False
print(finalURL)
print(compURLTwo)
}
Here's an image if that makes it easier to understand what's going on:
You should use
percentEncodedQuery
if you have a query that is already percent encoded:Or you can specify it unescaped (and it leaves it unescaped as it's not necessary to escape
/
characters in a query):And if you have to update
queryItems
, just make sure to setpercentEncodedQuery
at the very end: