mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-24 04:46:01 +08:00
Fix issues with mapping errors from 5xx payloads. Ensure acceptableStatusCodes tracks the status codes configured in the response descriptors. fixes #1157
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
|
||||
#import "RKObjectRequestOperation.h"
|
||||
#import "RKResponseMapperOperation.h"
|
||||
#import "RKResponseDescriptor.h"
|
||||
#import "RKMIMETypeSerialization.h"
|
||||
#import "RKHTTPUtilities.h"
|
||||
#import "RKLog.h"
|
||||
@@ -57,15 +58,14 @@ static inline NSString *RKDescriptionForRequest(NSURLRequest *request)
|
||||
return [NSString stringWithFormat:@"%@ '%@'", request.HTTPMethod, [request.URL absoluteString]];
|
||||
}
|
||||
|
||||
static NSIndexSet *RKObjectRequestOperationAcceptableStatusCodes()
|
||||
static NSIndexSet *RKAcceptableStatusCodesFromResponseDescriptors(NSArray *responseDescriptors)
|
||||
{
|
||||
static NSMutableIndexSet *statusCodes = nil;
|
||||
if (! statusCodes) {
|
||||
statusCodes = [NSMutableIndexSet indexSet];
|
||||
[statusCodes addIndexesInRange:RKStatusCodeRangeForClass(RKStatusCodeClassSuccessful)];
|
||||
[statusCodes addIndexesInRange:RKStatusCodeRangeForClass(RKStatusCodeClassClientError)];
|
||||
}
|
||||
return statusCodes;
|
||||
NSMutableIndexSet *acceptableStatusCodes = [NSMutableIndexSet indexSet];
|
||||
[responseDescriptors enumerateObjectsUsingBlock:^(RKResponseDescriptor *responseDescriptor, NSUInteger idx, BOOL *stop) {
|
||||
[acceptableStatusCodes addIndexes:responseDescriptor.statusCodes];
|
||||
}];
|
||||
// If there are no indexes specified in the response descriptors, then we want to aceept anything
|
||||
return [acceptableStatusCodes count] ? acceptableStatusCodes : nil;
|
||||
}
|
||||
|
||||
static NSString *RKStringForStateOfObjectRequestOperation(RKObjectRequestOperation *operation)
|
||||
@@ -143,7 +143,7 @@ static NSString *RKStringDescribingURLResponseWithData(NSURLResponse *response,
|
||||
self.responseDescriptors = responseDescriptors;
|
||||
self.HTTPRequestOperation = requestOperation;
|
||||
self.HTTPRequestOperation.acceptableContentTypes = [RKMIMETypeSerialization registeredMIMETypes];
|
||||
self.HTTPRequestOperation.acceptableStatusCodes = RKObjectRequestOperationAcceptableStatusCodes();
|
||||
self.HTTPRequestOperation.acceptableStatusCodes = RKAcceptableStatusCodesFromResponseDescriptors(responseDescriptors);
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -91,6 +91,17 @@ static NSString *RKFailureReasonErrorStringForResponseDescriptorsMismatchWithRes
|
||||
return failureReason;
|
||||
}
|
||||
|
||||
static NSIndexSet *RKErrorStatusCodes()
|
||||
{
|
||||
static NSIndexSet *errorStatusCodes = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
errorStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(400, 200)];
|
||||
});
|
||||
|
||||
return errorStatusCodes;
|
||||
}
|
||||
|
||||
/**
|
||||
A serial dispatch queue used for all deserialization of response bodies
|
||||
*/
|
||||
@@ -211,10 +222,10 @@ static dispatch_queue_t RKResponseMapperSerializationQueue() {
|
||||
{
|
||||
if (self.isCancelled) return;
|
||||
|
||||
BOOL isClientError = NSLocationInRange(self.response.statusCode, RKStatusCodeRangeForClass(RKStatusCodeClassClientError));
|
||||
|
||||
BOOL isErrorStatusCode = [RKErrorStatusCodes() containsIndex:self.response.statusCode];
|
||||
|
||||
// If we are an error response and empty, we emit an error that the content is unmappable
|
||||
if (isClientError && [self hasEmptyResponse]) {
|
||||
if (isErrorStatusCode && [self hasEmptyResponse]) {
|
||||
self.error = RKUnprocessableClientErrorFromResponse(self.response);
|
||||
return;
|
||||
}
|
||||
@@ -258,7 +269,7 @@ static dispatch_queue_t RKResponseMapperSerializationQueue() {
|
||||
self.mappingResult = [self performMappingWithObject:parsedBody error:&error];
|
||||
|
||||
// If the response is a client error return either the mapping error or the mapped result to the caller as the error
|
||||
if (isClientError) {
|
||||
if (isErrorStatusCode) {
|
||||
if ([self.mappingResult count] > 0) {
|
||||
error = RKErrorFromMappingResult(self.mappingResult);
|
||||
} else {
|
||||
|
||||
@@ -54,9 +54,6 @@
|
||||
|
||||
- (RKResponseDescriptor *)responseDescriptorForComplexUser
|
||||
{
|
||||
// NSMutableDictionary *mappingDictionary = [NSMutableDictionary dictionary];
|
||||
// [mappingsDictionary setObject:userMapping forKey:@"data.STUser"];
|
||||
// return provider;
|
||||
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
||||
[userMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"firstname" toKeyPath:@"firstname"]];
|
||||
|
||||
@@ -606,7 +603,7 @@
|
||||
[requestOperation waitUntilFinished];
|
||||
|
||||
expect(requestOperation.error).notTo.beNil();
|
||||
expect([requestOperation.error localizedDescription]).to.equal(@"Expected status code in (200-299,400-499), got 503");
|
||||
expect([requestOperation.error localizedDescription]).to.equal(@"Expected status code in (200-299), got 503");
|
||||
}
|
||||
|
||||
- (void)testThatMapperOperationDelegateIsPassedThroughToUnderlyingMapperOperation
|
||||
|
||||
@@ -1105,4 +1105,21 @@
|
||||
expect(tagsCount).to.equal(2);
|
||||
}
|
||||
|
||||
- (void)testMappingErrorsFromFiveHundredStatusCodeRange
|
||||
{
|
||||
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
|
||||
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassServerError);
|
||||
RKObjectMapping *errorResponseMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
|
||||
[errorResponseMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"errorMessage"]];
|
||||
[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:errorResponseMapping pathPattern:nil keyPath:@"errors" statusCodes:statusCodes]];
|
||||
|
||||
__block NSError *error = nil;
|
||||
[objectManager getObjectsAtPath:@"/fail" parameters:nil success:nil failure:^(RKObjectRequestOperation *operation, NSError *blockError) {
|
||||
error = blockError;
|
||||
}];
|
||||
|
||||
expect(error).willNot.beNil();
|
||||
expect([error localizedDescription]).to.equal(@"error1, error2");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user