質問

I'm using AFNetworking in my iOS App. I've discovered a problem that occurs when request parameters contain percent signs. Then the encoding fails. The method AFURLEncodedStringFromStringWithEncoding returns nil.

I've tested this code and it prints (null):

NSLog(@"%@", AFURLEncodedStringFromStringWithEncoding(@"%", NSUTF8StringEncoding));

The expected output should be: %25. Other characters can be encoded with no problem.

The method is defined as follows:

NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
    static NSString * const kAFLegalCharactersToBeEscaped = @"?!@#$^&%*+,:;='\"`<>()[]{}/\\|~ ";

    // Following the suggestion in documentation for `CFURLCreateStringByAddingPercentEscapes` to "pre-process" URL strings (using stringByReplacingPercentEscapesUsingEncoding) with unpredictable sequences that may already contain percent escapes.
    return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)[string stringByReplacingPercentEscapesUsingEncoding:encoding], NULL, (CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease];
}

Any ideas what's going wrong here?

EDIT: The issue has been fixed in AFNetworking.

役に立ちましたか?

解決

I don't know about the API but URL encoding is normally done by

  • UTF-8 encoding the string portions--path, arguments, etc--into bytes
  • applying percent-encoding of the byte values to obtain ASCII-only string pieces
  • assembling the URL pieces together with the separators :, /, ?, & etc.
  • encoding that string into bytes again
  • sending it over the wire

See http://tools.ietf.org/html/rfc3986#section-2.5 for nuances. Note that the RFC states that if the URL refers to a document on an EBCDIC system, the URL should specify the byte values for the EBCDIC encoding of its name, not the string name that human users of the EBCDIC system know it by. So a URL is ultimately a byte-string not a character-string.

As to how to get your API to represent that byte-string correctly, I am unsure.

他のヒント

Just removing the stringByReplacingPercentEscapesUsingEncoding:encoding is fine, no need to encode twice, so the return value should be:

return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, 
                    (CFStringRef)string, 
                    NULL, 
                    (CFStringRef)kAFLegalCharactersToBeEscaped, 
                    CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease];
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top