4

我有一个用作浏览器的 wkwebview。我无法加载带有特殊字符的地址,例如“ http://www.håbo.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.}}, 
4

1 回答 1

2

这个很复杂。从这篇文章

解析域名

如果表示域名的字符串不是 Unicode,则用户代理会将字符串转换为 Unicode。然后它对字符串执行一些规范化功能,以消除 Unicode 编码文本中可能存在的歧义。

规范化涉及诸如将大写字符转换为小写、减少替代表示(例如将半角假名转换为全角)、消除禁止字符(例如空格)等。

接下来,用户代理将 Unicode 字符串中的每个标签(即点之间的文本片段)转换为 punycode 表示。一个特殊的标记('xn--')被添加到每个包含非 ASCII 字符的标签的开头,以表明该标签最初不是 ASCII。最终结果不是非常用户友好,但准确地表示了原始字符串,同时仅使用了以前允许用于域名的字符。

例如,以下域名:

JP纳豆.example.jp

转换为下一个表示:

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

您可以使用以下代码来执行此转换。

解析路径

如果字符串由用户输入或以非 Unicode 编码存储,则将其转换为 Unicode,使用 Unicode Normalization Form C 进行规范化,并使用 UTF-8 编码进行编码。

用户代理然后将非 ASCII 字节转换为百分比转义。

例如,以下路径:

/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 组件。但我希望我已经回答了你的问题。

于 2016-03-14T20:09:00.427 回答