[Issue #619] Sorting dictionary keys with caseInsensitiveCompare to ensure deterministic ordering of query string parameters, which may otherwise cause ambiguous representations of nested parameters
This commit is contained in:
parent
9cde4e4584
commit
5b32b45469
2 changed files with 10 additions and 3 deletions
|
|
@ -113,6 +113,8 @@ typedef enum {
|
|||
|
||||
/**
|
||||
The `AFHTTPClientParameterEncoding` value corresponding to how parameters are encoded into a request body. This is `AFFormURLParameterEncoding` by default.
|
||||
|
||||
@warning Some nested parameter structures, such as a keyed array of hashes containing inconsistent keys (i.e. `@{@"": @[@{@"a" : @(1)}, @{@"b" : @(2)}]}`), cannot be unambiguously represented in query strings. It is strongly recommended that an unambiguous encoding, such as `AFJSONParameterEncoding`, is used when posting complicated or nondeterministic parameter structures.
|
||||
*/
|
||||
@property (nonatomic, assign) AFHTTPClientParameterEncoding parameterEncoding;
|
||||
|
||||
|
|
@ -461,7 +463,7 @@ typedef enum {
|
|||
}
|
||||
|
||||
`AFFormURLParameterEncoding`
|
||||
Parameters are encoded into field/key pairs in the URL query string for `GET` `HEAD` and `DELETE` requests, and in the message body otherwise.
|
||||
Parameters are encoded into field/key pairs in the URL query string for `GET` `HEAD` and `DELETE` requests, and in the message body otherwise. Dictionary keys are sorted with the `caseInsensitiveCompare:` selector of their description, in order to mitigate the possibility of ambiguous query strings being generated non-deterministically. See the warning for the `parameterEncoding` property for additional information.
|
||||
|
||||
`AFJSONParameterEncoding`
|
||||
Parameters are encoded into JSON in the message body.
|
||||
|
|
|
|||
|
|
@ -146,8 +146,13 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
|||
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
||||
|
||||
if([value isKindOfClass:[NSDictionary class]]) {
|
||||
[value enumerateKeysAndObjectsUsingBlock:^(id nestedKey, id nestedValue, BOOL *stop) {
|
||||
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
||||
// Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
|
||||
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(caseInsensitiveCompare:)];
|
||||
[[[value allKeys] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]] enumerateObjectsUsingBlock:^(id nestedKey, NSUInteger idx, BOOL *stop) {
|
||||
id nestedValue = [value objectForKey:nestedKey];
|
||||
if (nestedValue) {
|
||||
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
||||
}
|
||||
}];
|
||||
} else if([value isKindOfClass:[NSArray class]]) {
|
||||
[value enumerateObjectsUsingBlock:^(id nestedValue, NSUInteger idx, BOOL *stop) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue