mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-01-12 22:51:50 +08:00
Override error implementation to correct the NSLocalizedDescription key for RKHTTPRequestOperation objects. fixes #1070
This commit is contained in:
@@ -28,6 +28,8 @@
|
||||
#undef RKLogComponent
|
||||
#define RKLogComponent RKlcl_cRestKitNetwork
|
||||
|
||||
NSString *RKStringFromIndexSet(NSIndexSet *indexSet); // Defined in RKResponseDescriptor.m
|
||||
|
||||
static BOOL RKLogIsStringBlank(NSString *string)
|
||||
{
|
||||
return ([[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0);
|
||||
@@ -163,10 +165,13 @@ static NSString *RKStringDescribingStream(NSStream *stream)
|
||||
@end
|
||||
|
||||
@interface AFURLConnectionOperation () <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
|
||||
@property (readwrite, nonatomic, strong) NSError *HTTPError;
|
||||
@end
|
||||
|
||||
@implementation RKHTTPRequestOperation
|
||||
|
||||
@dynamic HTTPError;
|
||||
|
||||
- (BOOL)hasAcceptableStatusCode
|
||||
{
|
||||
return self.acceptableStatusCodes ? [self.acceptableStatusCodes containsIndex:[self.response statusCode]] : [super hasAcceptableStatusCode];
|
||||
@@ -177,6 +182,32 @@ static NSString *RKStringDescribingStream(NSStream *stream)
|
||||
return self.acceptableContentTypes ? RKMIMETypeInSet([self.response MIMEType], self.acceptableContentTypes) : [super hasAcceptableContentType];
|
||||
}
|
||||
|
||||
- (NSError *)error
|
||||
{
|
||||
// The first we are invoked, we need to mutate the HTTP error to correct the Content Types and Status Codes returned
|
||||
if (self.response && !self.HTTPError) {
|
||||
NSError *error = [super error];
|
||||
if ([error.domain isEqualToString:AFNetworkingErrorDomain]) {
|
||||
if (![self hasAcceptableStatusCode] || ![self hasAcceptableContentType]) {
|
||||
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
|
||||
|
||||
if (error.code == NSURLErrorBadServerResponse) {
|
||||
// Replace the NSLocalizedDescriptionKey
|
||||
NSUInteger statusCode = ([self.response isKindOfClass:[NSHTTPURLResponse class]]) ? (NSUInteger)[self.response statusCode] : 200;
|
||||
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected status code in (%@), got %d", nil), RKStringFromIndexSet([self acceptableStatusCodes]), statusCode] forKey:NSLocalizedDescriptionKey];
|
||||
self.HTTPError = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo];
|
||||
} else if (error.code == NSURLErrorCannotDecodeContentData) {
|
||||
// Because we have shifted the Acceptable Content Types and Status Codes
|
||||
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected content type %@, got %@", nil), [self acceptableContentTypes], [self.response MIMEType]] forKey:NSLocalizedDescriptionKey];
|
||||
self.HTTPError = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [super error];
|
||||
}
|
||||
|
||||
- (BOOL)wasNotModified
|
||||
{
|
||||
return [(NSString *)[[self.response allHeaderFields] objectForKey:@"Status"] isEqualToString:@"304 Not Modified"];
|
||||
|
||||
@@ -312,7 +312,7 @@ RKMappingResult, RKRequestDescriptor, RKResponseDescriptor;
|
||||
@property (nonatomic, strong) NSString *requestSerializationMIMEType;
|
||||
|
||||
/**
|
||||
Sets a default header on the HTTP cleitn for the HTTP "Accept" header to specify the preferred serialization format for retrieved data.
|
||||
Sets a default header on the HTTP client for the HTTP "Accept" header to specify the preferred serialization format for retrieved data.
|
||||
|
||||
This method is a convenience method whose implementation is equivalent to the following example code:
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ static inline NSString *RKDescriptionForRequest(NSURLRequest *request)
|
||||
return [NSString stringWithFormat:@"%@ '%@'", request.HTTPMethod, [request.URL absoluteString]];
|
||||
}
|
||||
|
||||
static NSIndexSet *RKObjectRequestOperationAcceptableMIMETypes()
|
||||
static NSIndexSet *RKObjectRequestOperationAcceptableStatusCodes()
|
||||
{
|
||||
static NSMutableIndexSet *statusCodes = nil;
|
||||
if (! statusCodes) {
|
||||
@@ -136,7 +136,7 @@ static NSString *RKStringDescribingURLResponseWithData(NSURLResponse *response,
|
||||
self.responseDescriptors = responseDescriptors;
|
||||
self.HTTPRequestOperation = requestOperation;
|
||||
self.HTTPRequestOperation.acceptableContentTypes = [RKMIMETypeSerialization registeredMIMETypes];
|
||||
self.HTTPRequestOperation.acceptableStatusCodes = RKObjectRequestOperationAcceptableMIMETypes();
|
||||
self.HTTPRequestOperation.acceptableStatusCodes = RKObjectRequestOperationAcceptableStatusCodes();
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -367,6 +367,8 @@
|
||||
2548AC6E162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2548AC6C162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m */; };
|
||||
2549D646162B376F003DD135 /* RKRequestDescriptorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2549D645162B376F003DD135 /* RKRequestDescriptorTest.m */; };
|
||||
2549D647162B376F003DD135 /* RKRequestDescriptorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2549D645162B376F003DD135 /* RKRequestDescriptorTest.m */; };
|
||||
2551338F167838590017E4B6 /* RKHTTPRequestOperationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2551338E167838590017E4B6 /* RKHTTPRequestOperationTest.m */; };
|
||||
25513390167838590017E4B6 /* RKHTTPRequestOperationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2551338E167838590017E4B6 /* RKHTTPRequestOperationTest.m */; };
|
||||
25565956161FC3C300F5BB20 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 25565955161FC3C300F5BB20 /* CoreServices.framework */; };
|
||||
25565959161FC3CD00F5BB20 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 25565958161FC3CD00F5BB20 /* SystemConfiguration.framework */; };
|
||||
25565965161FDD8800F5BB20 /* RKResponseMapperOperationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25565964161FDD8800F5BB20 /* RKResponseMapperOperationTest.m */; };
|
||||
@@ -827,6 +829,7 @@
|
||||
2548AC6C162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectRequestOperationTest.m; sourceTree = "<group>"; };
|
||||
2549D645162B376F003DD135 /* RKRequestDescriptorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKRequestDescriptorTest.m; sourceTree = "<group>"; };
|
||||
254A62BF14AD591C00939BEE /* RKPaginatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKPaginatorTest.m; sourceTree = "<group>"; };
|
||||
2551338E167838590017E4B6 /* RKHTTPRequestOperationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKHTTPRequestOperationTest.m; sourceTree = "<group>"; };
|
||||
25565955161FC3C300F5BB20 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/CoreServices.framework; sourceTree = DEVELOPER_DIR; };
|
||||
25565958161FC3CD00F5BB20 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; };
|
||||
25565964161FDD8800F5BB20 /* RKResponseMapperOperationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKResponseMapperOperationTest.m; sourceTree = "<group>"; };
|
||||
@@ -1454,6 +1457,7 @@
|
||||
2549D645162B376F003DD135 /* RKRequestDescriptorTest.m */,
|
||||
2548AC6C162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m */,
|
||||
2536D1FC167270F100DF9BB0 /* RKRouterTest.m */,
|
||||
2551338E167838590017E4B6 /* RKHTTPRequestOperationTest.m */,
|
||||
);
|
||||
name = Network;
|
||||
path = Logic/Network;
|
||||
@@ -2353,6 +2357,7 @@
|
||||
2546A95816628EDD0078E044 /* RKConnectionDescriptionTest.m in Sources */,
|
||||
2543A25D1664FD3100821D5B /* RKResponseDescriptorTest.m in Sources */,
|
||||
2536D1FD167270F100DF9BB0 /* RKRouterTest.m in Sources */,
|
||||
2551338F167838590017E4B6 /* RKHTTPRequestOperationTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2502,6 +2507,7 @@
|
||||
2546A95916628EDD0078E044 /* RKConnectionDescriptionTest.m in Sources */,
|
||||
2543A25E1664FD3200821D5B /* RKResponseDescriptorTest.m in Sources */,
|
||||
2536D1FE167270F100DF9BB0 /* RKRouterTest.m in Sources */,
|
||||
25513390167838590017E4B6 /* RKHTTPRequestOperationTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
44
Tests/Logic/Network/RKHTTPRequestOperationTest.m
Normal file
44
Tests/Logic/Network/RKHTTPRequestOperationTest.m
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// RKHTTPRequestOperationTest.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 12/11/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKTestEnvironment.h"
|
||||
#import "RKHTTPRequestOperation.h"
|
||||
|
||||
@interface RKHTTPRequestOperationTest : SenTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RKHTTPRequestOperationTest
|
||||
|
||||
- (void)testThatLoadingAnUnexpectedContentTypeReturnsCorrectErrorMessage
|
||||
{
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/XML/channels.xml" relativeToURL:[RKTestFactory baseURL]]];
|
||||
RKHTTPRequestOperation *requestOperation = [[RKHTTPRequestOperation alloc] initWithRequest:request];
|
||||
requestOperation.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
|
||||
requestOperation.acceptableStatusCodes = [NSIndexSet indexSetWithIndex:200];
|
||||
[requestOperation start];
|
||||
[requestOperation waitUntilFinished];
|
||||
|
||||
expect(requestOperation.error).notTo.beNil();
|
||||
expect([requestOperation.error localizedDescription]).to.equal(@"Expected content type {(\n \"application/json\"\n)}, got application/xml");
|
||||
}
|
||||
|
||||
- (void)testThatLoadingAnUnexpectedStatusCodeReturnsCorrectErrorMessage
|
||||
{
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/503" relativeToURL:[RKTestFactory baseURL]]];
|
||||
RKHTTPRequestOperation *requestOperation = [[RKHTTPRequestOperation alloc] initWithRequest:request];
|
||||
requestOperation.acceptableContentTypes = [NSSet setWithObject:@"text/xml"];
|
||||
requestOperation.acceptableStatusCodes = [NSIndexSet indexSetWithIndex:200];
|
||||
[requestOperation start];
|
||||
[requestOperation waitUntilFinished];
|
||||
|
||||
expect(requestOperation.error).notTo.beNil();
|
||||
expect([requestOperation.error localizedDescription]).to.equal(@"Expected status code in (200), got 503");
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -334,7 +334,6 @@
|
||||
|
||||
- (void)testMappingResponseWithDynamicMatchForResponseDescriptorPathPattern
|
||||
{
|
||||
|
||||
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
||||
[userMapping addAttributeMappingsFromArray:@[@"firstname"]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping pathPattern:@"/JSON/:name\\.json" keyPath:@"data.STUser" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
|
||||
@@ -545,4 +544,34 @@
|
||||
expect(user.email).to.equal(@"blake@restkit.org");
|
||||
}
|
||||
|
||||
- (void)testThatLoadingAnUnexpectedContentTypeReturnsCorrectErrorMessage
|
||||
{
|
||||
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
||||
[userMapping addAttributeMappingsFromArray:@[@"firstname"]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping pathPattern:@"/JSON/ComplexNestedUser.json" keyPath:@"data.STUser" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
|
||||
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/XML/channels.xml" relativeToURL:[RKTestFactory baseURL]]];
|
||||
RKObjectRequestOperation *requestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[ responseDescriptor ]];
|
||||
[requestOperation start];
|
||||
[requestOperation waitUntilFinished];
|
||||
|
||||
expect(requestOperation.error).notTo.beNil();
|
||||
expect([requestOperation.error localizedDescription]).to.equal(@"Expected content type {(\n \"application/json\",\n \"application/x-www-form-urlencoded\"\n)}, got application/xml");
|
||||
}
|
||||
|
||||
- (void)testThatLoadingAnUnexpectedStatusCodeReturnsCorrectErrorMessage
|
||||
{
|
||||
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestComplexUser class]];
|
||||
[userMapping addAttributeMappingsFromArray:@[@"firstname"]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping pathPattern:@"/JSON/ComplexNestedUser.json" keyPath:@"data.STUser" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
|
||||
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/503" relativeToURL:[RKTestFactory baseURL]]];
|
||||
RKObjectRequestOperation *requestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[ responseDescriptor ]];
|
||||
[requestOperation start];
|
||||
[requestOperation waitUntilFinished];
|
||||
|
||||
expect(requestOperation.error).notTo.beNil();
|
||||
expect([requestOperation.error localizedDescription]).to.equal(@"Expected status code in (200-299,400-499), got 503");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user