let urlString = "https://www.google.com/path1?param1=https://www.apple.com/path2?param2=asdf"
print(urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed))
// https://www.google.com/path1?param1=https://www.apple.com/path2?param2=asdf
// It is not encoded.
I think, my expectation is below.
https://www.google.com/path1?param1=https%3A%2F%2Fwww.apple.com%2Fpath2%3Fparam2%3Dasdf
The idiomatic answer is URLComponents, which is designed to do this percent-encoding for us.
So consider that you have a well-formed URL, https://www.apple.com/path2?param2=asdf, that you want to pass as param1 to the Google URL. It would be:
guard var components = URLComponents(string: "https://www.google.com") else {
return
}
components.queryItems = [
URLQueryItem(name: "param1", value: "https://www.apple.com/path2?param2=asdf"),
]
guard let url = components.url else {
return
}
print(url) // https://www.google.com?param1=https://www.apple.com/path2?param2%3Dasdf
Note:
The : and / within the value associated param1 technically do not need to be percent-encoded, so neither URLComponents nor encoding with .urlQueryAllowed will do so. They employ a minimal encoding strategy.
Apple’s approach is consistent with section 3.4 of RFC 3986, which explicitly contemplates URLs in the query parameter, advising that it is “sometimes better for usability” to not percent-encode these URLS:
However, as query components are often used to carry identifying information in the form of “key=value” pairs and one frequently used value is a reference to another URI, it is sometimes better for usability to avoid percent-encoding those characters.
That having been said, the remainder of the URL buried in the param1 parameter is percent-encoded to avoid ambiguity between its parameters and those of the main Google URL.