WKWebView загружает веб-страницу со специальными символами

У меня есть wkwebview, который работает как браузер. Мне не удается загрузить адреса со специальными символами, такими как "http://www.h%C3%A5bo.se" (шведский символ).

Я использую:

parsedUrl = [parsedUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

что многообещающе, поскольку создает адрес, который выглядит следующим образом: http://www.h%c3%a5bo.se/

Если я ввожу это в Chrome, он работает. Но когда я пытаюсь загрузить его в wkwebview, я получаю следующее (я могу загрузить все остальные страницы):

Вот полный напечатанный NSError

Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo={_WKRecoveryAttempterErrorKey=<WKReloadFrameErrorRecoveryAttempter: 0x7f82ca502290>, NSErrorFailingURLStringKey=http://www.h%c3%a5bo.se/, NSErrorFailingURLKey=http://www.h%c3%a5bo.se/, NSUnderlyingError=0x7f82ca692200 {Error Domain=kCFErrorDomainCFNetwork Code=-1003 "A server with the specified hostname could not be found." UserInfo={NSErrorFailingURLStringKey=http://www.h%c3%a5bo.se/, NSErrorFailingURLKey=http://www.h%c3%a5bo.se/, _kCFStreamErrorCodeKey=8, _kCFStreamErrorDomainKey=12, NSLocalizedDescription=A server with the specified hostname could not be found.}}, 

person Daniel Åkesson    schedule 14.03.2016    source источник


Ответы (1)


Этот сложный. Из этой статьи:

Разрешение доменного имени

Если строка, представляющая имя домена, не в Юникоде, пользовательский агент преобразует строку в Юникод. Затем он выполняет некоторые функции нормализации строки, чтобы устранить неоднозначности, которые могут существовать в тексте, закодированном в Unicode.

Нормализация включает в себя такие вещи, как преобразование символов верхнего регистра в нижний регистр, сокращение альтернативных представлений (например, преобразование каны половинной ширины в полную), устранение запрещенных символов (например, пробелов) и т. д.

Затем пользовательский агент преобразует каждую из меток (т. е. фрагментов текста между точками) в строке Unicode в представление punycode. В начало каждой метки, содержащей символы, отличные от ASCII, добавляется специальный маркер ('xn--'), чтобы показать, что метка изначально не была ASCII. Конечный результат не очень удобен для пользователя, но точно представляет исходную строку символов, используя только те символы, которые ранее были разрешены для доменных имен.

Например, следующее доменное имя:

JP納豆.例.jp

преобразуется в следующее представление:

xn--jp-cd2fp15c.xn--fsq.jp

Вы можете использовать следующий код для выполнения этого преобразования.

Разрешение пути

Если строка вводится пользователем или сохраняется в кодировке, отличной от Unicode, она преобразуется в Unicode, нормализуется с использованием формы нормализации Unicode C и кодируется с использованием кодировки UTF-8.

Затем пользовательский агент преобразует байты, отличные от ASCII, в процентные escape-последовательности.

Например, следующий путь:

/dir1/引き割り.html

преобразуется в следующее представление:

/dir1/%E5%BC%95%E3%81%8D%E5%89%B2%E3%82%8A.html

Для этой цели вы можете использовать следующий код:

path = [URL.path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];

Обратите внимание, что stringByAddingPercentEscapesUsingEncoding: устарел, потому что каждый компонент или подкомпонент URL имеет разные правила относительно того, какие символы допустимы.

Собираем все вместе

Результирующий код:

@implementation NSURL (Normalization)

- (NSURL*)normalizedURL {
    NSURLComponents *components = [NSURLComponents componentsWithURL:self resolvingAgainstBaseURL:YES];
    components.host = [components.host IDNAEncodedString]; // from https://github.com/OnionBrowser/iOS-OnionBrowser/blob/master/OnionBrowser/NSStringPunycodeAdditions.h
    components.path = [components.path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];
    return components.URL;
}

@end

К сожалению, фактическая «нормализация» URL-адреса более сложна — вам также необходимо обрабатывать все остальные компоненты URL-адреса. Но я надеюсь, что ответил на ваш вопрос.

person Borys Verebskyi    schedule 14.03.2016
comment
Спасибо за ваш ответ, я не думал, что это необходимо для преобразования в IDN. Я использовал это: github.com/wordpress-mobile/NSURL-IDN и преобразовал string перед созданием NSURL, и это работает как шарм. - person Daniel Åkesson; 15.03.2016