您的查询组件需要“百分比转义”。此外,您的查询组件可能很特殊,因为它的结构是分层的。也就是说,服务器需要实现自定义代码来处理这个问题。
服务器解码 URL 的查询组件的标准方法是使用为解码“application/x-www-form-urlencoded”请求的主体定义的相同算法。客户端使用的相应编码算法在这里定义:
application/x-www-form-urlencoded 编码算法
(注意:查询组件是问号'?'
之后直到哈希字符的所有内容'#'
!)
但是,根据RFC 3986,此编码算法可能会为 URL 的“未保留”字符集中的字符产生百分比转义,即波浪号 ~ 字符。“未保留”字符集中的字符不需要转义。更严格地说,由于对 URI 比较实现的影响,RFC 3986 提出了以下建议:
"为保持一致性,在 ALPHA(%41-%5A 和 %61-%7A)、DIGIT (%30-%39)、连字符 (%2D)、句点 (%2E)、下划线 ( URI 生产者不应创建 %5F) 或波浪号 (%7E) ”。
因此,稍微修改的实现将波浪号排除在'~'
转义之外可能会产生最佳结果。
以下代码对参数的名称或值进行编码。注意参数必须用'&'分隔,名称和值必须用'='分隔。
static NSString* form_urlencode_rfc3986(NSString* s) {
CFStringRef charactersToLeaveUnescaped = CFSTR(" ");
//CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@~");
// Modified for urls (excluding '~'):
CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@");
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge CFStringRef)s,
charactersToLeaveUnescaped,
legalURLCharactersToBeEscaped,
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}
例子:
给定您的示例 URL,查询组件包含一个参数:
参数名称:“做”
参数值:"/webservice/whisper/login_ms@gmail.com/password_ms/action_stirwhisper/whisperstirdata_{"feed_id":"89","say_something":"pqrst","privacy":0}"
编码后的查询组件将如下所示:
do=%2Fwebservice%2Fwhisper%2Flogin_ms%40gmail.com%2Fpassword_ms%2Faction_stirwhisper%2Fwhisperstirdata_%7B%22feed_id%22%3A%2289%22%2C%22say_something%22%3A%22pqrst%22%2C%22privacy%22%3A0%7D