objective-cnsstringnsurlconnectionnsurlnsstringencoding

A single "|" character in the URL breaks loading contents of URL


I'm trying to load an article in JSON format from the Wikipedia API and I get these errors:

nil host used in call to allowsSpecificHTTPSCertificateForHost
nil host used in call to allowsAnyHTTPSCertificateForHost:
NSURLConnection finished with error - code -1002
error when trying to fetch from URL (null) - The file couldn’t be opened.

I get these errors only when the URL string includes the character "|"

The URL for an article with id=1 (pageids=1) is:

https://en.wikipedia.org/w/api.php?action=query&format=json&pageids=1&prop=extracts&exintro&explaintext

The URL above doesn't contain the character "I" so it works just fine.

In the wikipedia API you can ask for multiple articles by seperating their ids with the "|" character

The URL for the articles with ids=1,2 and 3 (pageids=1|2|3) is:

https://en.wikipedia.org/w/api.php?action=query&format=json&pageids=1|2|3&prop=extracts&exintro&explaintext

The URL above contains the "|" character and everything fails.

I use this snippet I found in another post just to catch the errors:

NSError *error = NULL;
NSStringEncoding actualEncoding;

NSString *string = [[NSString alloc] initWithContentsOfURL:url usedEncoding:&actualEncoding error:&error];
if(string)
{
    NSLog( @"hey, I actually got a result of %@", string);

    if(actualEncoding != NSUTF8StringEncoding)
    {
        NSLog( @"and look at that, the actual encoding wasn't NSUTF8StringEncoding");
    }
} else {
    NSLog( @"error when trying to fetch from URL %@ - %@", [url absoluteString], [error localizedDescription]);
}

If you go through the code, url.absoluteString returns null when there's a "|" character in it.


Solution

  • The pipe (|) is a special character. You have to encode the URL by adding appropriate percent encoding.

    This has nothing to do with the text encoding of a string.

    NSString * string = @"https://en.wikipedia.org/w/api.php?action=query&format=json&pageids=1|2|3&prop=extracts&exintro&explaintext";
    NSURL *url = [NSURL URLWithString:[string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];