Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Commit

Permalink
Merge branch 'experimental-http-client-callback-refactoring' into exp…
Browse files Browse the repository at this point in the history
…erimental-0.8
  • Loading branch information
mattt committed Nov 7, 2011
2 parents a3df2ce + a37cda1 commit 200512c
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 221 deletions.
58 changes: 15 additions & 43 deletions AFNetworking/AFHTTPClient.h
Expand Up @@ -125,20 +125,20 @@ typedef enum {
///----------------------------------

/**
Attempts to register a class conforming to the `AFHTTPClientOperation` protocol, adding it to a chain to automatically generate request operations from a URL request.
Attempts to register a subclass of `AFHTTPRequestOperation`, adding it to a chain to automatically generate request operations from a URL request.
@param The class conforming to the `AFHTTPClientOperation` protocol to register
@param The subclass of `AFHTTPRequestOperation` to register
@return `YES` if the registration is successful, `NO` otherwise. The only failure condition is if `operationClass` does not conform to the `AFHTTPCLientOperation` protocol.
@return `YES` if the registration is successful, `NO` otherwise. The only failure condition is if `operationClass` does is not a subclass of `AFHTTPRequestOperation`.
@discussion When `enqueueHTTPRequestOperationWithRequest:success:failure` is invoked, each registered class is consulted in turn to see if it can handle the specific request. The first class to return `YES` when sent a `canProcessRequest:` message is used to generate an operation using `HTTPRequestOperationWithRequest:success:failure:`. There is no guarantee that all registered classes will be consulted. Classes are consulted in the reverse order of their registration. Attempting to register an already-registered class will move it to the top of the chain.
@discussion When `enqueueHTTPRequestOperationWithRequest:success:failure` is invoked, each registered class is consulted in turn to see if it can handle the specific request. The first class to return `YES` when sent a `canProcessRequest:` message is used to create an operation using `initWithURLRequest:` and do `setCompletionBlockWithSuccess:failure:`. There is no guarantee that all registered classes will be consulted. Classes are consulted in the reverse order of their registration. Attempting to register an already-registered class will move it to the top of the list.
@see `AFHTTPClientOperation`
*/
- (BOOL)registerHTTPOperationClass:(Class)operationClass;

/**
Unregisteres the specified class conforming to the `AFHTTPClientOperation` protocol.
Unregisters the specified subclass of `AFHTTPRequestOperation`.
@param The class conforming to the `AFHTTPClientOperation` protocol to unregister
Expand Down Expand Up @@ -244,8 +244,8 @@ typedef enum {
@see `AFHTTPClientOperation`
*/
- (void)enqueueHTTPRequestOperationWithRequest:(NSURLRequest *)request
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure;
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
/**
Enqueues an `AFHTTPRequestOperation` to the HTTP client's operation queue.
Expand Down Expand Up @@ -281,8 +281,8 @@ typedef enum {
*/
- (void)getPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure;
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;

/**
Creates an `AFHTTPRequestOperation` with a `POST` request, and enqueues it to the HTTP client's operation queue.
Expand All @@ -296,8 +296,8 @@ typedef enum {
*/
- (void)postPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure;
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;

/**
Creates an `AFHTTPRequestOperation` with a `PUT` request, and enqueues it to the HTTP client's operation queue.
Expand All @@ -311,8 +311,8 @@ typedef enum {
*/
- (void)putPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure;
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;

/**
Creates an `AFHTTPRequestOperation` with a `DELETE` request, and enqueues it to the HTTP client's operation queue.
Expand All @@ -326,36 +326,8 @@ typedef enum {
*/
- (void)deletePath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure;
@end

#pragma mark -

/**
The `AFHTTPClientOperation` protocol defines the methods used for the automatic content parsing functionality of `AFHTTPClient`.
@see `AFHTTPClient -registerHTTPOperationClass:`
*/
@protocol AFHTTPClientOperation

/**
A Boolean value determining whether or not the class can process the specified request. For example, `AFJSONRequestOperation` may check to make sure the content type was `application/json` or the URL path extension was `.json`.
@param urlRequest The request that is determined to be supported or not supported for this class.
*/
+ (BOOL)canProcessRequest:(NSURLRequest *)urlRequest;

/**
Constructs and initializes an operation with success and failure callbacks.
@param urlRequest The request used by the operation connection.
@param success A block object to be executed when the operation finishes successfully. The block has no return value and takes a single argument, the response object from the request.
@param failure A block object to be executed when the operation finishes unsuccessfully. The block has no return value and takes two arguments: the response received from the server, and the error describing the network or parsing error that occurred.
*/
+ (id)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure;
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
@end

#pragma mark -
Expand Down
28 changes: 15 additions & 13 deletions AFNetworking/AFHTTPClient.m
Expand Up @@ -208,7 +208,7 @@ - (void)dealloc {
#pragma mark -

- (BOOL)registerHTTPOperationClass:(Class)operationClass {
if (![operationClass conformsToProtocol:@protocol(AFHTTPClientOperation)]) {
if (![operationClass isSubclassOfClass:[AFHTTPRequestOperation class]]) {
return NO;
}

Expand Down Expand Up @@ -325,22 +325,24 @@ - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
}

- (void)enqueueHTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
AFHTTPRequestOperation *operation = nil;
NSString *className = nil;
NSEnumerator *enumerator = [self.registeredHTTPOperationClassNames reverseObjectEnumerator];
while (!operation && (className = [enumerator nextObject])) {
Class class = NSClassFromString(className);
if (class && [class canProcessRequest:urlRequest]) {
operation = [class HTTPRequestOperationWithRequest:urlRequest success:success failure:failure];
operation = [[(AFHTTPRequestOperation *)[class alloc] initWithRequest:urlRequest] autorelease];
}
}

if (!operation) {
operation = [AFHTTPRequestOperation HTTPRequestOperationWithRequest:urlRequest success:success failure:failure];
operation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
}

[operation setCompletionBlockWithSuccess:success failure:failure];

[self enqueueHTTPRequestOperation:operation];
}
Expand All @@ -361,35 +363,35 @@ - (void)cancelHTTPOperationsWithMethod:(NSString *)method andURL:(NSURL *)url {

- (void)getPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSURLRequest *request = [self requestWithMethod:@"GET" path:path parameters:parameters];
[self enqueueHTTPRequestOperationWithRequest:request success:success failure:failure];
}

- (void)postPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSURLRequest *request = [self requestWithMethod:@"POST" path:path parameters:parameters];
[self enqueueHTTPRequestOperationWithRequest:request success:success failure:failure];
}

- (void)putPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSURLRequest *request = [self requestWithMethod:@"PUT" path:path parameters:parameters];
[self enqueueHTTPRequestOperationWithRequest:request success:success failure:failure];
}

