文章地址
在 RFC 3986 文档中规定,URL 中只允许包含以下四种:
- 英文字母 a-z 以及 A-Z
- 数字 0-9
- 4个特殊字符:中横线 -、下划线 _、小数点 . 以及波浪线 ~
- 保留字符:!*'();:@&=+$,/?#[]
除上述四种字符外,所有其他字符都将被替换成百分号 % + 两位十六进制数。
@":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`\r\n\t" // @"" 是 OC 语法, 关注引号中字符即可
这33个字符需要转义, 其中
@" \"#%&()+,/:;<>=?@\\|"
是特殊字符转义编码, 一定要转义
@"{}^[]`~"
这些属于不安全字段, 传输过程中某些网关会篡改这些字符, 最好也转义
对于 NSURLComponents 不能解析的字符串有
@"[] \"<>%{}|\\^`\r\n\t"
这 16 个字符, 执行 urlComponents.queryItems 为 nil
特殊字符的编码如下:
ASCII 字符 | URL-编码 |
---|---|
空格 | %20 |
! | %21 |
" | %22 |
# | %23 |
$ | %24 |
% | %25 |
& | %26 |
' | %27 |
( | %28 |
) | %29 |
* | %2A |
+ | %2B |
, | %2C |
- | %2D |
. | %2E |
/ | %2F |
: | %3A |
; | %3B |
< | %3C |
= | %3D |
> | %3E |
? | %3F |
@ | %40 |
[ | %5B |
\ | %5C |
] | %5D |
^ | %5E |
_ | %5F |
` | %60 |
{ | %7B |
| | %7C |
} | %7D |
~ | %7E |
问题原由
在 url 解析参数时, 对 query 参数做了 [NSString stringByRemovingPercentEncoding]
转义, 替换掉了所有的 %20 转义字符, 然后将转移后的 url 交给 WebView 展示. 然后 webview 在使用 NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithString:url];
解析 url 时, 发现 url 含有'^|'等字符就直接解析失败, 造成 bug, 解决办法也很简单, 在解析失败的时候, 针对
[] \"<>%{}|\\^`\r\n\t
这些字符做重新编码, 然后再使用 NSURLComponents
解析即可, 代码如下
NSString *specialString = @"[] \"<>%{}|\\^`\r\n\t";
NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:specialString] invertedSet];
NSString *encoded = [url stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
// 再解析 encoded 即可