3

I know how to encode a string in URL format (the smiley face is intentional):

let str = "www.mywebsite.com/😀.html"
let escapedStr = str.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())!
print(escapedStr)

// Output:
// www.mywebsite.com/%F0%9F%98%80.html

But if I attach http:// to the unescaped string Swift escapes the colon too:

let str = "http://www.mywebsite.com/😀.html"
let escapedStr = str.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())!
print(escapedStr)

// Output
// http%3A//www.mywebsite.com/%F0%9F%98%80.html

So short of removing and adding http:// manually, how can I properly escape those strings? There are other prefixes I must handle handle like https://, ftp:// or ssh://

3 Answers 3

5
+50

: is not a legal character in the path part of an URL. You percent-encoded everything not in URLPathAllowedCharacterSet, so it shouldn't be surprising that the : was encoded.

Each part of an URL has different encoding rules. iOS can't correctly encode an URL until it knows what goes in what part, and it can't do that from an unencoded string (since it'd have to parse it first, and it can't parse it because it's not correctly encoded yet). In some systems (including older versions of iOS), it would use various heuristics that assumed "well, I guess you probably meant..." rather than actually following the URL-encoding rules. This was convenient common cases, while mis-encoding less common, but legal, cases (especially involving non-http URLs and non-Latin URLs). iOS now follows the rules, so things encode consistently, but it means you need to actually think about URLs and not just throw random stuff at the system and hope it figures it out.

The best way to do this (if you have to compute this stuff dynamically) is with NSURLComponents:

let url = NSURLComponents()
url.scheme = "http"
url.host = "www.mywebsite.com"
url.path = "/😀.html"

url.string                // "http://www.mywebsite.com/%F0%9F%98%80.html"
url.percentEncodedPath    // "/%F0%9F%98%80.html"
url.URL                   // http://www.mywebsite.com/%F0%9F%98%80.html
// etc.

See also NSURLComponents.URLReativeToURL if you have some base, static URL that you don't have to worry about dynamically encoding.

let baseURL = NSURL(string: "http://www.mywebsite.com")

let relative = NSURLComponents()
relative.path = "/😀.html"
let url = relative.URLRelativeToURL(baseURL)
url?.absoluteString
Sign up to request clarification or add additional context in comments.

Comments

0

You're confusing things – the special characters after the domain name need to be escaped using the "percent encoding" (I don't think that's 100% the correct term), according to the HTTP standard.

The Domain name itself can contain any unicode codepoint (and the client should then apply Punycode to map it to a DNS name), and the URL classifier (http:) must not be escaped.

So, yes, you'll need to handle these parts of your URL differently – no way around that. Other protocols might require other encoding of special characters than HTTP does. For example, the ssh: URL class (which is pretty application specific. SSH as it is just a family of secure transports, not a means to describe a uniform ressource location) will probably have wildly different approaches to non-ASCII characters than HTTP, depending on what you actually mean with ssh: "URLs".

Comments

0

The fastest way to do:

In past you use to escape and encode your string to UTF8 coding the following statement:

let str = "http://www.mywebsite.com/😀.html"
let escapedStr = str.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

Now this code is deprecated so the equivalent in swift 2.2 is:

let str = "http://www.mywebsite.com/😀.html"
let escapedStr = str.stringByAddingPercentEncodingWithAllowedCharacters(.URLQueryAllowedCharacterSet())

It encodes everything after the question mark in the URL string.

Comments

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.