1

I want to encode url with percent encoding.
If the value of query parameter is url type, how can I encode?
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

3
  • 2
    Are you given the entire unescaped URL as a String? Or do you have the components and is trying to construct a URL? Commented Aug 29 at 8:47
  • 1
    If you have a string only: What happens if you have an URL like https://example.com?p1=https://foo.bar?p2=x&p3=y? How do you know, whether p3 is a parameter to example.com or foo.bar? Commented Aug 29 at 9:20
  • @Sweeper It's the latter. I want to construct appropriately url-encoded URL. Commented Sep 2 at 8:04

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

5 Comments

By the way, one unrelated caveat: The “+” character. If you send a query of calculate=1+2, web servers often employ “form encoding”, and will interpret the + as a space, and not as a +. If you want that percent-encoded, you have to do that yourself. Apple’s position is not entirely unwarranted because the “+ ⇒ space” logic is technically not part of the URI-encoding scheme, but rather an idiosyncrasy of “form encoding”. That is the only edge case, AFAIK, in Apple’s percent-encoding strategy. Apple advises manually percent-encoding those + yourself if that’s what you require.
I agree with the recommendation to use URLComponents. It knows what type of encoding to apply to each of the different components (excluding some of the "gray areas" that Rob mentions.)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.