- (void)deletePath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSURLRequest *request = [self requestWithMethod:@"DELETE" path:path parameters:parameters];
[self enqueueHTTPRequestOperationWithRequest:request success:success failure:failure];
Expand Down
20 changes: 18 additions & 2 deletions AFNetworking/AFHTTPRequestOperation.h
Expand Up @@ -22,12 +22,11 @@

#import <Foundation/Foundation.h>
#import "AFURLConnectionOperation.h"
#import "AFHTTPClient.h"

/**
`AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request.
*/
@interface AFHTTPRequestOperation : AFURLConnectionOperation <AFHTTPClientOperation> {
@interface AFHTTPRequestOperation : AFURLConnectionOperation {
@private
NSIndexSet *_acceptableStatusCodes;
NSSet *_acceptableContentTypes;
Expand Down Expand Up @@ -72,4 +71,21 @@
*/
@property (readonly) BOOL hasAcceptableContentType;

/**
A Boolean value determining whether or not the class can process the specified request. For example, `AFJSONRequestOperation` may check to make sure the content type was `application/json` or the URL path extension was `.json`.
@param urlRequest The request that is determined to be supported or not supported for this class.
*/
+ (BOOL)canProcessRequest:(NSURLRequest *)urlRequest;

///-----------------------------------------------------------
/// @name Setting Completion Block Success / Failure Callbacks
///-----------------------------------------------------------

/**
*/
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;

@end
50 changes: 25 additions & 25 deletions AFNetworking/AFHTTPRequestOperation.m
Expand Up @@ -23,14 +23,14 @@
#import "AFHTTPRequestOperation.h"

@interface AFHTTPRequestOperation ()
@property (readwrite, nonatomic, retain) NSError *error;
@property (readwrite, nonatomic, retain) NSError *HTTPError;
@property (readonly, nonatomic, assign) BOOL hasContent;
@end

@implementation AFHTTPRequestOperation
@synthesize acceptableStatusCodes = _acceptableStatusCodes;
@synthesize acceptableContentTypes = _acceptableContentTypes;
@synthesize error = _HTTPError;
@synthesize HTTPError = _HTTPError;

- (id)initWithRequest:(NSURLRequest *)request {
self = [super initWithRequest:request];
Expand All @@ -55,23 +55,27 @@ - (NSHTTPURLResponse *)response {
}

- (NSError *)error {
if (self.response) {
if (self.response && !self.HTTPError) {
if (![self hasAcceptableStatusCode]) {
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected status code %@, got %d", nil), self.acceptableStatusCodes, [self.response statusCode]] forKey:NSLocalizedDescriptionKey];
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];

self.error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo] autorelease];
self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo] autorelease];
} else if ([self hasContent] && ![self hasAcceptableContentType]) { // Don't invalidate content type if there is no content
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected content type %@, got %@", nil), self.acceptableContentTypes, [self.response MIMEType]] forKey:NSLocalizedDescriptionKey];
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];

self.error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo] autorelease];
self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo] autorelease];
}
}

return _HTTPError;
if (_HTTPError) {
return _HTTPError;
} else {
return [super error];
}
}

- (BOOL)hasContent {
Expand All @@ -86,38 +90,34 @@ - (BOOL)hasAcceptableContentType {
return !self.acceptableContentTypes || [self.acceptableContentTypes containsObject:[self.response MIMEType]];
}

#pragma mark - AFHTTPClientOperation

+ (BOOL)canProcessRequest:(NSURLRequest *)request {
return NO;
}

+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
AFHTTPRequestOperation *operation = [[[self alloc] initWithRequest:urlRequest] autorelease];
operation.completionBlock = ^ {
if ([operation isCancelled]) {
self.completionBlock = ^ {
if ([self isCancelled]) {
return;
}

if (operation.error) {
if (self.error) {
if (failure) {
dispatch_async(dispatch_get_main_queue(), ^(void) {
failure(operation.response, operation.error);
failure(self, self.error);
});
}
} else {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^(void) {
success(operation.responseData);
dispatch_async(dispatch_get_main_queue(), ^{
success(self, self.responseData);
});
}
}
};

return operation;
}
}

#pragma mark - AFHTTPClientOperation

+ (BOOL)canProcessRequest:(NSURLRequest *)request {
return YES;
}

@end
4 changes: 2 additions & 2 deletions AFNetworking/AFJSONRequestOperation.h
Expand Up @@ -62,6 +62,6 @@
@return A new JSON request operation
*/
+ (AFJSONRequestOperation *)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success
failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure;
success:(void (^)(NSURLRequest *request, NSURLResponse *response, id JSON))success
failure:(void (^)(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON))failure;
@end

0 comments on commit 200512c

Please sign in to comment.