Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cancel-able requests #3

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions Source/Framework/MPOAuthAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ typedef enum {
@end

@class MPOAuthAuthenticationMethod;
@class MPOAuthAPIRequestLoader;

@interface MPOAuthAPI : NSObject <MPOAuthAPIInternalClient> {
@private
Expand All @@ -69,15 +70,15 @@ typedef enum {
- (id)initWithCredentials:(NSDictionary *)inCredentials authenticationURL:(NSURL *)inAuthURL andBaseURL:(NSURL *)inBaseURL autoStart:(BOOL)aFlag;
- (id)initWithCredentials:(NSDictionary *)inCredentials withConfiguration:(NSDictionary *)inConfiguration autoStart:(BOOL)aFlag;

- (void)authenticate;
- (void)beginAuthentication;
- (BOOL)isAuthenticated;

- (void)performMethod:(NSString *)inMethod withTarget:(id)inTarget andAction:(SEL)inAction;
- (void)performMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction;
- (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction;
- (void)performPOSTMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction;
- (void)performPOSTMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction;
- (void)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andAction:(SEL)inAction;
- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod withTarget:(id)inTarget andAction:(SEL)inAction;
- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction;
- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction;
- (MPOAuthAPIRequestLoader*)performPOSTMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction;
- (MPOAuthAPIRequestLoader*)performPOSTMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction;
- (MPOAuthAPIRequestLoader*)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andAction:(SEL)inAction;

- (NSData *)dataForMethod:(NSString *)inMethod;
- (NSData *)dataForMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters;
Expand Down
42 changes: 23 additions & 19 deletions Source/Framework/MPOAuthAPI.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ @interface MPOAuthAPI ()
@property (nonatomic, readwrite, retain) NSMutableArray *activeLoaders;
@property (nonatomic, readwrite, assign) MPOAuthAuthenticationState authenticationState;

- (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction usingHTTPMethod:(NSString *)inHTTPMethod;
- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction usingHTTPMethod:(NSString *)inHTTPMethod;
@end

@implementation MPOAuthAPI
Expand All @@ -53,7 +53,7 @@ - (id)initWithCredentials:(NSDictionary *)inCredentials authenticationURL:(NSURL
}

- (id)initWithCredentials:(NSDictionary *)inCredentials authenticationURL:(NSURL *)inAuthURL andBaseURL:(NSURL *)inBaseURL autoStart:(BOOL)aFlag {
if (self = [super init]) {
if ((self = [super init])) {
self.authenticationURL = inAuthURL;
self.baseURL = inBaseURL;
self.authenticationState = MPOAuthAuthenticationStateUnauthenticated;
Expand All @@ -64,14 +64,14 @@ - (id)initWithCredentials:(NSDictionary *)inCredentials authenticationURL:(NSURL
activeLoaders_ = [[NSMutableArray alloc] initWithCapacity:10];

if (aFlag) {
[self authenticate];
[self beginAuthentication];
}
}
return self;
}

- (id)initWithCredentials:(NSDictionary *)inCredentials withConfiguration:(NSDictionary *)inConfiguration autoStart:(BOOL)aFlag {
if (self = [super init]) {
if ((self = [super init])) {
self.authenticationURL = [inConfiguration valueForKey:MPOAuthAuthenticationURLKey];
self.baseURL = [inConfiguration valueForKey:MPOAuthBaseURLKey];
self.authenticationState = MPOAuthAuthenticationStateUnauthenticated;
Expand All @@ -82,7 +82,7 @@ - (id)initWithCredentials:(NSDictionary *)inCredentials withConfiguration:(NSDic
activeLoaders_ = [[NSMutableArray alloc] initWithCapacity:10];

if (aFlag) {
[self authenticate];
[self beginAuthentication];
}
}
return self;
Expand Down Expand Up @@ -130,9 +130,9 @@ - (void)setSignatureScheme:(MPOAuthSignatureScheme)inScheme {

#pragma mark -

- (void)authenticate {
- (void)beginAuthentication {
NSAssert(credentials_.consumerKey, @"A Consumer Key is required for use of OAuth.");
[self.authenticationMethod authenticate];
[self.authenticationMethod beginAuthentication];
}

- (BOOL)isAuthenticated {
Expand All @@ -141,27 +141,27 @@ - (BOOL)isAuthenticated {

#pragma mark -

- (void)performMethod:(NSString *)inMethod withTarget:(id)inTarget andAction:(SEL)inAction {
[self performMethod:inMethod atURL:self.baseURL withParameters:nil withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"];
- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod withTarget:(id)inTarget andAction:(SEL)inAction {
return [self performMethod:inMethod atURL:self.baseURL withParameters:nil withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"];
}

- (void)performMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction {
[self performMethod:inMethod atURL:self.baseURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"];
- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction {
return [self performMethod:inMethod atURL:self.baseURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"];
}

- (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction {
[self performMethod:inMethod atURL:inURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"];
- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction {
return [self performMethod:inMethod atURL:inURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"];
}

- (void)performPOSTMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction {
[self performPOSTMethod:inMethod atURL:self.baseURL withParameters:inParameters withTarget:inTarget andAction:inAction];
- (MPOAuthAPIRequestLoader*)performPOSTMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction {
return [self performPOSTMethod:inMethod atURL:self.baseURL withParameters:inParameters withTarget:inTarget andAction:inAction];
}

- (void)performPOSTMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction {
[self performMethod:inMethod atURL:inURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"POST"];
- (MPOAuthAPIRequestLoader*)performPOSTMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction {
return [self performMethod:inMethod atURL:inURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"POST"];
}

- (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction usingHTTPMethod:(NSString *)inHTTPMethod {
- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction usingHTTPMethod:(NSString *)inHTTPMethod {
if (!inMethod && ![inURL path] && ![inURL query]) {
[NSException raise:@"MPOAuthNilMethodRequestException" format:@"Nil was passed as the method to be performed on %@", inURL];
}
Expand All @@ -180,9 +180,11 @@ - (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(

[loader release];
[aRequest release];

return loader;
}

- (void)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andAction:(SEL)inAction {
- (MPOAuthAPIRequestLoader*)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andAction:(SEL)inAction {
if (!inRequest && ![[inRequest URL] path] && ![[inRequest URL] query]) {
[NSException raise:@"MPOAuthNilMethodRequestException" format:@"Nil was passed as the method to be performed on %@", inRequest];
}
Expand All @@ -199,6 +201,8 @@ - (void)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andA

[loader release];
[aRequest release];

return loader;
}

- (NSData *)dataForMethod:(NSString *)inMethod {
Expand Down
4 changes: 4 additions & 0 deletions Source/Framework/MPOAuthAPIRequestLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ extern NSString * const MPOAuthNotificationErrorHasOccurred;
@protocol MPOAuthCredentialStore;
@protocol MPOAuthParameterFactory;

@class MPOAuthConnection;
@class MPOAuthURLRequest;
@class MPOAuthURLResponse;
@class MPOAuthCredentialConcreteStore;

@interface MPOAuthAPIRequestLoader : NSObject {
MPOAuthCredentialConcreteStore *_credentials;
MPOAuthConnection *_connection;
MPOAuthURLRequest *_oauthRequest;
MPOAuthURLResponse *_oauthResponse;
NSMutableData *_dataBuffer;
Expand All @@ -46,5 +48,7 @@ extern NSString * const MPOAuthNotificationErrorHasOccurred;

- (void)loadSynchronously:(BOOL)inSynchronous;

- (void)cancel;

@end

149 changes: 78 additions & 71 deletions Source/Framework/MPOAuthAPIRequestLoader.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ @interface MPOAuthAPIRequestLoader ()
@property (nonatomic, readwrite, retain) NSData *data;
@property (nonatomic, readwrite, retain) NSString *responseString;

- (void)_interrogateResponseForOAuthData;
- (BOOL)_interrogateResponseForOAuthData;
@end

@protocol MPOAuthAPIInternalClient;
Expand All @@ -46,7 +46,7 @@ - (id)initWithURL:(NSURL *)inURL {
}

- (id)initWithRequest:(MPOAuthURLRequest *)inRequest {
if (self = [super init]) {
if ((self = [super init])) {
self.oauthRequest = inRequest;
_dataBuffer = [[NSMutableData alloc] init];
}
Expand Down Expand Up @@ -94,7 +94,7 @@ - (void)loadSynchronously:(BOOL)inSynchronous {
NSAssert(_credentials.consumerKey, @"Unable to load, credentials contain no consumer key");

if (!inSynchronous) {
[MPOAuthConnection connectionWithRequest:self.oauthRequest delegate:self credentials:self.credentials];
_connection = [MPOAuthConnection connectionWithRequest:self.oauthRequest delegate:self credentials:self.credentials];
} else {
MPOAuthURLResponse *theOAuthResponse = nil;
self.data = [MPOAuthConnection sendSynchronousRequest:self.oauthRequest usingCredentials:self.credentials returningResponse:&theOAuthResponse error:nil];
Expand All @@ -103,9 +103,17 @@ - (void)loadSynchronously:(BOOL)inSynchronous {
}
}

- (void)cancel {
if ( _connection ) {
[_connection cancel];
_connection = nil;
}
}

#pragma mark -

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
_connection = nil;
MPLog(@"%p: [%@ %@] %@, %@", self, NSStringFromClass([self class]), NSStringFromSelector(_cmd), connection, error);
if ([_target respondsToSelector:@selector(loader:didFailWithError:)]) {
[_target performSelector: @selector(loader:didFailWithError:) withObject: self withObject: error];
Expand All @@ -130,9 +138,10 @@ - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSUR
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
_connection = nil;
[self _interrogateResponseForOAuthData];

if (_action) {
if ( _action ) {
if ([_target conformsToProtocol:@protocol(MPOAuthAPIInternalClient)]) {
[_target performSelector:_action withObject:self withObject:self.data];
} else {
Expand All @@ -143,78 +152,76 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection {

#pragma mark -

- (void)_interrogateResponseForOAuthData {
- (BOOL)_interrogateResponseForOAuthData {
NSString *response = self.responseString;
NSDictionary *foundParameters = nil;
NSInteger status = [(NSHTTPURLResponse *)[self.oauthResponse urlResponse] statusCode];

if ([response length] > 5 && [[response substringToIndex:5] isEqualToString:@"oauth"]) {
foundParameters = [MPURLRequestParameter parameterDictionaryFromString:response];
self.oauthResponse.oauthParameters = foundParameters;

if (status == 401 || [foundParameters objectForKey:@"oauth_problem"]) {
NSString *aParameterValue = nil;
MPLog(@"oauthProblem = %@", foundParameters);

if ([foundParameters count] && (aParameterValue = [foundParameters objectForKey:@"oauth_problem"])) {
if ([aParameterValue isEqualToString:@"token_rejected"]) {
if (self.credentials.requestToken && !self.credentials.accessToken) {
[_credentials setRequestToken:nil];
[_credentials setRequestTokenSecret:nil];

[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationRequestTokenRejected
object:nil
userInfo:foundParameters];
} else if (self.credentials.accessToken && !self.credentials.requestToken) {
// your access token may be invalid due to a number of reasons so it's up to the
// user to decide whether or not to remove them
[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenRejected
object:nil
userInfo:foundParameters];

}
}

// something's messed up, so throw an error
[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationErrorHasOccurred
object:nil
userInfo:foundParameters];
}
} else if ([foundParameters objectForKey:@"oauth_token"]) {
NSString *aParameterValue = nil;
MPLog(@"foundParameters = %@", foundParameters);

if ([foundParameters count] && (aParameterValue = [foundParameters objectForKey:@"oauth_token"])) {
if (!self.credentials.requestToken && !self.credentials.accessToken) {
[_credentials setRequestToken:aParameterValue];
[_credentials setRequestTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]];

[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationRequestTokenReceived
object:nil
userInfo:foundParameters];

} else if (!self.credentials.accessToken && self.credentials.requestToken) {
[_credentials setRequestToken:nil];
[_credentials setRequestTokenSecret:nil];
[_credentials setAccessToken:aParameterValue];
[_credentials setAccessTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]];

[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenReceived
object:nil
userInfo:foundParameters];

} else if (self.credentials.accessToken && !self.credentials.requestToken) {
// replace the current token
[_credentials setAccessToken:aParameterValue];
[_credentials setAccessTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]];

[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenRefreshed
object:nil
userInfo:foundParameters];
}
}
}
if ([response length] > 5 && [[response substringToIndex:5] isEqualToString:@"oauth"]) {
foundParameters = [MPURLRequestParameter parameterDictionaryFromString:response];
self.oauthResponse.oauthParameters = foundParameters;
}

if ( status == 401 || ![foundParameters count] || [foundParameters objectForKey:@"oauth_problem"] ) {
NSString *aParameterValue = nil;
MPLog(@"oauthProblem = %@", foundParameters);

if ( status == 401 || ([foundParameters count] && (aParameterValue = [foundParameters objectForKey:@"oauth_problem"])) ) {
if ( !aParameterValue || [aParameterValue isEqualToString:@"token_rejected"]) {
[_credentials setRequestToken:nil];
[_credentials setRequestTokenSecret:nil];

[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationRequestTokenRejected
object:nil
userInfo:foundParameters];
}
return NO;
}

// something's messed up, so throw an error
[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationErrorHasOccurred
object:nil
userInfo:foundParameters];
return NO;
}

if ( foundParameters && [foundParameters objectForKey:@"oauth_token"]) {
NSString *aParameterValue = nil;
MPLog(@"foundParameters = %@", foundParameters);

if ([foundParameters count] && (aParameterValue = [foundParameters objectForKey:@"oauth_token"])) {
if (!self.credentials.requestToken && !self.credentials.accessToken) {
[_credentials setRequestToken:aParameterValue];
[_credentials setRequestTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]];

[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationRequestTokenReceived
object:nil
userInfo:foundParameters];

} else if (!self.credentials.accessToken && self.credentials.requestToken) {
[_credentials setRequestToken:nil];
[_credentials setRequestTokenSecret:nil];
[_credentials setAccessToken:aParameterValue];
[_credentials setAccessTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]];

[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenReceived
object:nil
userInfo:foundParameters];

} else if (self.credentials.accessToken && !self.credentials.requestToken) {
// replace the current token
[_credentials setAccessToken:aParameterValue];
[_credentials setAccessTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]];

[[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenRefreshed
object:nil
userInfo:foundParameters];
}
return YES;
}
}

return NO;
}

@end
8 changes: 7 additions & 1 deletion Source/Framework/MPOAuthAuthenticationMethod.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@

extern NSString * const MPOAuthAccessTokenURLKey;

extern NSString * const MPOAuthAuthenticationErrorDomain;

enum {
MPOAuthAuthenticationErrorUnknown
};

@class MPOAuthAPI;

@interface MPOAuthAuthenticationMethod : NSObject {
Expand All @@ -23,7 +29,7 @@ extern NSString * const MPOAuthAccessTokenURLKey;

- (id)initWithAPI:(MPOAuthAPI *)inAPI forURL:(NSURL *)inURL;
- (id)initWithAPI:(MPOAuthAPI *)inAPI forURL:(NSURL *)inURL withConfiguration:(NSDictionary *)inConfig;
- (void)authenticate;
- (void)beginAuthentication;

- (void)setTokenRefreshInterval:(NSTimeInterval)inTimeInterval;
- (void)refreshAccessToken;
Expand Down
Loading